test: migrate e2e to Playwright and component test to Vitest browser mode

Replace Cypress with Playwright for the end-to-end suite and drop
@shellygo/cypress-test-utils in favour of a hand-written MaputnikDriver
page object that keeps the fluent then(...).shouldX() assertion style
(now async). The InputAutocomplete component test moves to Vitest browser
mode using the Playwright provider.

- e2e/maputnik-driver.ts: driver + MaputnikAssertable over Playwright
- e2e/{fixtures,coverage,global-setup,global-teardown}.ts: test fixture,
  istanbul coverage collection, and nyc report generation
- playwright.config.ts / vitest.config.ts
- Code coverage preserved: dev server is istanbul-instrumented, per-test
  window.__coverage__ is merged via nyc into coverage/coverage-final.json
- CI: Cypress jobs replaced with Playwright; docker e2e runs against the
  container via E2E_NO_WEBSERVER
- Remove Cypress deps, config and support files; update docs and .nycrc

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
HarelM
2026-07-08 12:42:32 +03:00
parent f7b48139a4
commit c3dd253737
33 changed files with 1908 additions and 3879 deletions
+40 -35
View File
@@ -1,41 +1,46 @@
import { defineConfig } from "cypress";
import { createRequire } from "module";
const require = createRequire(import.meta.url);
import { defineConfig, devices } from "@playwright/test";
const isCI = !!process.env.CI;
// When the app is already served elsewhere (e.g. the docker e2e job) set
// E2E_NO_WEBSERVER=1 so Playwright does not start its own dev server.
const useExternalServer = !!process.env.E2E_NO_WEBSERVER;
const baseURL = process.env.E2E_BASE_URL ?? "http://localhost:8888/";
export default defineConfig({
env: {
codeCoverage: {
exclude: "cypress/**/*.*",
},
testDir: "./e2e",
testMatch: "**/*.spec.ts",
globalSetup: "./e2e/global-setup.ts",
globalTeardown: "./e2e/global-teardown.ts",
fullyParallel: true,
forbidOnly: isCI,
retries: isCI ? 2 : 0,
reporter: isCI ? [["list"], ["html", { open: "never" }]] : "list",
use: {
baseURL,
trace: "on-first-retry",
},
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
require("@cypress/code-coverage/task")(on, config);
on("before:browser:launch", (browser, launchOptions) => {
if (browser.family !== "chromium") {
return;
}
launchOptions.args.push("--disable-gpu");
launchOptions.args.push("--enable-features=AllowSwiftShaderFallback,AllowSoftwareGLFallbackDueToCrashes");
launchOptions.args.push("--enable-unsafe-swiftshader");
return launchOptions;
});
return config;
projects: [
{
name: "chromium",
use: {
...devices["Desktop Chrome"],
launchOptions: {
// Allow WebGL (maplibre) to fall back to software rendering in headless.
args: [
"--disable-gpu",
"--enable-features=AllowSwiftShaderFallback,AllowSoftwareGLFallbackDueToCrashes",
"--enable-unsafe-swiftshader",
],
},
},
},
baseUrl: "http://localhost:8888",
scrollBehavior: "center",
retries: {
runMode: 2,
openMode: 0,
],
webServer: useExternalServer
? undefined
: {
command: "npm run start",
url: "http://localhost:8888/maputnik/",
reuseExistingServer: !isCI,
timeout: 120000,
},
},
component: {
devServer: {
framework: "react",
bundler: "vite",
},
},
});