/* Copyright 2026 Element Creations Ltd. SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE files in the repository root for full details. */ /// import { defineConfig } from "vitest/config"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { storybookTest } from "@storybook/addon-vitest/vitest-plugin"; import { storybookVis } from "storybook-addon-vis/vitest-plugin"; import { playwright } from "@vitest/browser-playwright"; import { nodePolyfills } from "vite-plugin-node-polyfills"; import { InlineConfig } from "vite"; import { Reporter } from "vitest/reporters"; import { env } from "process"; import { BrowserContextOptions } from "playwright-core"; const dirname = typeof __dirname !== "undefined" ? __dirname : path.dirname(fileURLToPath(import.meta.url)); const reporters: NonNullable["reporters"] = [["default"]]; const slowTestReporter: Reporter = { onTestRunEnd(testModules, unhandledErrors, reason) { const tests = testModules .flatMap((m) => Array.from(m.children.allTests())) .filter((test) => test.diagnostic()?.slow); tests.sort((x, y) => x.diagnostic()?.duration! - y.diagnostic()?.duration!); tests.reverse(); if (tests.length > 0) { console.warn("Slowest 10 tests:"); } for (const t of tests.slice(0, 10)) { console.warn(`${t.module.moduleId} > ${t.fullName}: ${t.diagnostic()?.duration.toFixed(0)}ms`); } }, }; // if we're running under GHA, enable the GHA & Sonar reporters if (env["GITHUB_ACTIONS"] !== undefined) { reporters.push([ "github-actions", { silent: false, }, ]); reporters.push([ "vitest-sonar-reporter", { outputFile: "coverage/sonar-report.xml", onWritePath: (path) => `packages/shared-components/${path}`, }, ]); // if we're running against the develop branch, also enable the slow test reporter if (env["GITHUB_REF"] == "refs/heads/develop") { reporters.push(slowTestReporter); } } const commonContextOptions: Omit = { reducedMotion: "reduce", // Force consistent font rendering colorScheme: "light", // Disable font smoothing for consistent rendering deviceScaleFactor: 1, }; const commonLaunchOptions = { // Options to try to make font rendering more consistent args: ["--font-render-hinting=none", "--disable-font-subpixel-positioning", "--disable-lcd-text"], }; export default defineConfig({ test: { coverage: { provider: "v8", include: ["src/**/*.{ts,tsx}"], exclude: ["src/**/*.stories.tsx"], reporter: [["lcov", { projectRoot: "../../" }]], }, reporters, globals: false, pool: "threads", projects: [ { extends: true, plugins: [ // The plugin will run tests for the stories defined in your Storybook config // See options at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon#storybooktest storybookTest({ configDir: path.join(dirname, ".storybook"), storybookScript: "storybook --ci", tags: { exclude: ["skip-test"], }, }), storybookVis({ // 3px of difference allowed before marking as failed failureThreshold: 3, // When running in CI=1 mode, set the platform to `linux` as that is the platform where the browser-in-docker is running snapshotRootDir: ({ ci, platform }) => `__vis__/${ci ? "linux" : platform}`, }), ], test: { name: "storybook", browser: { enabled: true, headless: true, provider: playwright({ contextOptions: commonContextOptions, launchOptions: process.env.PW_TEST_CONNECT_WS_ENDPOINT ? undefined : commonLaunchOptions, connectOptions: process.env.PW_TEST_CONNECT_WS_ENDPOINT ? { wsEndpoint: process.env.PW_TEST_CONNECT_WS_ENDPOINT, exposeNetwork: "", headers: { "x-playwright-launch-options": JSON.stringify(commonLaunchOptions), }, } : undefined, }), instances: [{ browser: "chromium" }], }, setupFiles: [".storybook/vitest.setup.ts"], }, }, { extends: true, plugins: [nodePolyfills({ include: ["util"], globals: { global: false } })], test: { name: "unit", browser: { enabled: true, headless: true, provider: playwright({ // These tests don't actually take screenshots (at least at time of writing) // but let's pass these options everywhere for consistency contextOptions: commonContextOptions, launchOptions: commonLaunchOptions, }), instances: [{ browser: "chromium" }], }, setupFiles: ["src/test/setupTests.ts"], }, css: { modules: { // Stabilise snapshots by stripping the hash component of the CSS module class name generateScopedName: (name) => name, }, }, }, ], }, optimizeDeps: { include: ["vite-plugin-node-polyfills/shims/buffer", "vite-plugin-node-polyfills/shims/process"], }, resolve: { alias: { "@test-utils": path.resolve(__dirname, "./src/test/utils/index.tsx"), }, }, });