ui: run storybook tests with nix

This commit is contained in:
Glen Huang
2025-10-20 19:00:05 +08:00
parent c638df8ed9
commit 2d7e659953
6 changed files with 72 additions and 112 deletions

View File

@@ -12,7 +12,7 @@
fetchzip, fetchzip,
process-compose, process-compose,
json2ts, json2ts,
playwright-driver, playwright,
luakit, luakit,
self', self',
}: }:
@@ -108,32 +108,23 @@ mkShell {
export PC_CONFIG_FILES="$CLAN_CORE_PATH/pkgs/clan-app/process-compose.yaml" export PC_CONFIG_FILES="$CLAN_CORE_PATH/pkgs/clan-app/process-compose.yaml"
echo -e "${GREEN}To launch a qemu VM for testing, run:\n start-vm <number of VMs>${NC}" echo -e "${GREEN}To launch a qemu VM for testing, run:\n start-vm <number of VMs>${NC}"
''
+
# todo darwin support needs some work
(lib.optionalString stdenv.hostPlatform.isLinux ''
# configure playwright for storybook snapshot testing
# we only want webkit as that matches what the app is rendered with
export PLAYWRIGHT_BROWSERS_PATH=${ # configure playwright for storybook snapshot testing
playwright-driver.browsers.override { # we only want webkit as that matches what the app is rendered with
withFfmpeg = false;
withFirefox = false; export PLAYWRIGHT_BROWSERS_PATH=${
withWebkit = true; playwright.browsers.override {
withChromium = false; withFfmpeg = false;
withChromiumHeadlessShell = true; withFirefox = false;
} withWebkit = true;
withChromium = false;
withChromiumHeadlessShell = false;
} }
}
# stop playwright from trying to validate it has downloaded the necessary browsers # stop playwright from trying to validate it has downloaded the necessary browsers
# we are providing them manually via nix # we are providing them manually via nix
export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true
'';
# playwright browser drivers are versioned e.g. webkit-2191
# this helps us avoid having to update the playwright js dependency everytime we update nixpkgs and vice versa
# see vitest.config.js for corresponding launch configuration
export PLAYWRIGHT_CHROMIUM_EXECUTABLE=$(find -L "$PLAYWRIGHT_BROWSERS_PATH" -type f -name "headless_shell")
'');
} }

View File

@@ -35,7 +35,7 @@ buildNpmPackage (finalAttrs: {
# Something about passing orientation in any of the Form stories is causing the browser to crash # Something about passing orientation in any of the Form stories is causing the browser to crash
# `npm run test-storybook-static` works fine in the devshell # `npm run test-storybook-static` works fine in the devshell
passthru = rec { passthru = {
storybook = buildNpmPackage { storybook = buildNpmPackage {
pname = "${finalAttrs.pname}-storybook"; pname = "${finalAttrs.pname}-storybook";
inherit (finalAttrs) inherit (finalAttrs)
@@ -50,22 +50,18 @@ buildNpmPackage (finalAttrs: {
ps ps
]; ];
npmBuildScript = "test-storybook-static"; npmBuildScript = "test-storybook";
env = { env = {
PLAYWRIGHT_BROWSERS_PATH = "${playwright-driver.browsers.override { PLAYWRIGHT_BROWSERS_PATH = "${playwright-driver.browsers.override {
withChromiumHeadlessShell = true; withFfmpeg = false;
withFirefox = false;
withWebkit = true;
withChromium = false;
withChromiumHeadlessShell = false;
}}"; }}";
PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = true; PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = true;
}; };
preBuild = finalAttrs.preBuild + ''
export PLAYWRIGHT_CHROMIUM_EXECUTABLE=$(find -L "$PLAYWRIGHT_BROWSERS_PATH" -type f -name "headless_shell")
'';
postBuild = ''
mv storybook-static $out
'';
}; };
}; };
}) })

View File

@@ -55,7 +55,7 @@
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"knip": "^5.61.2", "knip": "^5.61.2",
"markdown-to-jsx": "^7.7.10", "markdown-to-jsx": "^7.7.10",
"playwright": "~1.55.1", "playwright": "1.54.1",
"postcss": "^8.4.38", "postcss": "^8.4.38",
"postcss-url": "^10.1.3", "postcss-url": "^10.1.3",
"prettier": "^3.2.5", "prettier": "^3.2.5",
@@ -7292,13 +7292,13 @@
} }
}, },
"node_modules/playwright": { "node_modules/playwright": {
"version": "1.55.1", "version": "1.54.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.1.tgz", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.1.tgz",
"integrity": "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==", "integrity": "sha512-peWpSwIBmSLi6aW2auvrUtf2DqY16YYcCMO8rTVx486jKmDTJg7UAhyrraP98GB8BoPURZP8+nxO7TSd4cPr5g==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.55.1" "playwright-core": "1.54.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@@ -7311,9 +7311,9 @@
} }
}, },
"node_modules/playwright-core": { "node_modules/playwright-core": {
"version": "1.55.1", "version": "1.54.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.1.tgz", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.1.tgz",
"integrity": "sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==", "integrity": "sha512-Nbjs2zjj0htNhzgiy5wu+3w09YetDx5pkrpI/kZotDlDUaYk0HVA5xrBVPdow4SAUIlhgKcJeJg4GRKW6xHusA==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {

View File

@@ -14,11 +14,9 @@
"vite": "vite", "vite": "vite",
"storybook": "storybook", "storybook": "storybook",
"knip": "knip --fix", "knip": "knip --fix",
"storybook-build": "storybook build",
"storybook-dev": "storybook dev -p 6006", "storybook-dev": "storybook dev -p 6006",
"test-storybook": "vitest run --project storybook --reporter verbose", "test-storybook": "vitest run --project storybook --reporter verbose",
"test-storybook-update-snapshots": "vitest run --project storybook --update", "test-storybook-update-snapshots": "vitest run --project storybook --update"
"test-storybook-static": "npm run storybook-build && concurrently -k -s first -n 'SB,TEST' -c 'magenta,blue' 'http-server storybook-static -a 127.0.0.1 -p 6006 --silent' 'wait-on tcp:127.0.0.1:6006 && npm run test-storybook'"
}, },
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
@@ -50,7 +48,7 @@
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"knip": "^5.61.2", "knip": "^5.61.2",
"markdown-to-jsx": "^7.7.10", "markdown-to-jsx": "^7.7.10",
"playwright": "~1.55.1", "playwright": "1.54.1",
"postcss": "^8.4.38", "postcss": "^8.4.38",
"postcss-url": "^10.1.3", "postcss-url": "^10.1.3",
"prettier": "^3.2.5", "prettier": "^3.2.5",

View File

@@ -5,6 +5,8 @@ import solidSvg from "vite-plugin-solid-svg";
import { patchCssModules } from "vite-css-modules"; import { patchCssModules } from "vite-css-modules";
import path from "node:path"; import path from "node:path";
import { exec } from "child_process"; import { exec } from "child_process";
// @ts-expect-error the type is a bit funky, but it's working
import { storybookTest } from "@storybook/addon-vitest/vitest-plugin";
// watch also clan-cli to catch api changes // watch also clan-cli to catch api changes
const clanCliDir = path.resolve(__dirname, "../../clan-cli"); const clanCliDir = path.resolve(__dirname, "../../clan-cli");
@@ -12,7 +14,7 @@ const clanCliDir = path.resolve(__dirname, "../../clan-cli");
function regenPythonApiOnFileChange() { function regenPythonApiOnFileChange() {
return { return {
name: "run-python-script-on-change", name: "run-python-script-on-change",
handleHotUpdate({}) { handleHotUpdate() {
exec("reload-python-api.sh", (err, stdout, stderr) => { exec("reload-python-api.sh", (err, stdout, stderr) => {
if (err) { if (err) {
console.error(`reload-python-api.sh error:\n${stderr}`); console.error(`reload-python-api.sh error:\n${stderr}`);
@@ -67,4 +69,40 @@ export default defineConfig({
}, },
// assetsInlineLimit: 0, // assetsInlineLimit: 0,
}, },
test: {
projects: [
{
test: {
name: "unit",
},
},
{
extends: path.resolve(__dirname, "vite.config.ts"),
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.resolve(__dirname, ".storybook"),
}),
],
test: {
name: "storybook",
browser: {
// Enable browser-based testing for UI components
enabled: true,
headless: true,
provider: "playwright",
instances: [
{
browser: "webkit",
},
],
},
// This setup file applies Storybook project annotations for Vitest
// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
setupFiles: [".storybook/vitest.setup.ts"],
},
},
],
},
}); });

View File

@@ -1,63 +0,0 @@
import path from "node:path";
import { fileURLToPath } from "node:url";
import solid from "vite-plugin-solid";
import { defineConfig, mergeConfig } from "vitest/config";
// @ts-expect-error the type is a bit funky, but it's working
import { storybookTest } from "@storybook/addon-vitest/vitest-plugin";
const dirname =
typeof __dirname !== "undefined"
? __dirname
: path.dirname(fileURLToPath(import.meta.url));
import viteConfig from "./vite.config";
const browser = process.env.BROWSER || "chromium";
export default mergeConfig(
viteConfig,
defineConfig({
plugins: [solid()],
test: {
projects: [
{
test: {
name: "unit",
},
},
{
extends: path.join(dirname, "vite.config.ts"),
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"),
}),
],
test: {
name: "storybook",
browser: {
// Enable browser-based testing for UI components
enabled: true,
headless: true,
provider: "playwright",
instances: [
{
browser: "chromium",
launch: {
// we specify this explicitly to avoid the version matching that playwright tries to do
executablePath: process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,
},
},
],
},
// This setup file applies Storybook project annotations for Vitest
// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
setupFiles: [".storybook/vitest.setup.ts"],
},
},
],
},
}),
);