trilium/packages/ckeditor5/vitest.config.ts
Elian Doran e8eeb68b50
test(ckeditor5): run browser mode on Playwright instead of webdriverio
Vitest 5 handed the webdriverio provider to community maintenance, and no
stable 5.x of `@vitest/browser-webdriverio` was ever published — npm `latest`
is still 4.1.11, with only a 5.0.0-rc.1 from before vitest 5.0.0 shipped.
Pairing that v4 provider with `@vitest/browser` 5 kills the suite at startup:

    TypeError: Cannot read properties of undefined (reading 'project')
        at createBrowserServer (@vitest/browser/dist/index.js:7900:26)

`@vitest/browser-playwright` 5.0.0 is stable and first-party, and Playwright
1.62.1 is already here for the e2e suites, so the browser toolchain costs
nothing new. Only two of the 129 specs touch provider-visible API at all, both
through the provider-agnostic `userEvent`.

Playwright drives the browser over CDP with no separate driver, so the
chromedriver half of the NixOS workaround goes away: the dev shell keeps
`pkgs.chromium` and `CHROME_BIN`, which now reaches the provider as
`launchOptions.executablePath`. CI installs the browser in a step of its own
rather than inside the test step, whose 15-minute cap exists to catch a browser
session that never starts and should not also have to cover a 190 MB download.

Two specs depended on webdriverio behaviour and are fixed rather than skipped:

- The token-cost assertion read `1.234` where it wanted `1,234`.
  `toLocaleString()` takes the browser's locale, and Playwright inherits the
  host's where the old Chrome defaulted to en-US. Pinning `contextOptions.locale`
  keeps the suite from depending on the developer's machine.
- The format painter's drag-selection selected nothing. Playwright's
  `dragAndDrop` turns on drag interception, so the press reaches the page as an
  HTML5 drag intent instead of selecting text. Driving the press, move and
  release over CDP restores what the test is actually for: proving a *native*
  pointer interaction has updated the model selection by the time the `mouseup`
  listener runs.

Vitest 5 also moved failure screenshots from `.vitest-attachments` to
`.vitest`, which needs ignoring.

Verified: 127 files / 1626 tests green, coverage 99.91/99.54/100/99.98 against
the 99.5 gate. The Nix path is unexercised — `executablePath` is ordinary
Playwright, but it was not run from a dev shell.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 23:19:52 +02:00

59 lines
2.8 KiB
TypeScript

import { resolve } from "node:path";
import { playwright } from "@vitest/browser-playwright";
import { defineConfig } from "vitest/config";
/**
* The browser to drive, when the one Playwright downloads for itself cannot run — on NixOS the
* bundled Chromium dies on a missing `libxcb.so.1`, since nothing outside the store provides it.
* Point `CHROME_BIN` at a system Chrome/Chromium and Playwright launches that instead. The Nix dev
* shell sets it.
*/
const systemChrome = process.env.CHROME_BIN;
export default defineConfig({
test: {
browser: {
enabled: true,
provider: playwright({
// Specs assert en-US number formatting (`toLocaleString()` renders 1,234 there and
// 1.234 under a European locale), so the host machine's locale must not decide.
contextOptions: { locale: "en-US" },
...(systemChrome ? { launchOptions: { executablePath: systemChrome } } : {})
}),
headless: true,
ui: false,
instances: [{ browser: "chromium" }]
},
include: ["src/**/*.spec.ts"],
setupFiles: ["./test/setup.ts"],
globals: true,
watch: false,
reporters: ["default", ["junit", { outputFile: "./test-output/vitest/junit.xml", addFileAttribute: true }]],
coverage: {
// 99.5 rather than 100: the suite is effectively fully covered, and the small
// remainder is unreachable defensive code that is cheaper to leave uncovered than to
// keep annotating. Raise it back if that residue is ever closed.
thresholds: {
lines: 99.5,
functions: 99.5,
branches: 99.5,
statements: 99.5
},
provider: "v8",
reportsDirectory: "./test-output/vitest/coverage",
// Restrict to this package's own sources. The aggregate imports the sibling
// @triliumnext/ckeditor5-* workspace packages, whose `src/` would otherwise bleed
// into this report; they carry their own 100% coverage gates in their own packages.
allowExternal: false,
include: ["src/**/*.{ts,tsx}"],
exclude: ["**/*.{test,spec}.{ts,mts,cts,tsx,js,jsx}", "**/*.d.ts", "**/node_modules/**", "**/ckeditor5-*/**"],
// Codecov resolves an lcov `SF:` path by matching it against the repo's file list, so
// the package-relative paths istanbul emits by default (`src/utils.ts`, relative to
// cwd) are ambiguous in this monorepo and get attributed to whichever package wins the
// match. Emit repo-root-relative paths instead.
reporter: ["text", ["lcov", { projectRoot: resolve(__dirname, "../..") }]]
}
}
});