webanvil 0.0.12 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,6 +25,7 @@ Table of contents
25
25
  - [A web app](#a-web-app)
26
26
  - [Storybook](#storybook)
27
27
  - [A Node project](#a-node-project)
28
+ - [Browser tests](#browser-tests)
28
29
  - [Configuration](#configuration)
29
30
  - [Tool selection](#tool-selection)
30
31
  - [Native tool configuration](#native-tool-configuration)
@@ -48,6 +49,7 @@ wa clean # remove tracked build output
48
49
  wa check # check formatting, linting, and types
49
50
  wa check --fix # format files and apply safe lint fixes before type checking
50
51
  wa test # run tests, watch them, collect coverage, or open the UI
52
+ wa e2e # build, preview, and run browser tests
51
53
  wa lint # lint files
52
54
  wa format # format files
53
55
  wa typecheck # type-check the project
@@ -64,6 +66,7 @@ What it includes
64
66
  | Tracked output cleanup | `wa clean` | WebAnvil |
65
67
  | Static checks | `wa check` | Oxfmt, Oxlint, TypeScript Native, or svelte-check |
66
68
  | Tests | `wa test` | Vitest |
69
+ | Browser tests | `wa e2e` | Playwright Test and Chromium |
67
70
  | Linting | `wa lint` | Oxlint |
68
71
  | Formatting | `wa format` | Oxfmt |
69
72
  | Type checking | `wa typecheck` | TypeScript Native or svelte-check |
@@ -95,6 +98,7 @@ Add the scripts you want to `package.json`:
95
98
  "clean": "wa clean",
96
99
  "check": "wa check",
97
100
  "test": "wa test",
101
+ "e2e": "wa e2e",
98
102
  "lint": "wa lint",
99
103
  "format": "wa format",
100
104
  "typecheck": "wa typecheck"
@@ -114,6 +118,7 @@ npm run build
114
118
  npm run clean
115
119
  npm run check
116
120
  npm run test
121
+ npm run e2e
117
122
  npm run lint
118
123
  npm run format
119
124
  npm run typecheck
@@ -335,16 +340,17 @@ preflights the engines it can dispatch before `webanvil.config.*` is loaded or
335
340
  its plugins are evaluated, so a declared command engine that is missing, has
336
341
  invalid package identity, or is outside the supported range fails first.
337
342
 
338
- | Tool | Supported project/workspace versions | Exact WebAnvil fallback |
339
- | -------------------------- | ------------------------------------ | ----------------------- |
340
- | Vite | `>=8.1.5 <9` | `8.1.5` |
341
- | Vitest | `>=4.1.10 <5` | `4.1.10` |
342
- | Storybook | `>=10.5.9 <11` | `10.5.9` |
343
- | Rolldown | `>=1.2.0 <2` | `1.2.0` |
344
- | Oxlint | `>=1.75.0 <2` | `1.75.0` |
345
- | Oxfmt | `>=0.60.0 <0.61` | `0.60.0` |
346
- | TypeScript (declarations) | `>=5 <7` | `6.0.3` |
347
- | TypeScript Native (`tsgo`) | `>=7.0.0-dev.20260707.2 <7.0.0` | `7.0.0-dev.20260707.2` |
343
+ | Tool | Supported project/workspace versions | Exact WebAnvil fallback |
344
+ | ---------------------------- | ------------------------------------ | ----------------------- |
345
+ | Vite | `>=8.1.5 <9` | `8.1.5` |
346
+ | Vitest | `>=4.1.10 <5` | `4.1.10` |
347
+ | Playwright Test and Chromium | Bundled only | `1.58.2` |
348
+ | Storybook | `>=10.5.9 <11` | `10.5.9` |
349
+ | Rolldown | `>=1.2.0 <2` | `1.2.0` |
350
+ | Oxlint | `>=1.75.0 <2` | `1.75.0` |
351
+ | Oxfmt | `>=0.60.0 <0.61` | `0.60.0` |
352
+ | TypeScript (declarations) | `>=5 <7` | `6.0.3` |
353
+ | TypeScript Native (`tsgo`) | `>=7.0.0-dev.20260707.2 <7.0.0` | `7.0.0-dev.20260707.2` |
348
354
 
349
355
  When a tool is first used, the CLI reports its package, version, and source, for
350
356
  example `Using rolldown 1.2.0 (project)` or
@@ -354,6 +360,9 @@ The TypeScript compiler is selected only after configuration enables a
354
360
  declaration build, but before Rolldown starts that build. It follows the same
355
361
  direct project/workspace declaration and exact-fallback rules.
356
362
 
363
+ `wa e2e` always uses WebAnvil's bundled Playwright Test and Chromium. This keeps
364
+ the runner and `webanvil/e2e` test API on the same version.
365
+
357
366
  ### Native tool configuration
358
367
 
359
368
  The `vite`, `test`, `rolldown`, `lint`, and `format` blocks use the owning
@@ -369,6 +378,10 @@ Precedence is:
369
378
  3. the matching native block in `webanvil.config.*`;
370
379
  4. WebAnvil defaults.
371
380
 
381
+ A `playwright.config.*` is different: it takes full control of `wa e2e`,
382
+ including the server lifecycle and browser configuration. WebAnvil still runs
383
+ its bundled Playwright Test binary.
384
+
372
385
  WebAnvil-owned `build`, `copy`, cross-engine `plugins`, and CLI behavior remain
373
386
  orchestration settings. `rolldown.input` and per-format `rolldown.output`
374
387
  options extend Node builds; WebAnvil still owns the input roots, output
@@ -494,6 +507,34 @@ These are run-specific modes; keep persistent Vitest configuration in
494
507
  `vitest.config.*`. `--ui-port` selects a strict loopback port and requires
495
508
  `--ui`.
496
509
 
510
+ ### Browser tests
511
+
512
+ `wa e2e` builds a web project, starts a production preview, and runs Playwright
513
+ Test files in `e2e/`. Import the test API from WebAnvil so the runner and test
514
+ code use the bundled matching version:
515
+
516
+ ```ts
517
+ import { expect, test } from "webanvil/e2e"
518
+
519
+ test("shows the home page", async ({ page }) => {
520
+ await page.goto("/")
521
+ await expect(page.getByRole("heading")).toBeVisible()
522
+ })
523
+ ```
524
+
525
+ The generated configuration provides a `chromium` project, so `wa e2e --project
526
+ chromium` works without a Playwright config. Use `--headed`, `--debug`, or `--ui`
527
+ for an interactive run. WebAnvil ships Playwright Test and Chromium, but the host
528
+ still needs the browser system libraries. On Linux CI, install them with:
529
+
530
+ ```sh
531
+ npx playwright install --with-deps chromium
532
+ ```
533
+
534
+ For advanced configuration, add `playwright.config.*`. WebAnvil then delegates
535
+ directly to Playwright and does not build or start a server. Configure
536
+ Playwright's `webServer` option in that file when the tests need one.
537
+
497
538
  ### Cleaning build output
498
539
 
499
540
  `wa build` records the actual emitted and copied files in
@@ -543,6 +584,7 @@ Command reference
543
584
  | `wa dev [entry]` | Starts Vite or a Node build watcher. A configured Storybook starts with the Node watcher. | `--mode`, `--out-dir`, `--host`, `--port`, `--copy`, `--bundle`, `--no-bundle`, `--formats`, `--declaration`, `--sourcemap`, `--minify`, `--platform`, `--target` |
544
585
  | `wa preview` | Serves a Vite production build or configured static Storybook output. | `--out-dir`, `--host`, `--port`, `--open` |
545
586
  | `wa test [filters...]` | Runs Vitest once, in watch mode, with coverage, or UI. | `--environment`, `--watch`, `--coverage`, `--ui`, `--ui-port` |
587
+ | `wa e2e [filters...]` | Builds, previews, and runs Playwright browser tests. Native Playwright configuration takes control. | `--host`, `--port`, `--ui`, `--headed`, `--debug`, `--project` |
546
588
  | `wa lint [paths...]` | Runs Oxlint and treats warnings as failures. | `--fix` |
547
589
  | `wa format [paths...]` | Formats with Oxfmt. | `--check` |
548
590
  | `wa typecheck [paths...]` | Type-checks with TypeScript Native. | No options |
@@ -17,6 +17,7 @@ import { playwright } from "@vitest/browser-playwright";
17
17
  import { storybookTest } from "@storybook/addon-vitest/vitest-plugin";
18
18
  import { consola } from "consola";
19
19
  import { randomUUID } from "node:crypto";
20
+ import { tmpdir } from "node:os";
20
21
  const entry = defineArgument({
21
22
  name: "entry",
22
23
  description: "Web entry or Node public root; unbundled Node builds emit its reachable graph with preserveModules."
@@ -103,6 +104,12 @@ const supportedTools = {
103
104
  packageName: "vitest",
104
105
  range: ">=4.1.10 <5"
105
106
  },
107
+ playwright: {
108
+ packageName: "@playwright/test",
109
+ range: ">=1.58.2 <2",
110
+ bin: "playwright",
111
+ allowProjectOverride: false
112
+ },
106
113
  storybook: {
107
114
  packageName: "storybook",
108
115
  range: ">=10.5.9 <11",
@@ -343,7 +350,7 @@ var Toolchain = class {
343
350
  }
344
351
  async #resolve(name) {
345
352
  const definition = supportedTools[name];
346
- const declaration = await findDeclaration(this.cwd, definition.packageName);
353
+ const declaration = definition.allowProjectOverride === false ? void 0 : await findDeclaration(this.cwd, definition.packageName);
347
354
  if (declaration !== void 0) return loadResolvedTool(name, definition, declaration.directory, "project");
348
355
  const webanvilPackageRoot = dirname$1(await findContainingManifest(fileURLToPath(import.meta.url)));
349
356
  return loadResolvedTool(name, definition, webanvilPackageRoot, "webanvil");
@@ -1255,6 +1262,11 @@ const declaration = defineOption({
1255
1262
  arity: 1,
1256
1263
  schema: z.enum(["true", "false"]).transform((value) => value === "true")
1257
1264
  });
1265
+ const debug = defineOption({
1266
+ name: "debug",
1267
+ description: "Run browser tests in Playwright debug mode.",
1268
+ arity: 0
1269
+ });
1258
1270
  const environment = defineOption({
1259
1271
  name: "environment",
1260
1272
  description: "Vitest environment to use for this run.",
@@ -1276,6 +1288,11 @@ const host = defineOption({
1276
1288
  description: "Host interface for the web server.",
1277
1289
  arity: 1
1278
1290
  });
1291
+ const headed = defineOption({
1292
+ name: "headed",
1293
+ description: "Run browser tests with a visible browser window.",
1294
+ arity: 0
1295
+ });
1279
1296
  const minify = defineOption({
1280
1297
  name: "minify",
1281
1298
  description: "Minify the build output: true or false.",
@@ -1308,6 +1325,12 @@ const platform = defineOption({
1308
1325
  "neutral"
1309
1326
  ])
1310
1327
  });
1328
+ const project = defineOption({
1329
+ name: "project",
1330
+ description: "Run one named Playwright project.",
1331
+ arity: 1,
1332
+ schema: z.string().min(1)
1333
+ });
1311
1334
  const port = defineOption({
1312
1335
  name: "port",
1313
1336
  description: "Port for the web server.",
@@ -1331,7 +1354,7 @@ const target = defineOption({
1331
1354
  });
1332
1355
  const ui = defineOption({
1333
1356
  name: "ui",
1334
- description: "Start the Vitest user interface.",
1357
+ description: "Start the test user interface.",
1335
1358
  arity: 0
1336
1359
  });
1337
1360
  const uiPort = defineOption({
@@ -1362,7 +1385,7 @@ const build = async (mode, entry, outDir, options = {}, plugins = [], viteConfig
1362
1385
  const rolldown = await useToolApi("rolldown", void 0, toolchain);
1363
1386
  await runNodeBuild(await createNodeBuildPlan(entry, outDir, options, resolveRolldownPlugins(plugins), rolldownConfig, toolchain), rolldown.rolldown);
1364
1387
  logger.success(`Built ${entry} to ${outDir}`);
1365
- return;
1388
+ return outDir;
1366
1389
  }
1367
1390
  const web = await build.webConfig(entry, outDir, options, plugins, viteConfig, toolchain, explicit);
1368
1391
  const target = web.outDir;
@@ -1379,6 +1402,7 @@ const build = async (mode, entry, outDir, options = {}, plugins = [], viteConfig
1379
1402
  ...copied
1380
1403
  ]);
1381
1404
  logger.success(`Built ${entry} to ${outDir}`);
1405
+ return target;
1382
1406
  };
1383
1407
  build.webConfig = async (entry, outDir, options, plugins, viteConfig = {}, toolchain = new Toolchain(process.cwd()), explicit = {}) => {
1384
1408
  assertSyntaxTarget(options.target);
@@ -1831,7 +1855,7 @@ var dev_default = defineCommand({
1831
1855
  return commandRun(toolchain)(arguments_, config);
1832
1856
  }
1833
1857
  });
1834
- const preview = async (outDir, host, port, useOutDir = false, waitForTermination = untilTerminated, openBrowser, viteConfig = {}) => {
1858
+ const startPreview = async (outDir, host, port, useOutDir = false, openBrowser, viteConfig = {}) => {
1835
1859
  logger.start("Starting web preview");
1836
1860
  const vite = await useToolApi("vite");
1837
1861
  const hasViteConfig = await hasToolConfig("vite");
@@ -1848,7 +1872,10 @@ const preview = async (outDir, host, port, useOutDir = false, waitForTermination
1848
1872
  ...openBrowser === void 0 ? {} : { open: openBrowser }
1849
1873
  }
1850
1874
  });
1851
- const server = await vite.preview(config);
1875
+ return vite.preview(config);
1876
+ };
1877
+ const preview = async (outDir, host, port, useOutDir = false, waitForTermination = untilTerminated, openBrowser, viteConfig = {}) => {
1878
+ const server = await startPreview(outDir, host, port, useOutDir, openBrowser, viteConfig);
1852
1879
  try {
1853
1880
  server.printUrls();
1854
1881
  await waitForTermination();
@@ -1872,6 +1899,94 @@ var preview_default = defineCommand({
1872
1899
  return preview(outDir ?? (storybook === void 0 ? config.build?.outDir ?? "dist" : storybookOutputDir(storybook)), host, port, outDir !== void 0 || storybook !== void 0, untilTerminated, open, config.vite);
1873
1900
  }
1874
1901
  });
1902
+ const localUrl = (server) => {
1903
+ const url = server.resolvedUrls?.local?.[0] ?? server.resolvedUrls?.network?.[0];
1904
+ if (url === void 0) throw new Error("WebAnvil could not determine the preview URL for browser tests");
1905
+ return url;
1906
+ };
1907
+ const argumentsFor = (filters, options, config, passWithNoTests = false) => [
1908
+ "test",
1909
+ ...config === void 0 ? [] : ["--config", config],
1910
+ ...filters,
1911
+ ...passWithNoTests ? ["--pass-with-no-tests"] : [],
1912
+ ...options.ui ? ["--ui"] : [],
1913
+ ...options.headed ? ["--headed"] : [],
1914
+ ...options.debug ? ["--debug"] : [],
1915
+ ...options.project === void 0 ? [] : ["--project", options.project]
1916
+ ];
1917
+ const defaultE2EConfig = (testDir, baseURL, outputDir) => ({
1918
+ outputDir,
1919
+ projects: [{
1920
+ name: "chromium",
1921
+ use: { browserName: "chromium" }
1922
+ }],
1923
+ testDir,
1924
+ use: { baseURL }
1925
+ });
1926
+ const defaultConfig = (testDir, baseURL, outputDir) => `${JSON.stringify(defaultE2EConfig(testDir, baseURL, outputDir), void 0, 4)}\n`;
1927
+ const runPlaywright = async (filters, options, config, baseURL, passWithNoTests = false) => {
1928
+ await execa(await useToolExecutable("playwright"), argumentsFor(filters, options, config, passWithNoTests), {
1929
+ cwd: process.cwd(),
1930
+ env: {
1931
+ ...process.env,
1932
+ ...baseURL === void 0 ? {} : { WEBANVIL_E2E_URL: baseURL },
1933
+ PLAYWRIGHT_TEST: "1"
1934
+ },
1935
+ stdio: "inherit"
1936
+ });
1937
+ };
1938
+ const e2e = async (filters, options = {}) => {
1939
+ logger.start("Running end-to-end tests");
1940
+ if (await hasToolConfig("playwright")) {
1941
+ await runPlaywright(filters, options);
1942
+ logger.success("End-to-end tests passed");
1943
+ return;
1944
+ }
1945
+ const { config } = await loadConfig();
1946
+ const effective = resolveEffectiveBuildConfig(config, {}, false);
1947
+ if (effective.mode !== "web") throw new Error("wa e2e requires build.mode: \"web\" or a native playwright.config.* file");
1948
+ const toolchain = new Toolchain(process.cwd());
1949
+ const server = await startPreview(await build(effective.mode, effective.entry, effective.outDir, effective, config.plugins ?? [], config.vite, config.rolldown, toolchain), options.host, options.port, true, false, config.vite);
1950
+ let directory;
1951
+ try {
1952
+ const baseURL = localUrl(server);
1953
+ directory = await mkdtemp(join$1(tmpdir(), "webanvil-playwright-"));
1954
+ const configPath = join$1(directory, "playwright.config.mjs");
1955
+ await writeFile(configPath, `export default ${defaultConfig(resolve$1(process.cwd(), "e2e"), baseURL, join$1(directory, "test-results"))}`);
1956
+ await runPlaywright(filters, options, configPath, baseURL, true);
1957
+ } finally {
1958
+ await Promise.all([server.close(), ...directory === void 0 ? [] : [rm(directory, {
1959
+ force: true,
1960
+ recursive: true
1961
+ })]]);
1962
+ }
1963
+ logger.success("End-to-end tests passed");
1964
+ };
1965
+ var e2e_default = defineCommand({
1966
+ name: "e2e",
1967
+ description: "Run end-to-end browser tests.",
1968
+ arguments: [filters],
1969
+ options: [
1970
+ host,
1971
+ port,
1972
+ ui,
1973
+ headed,
1974
+ debug,
1975
+ project
1976
+ ],
1977
+ run: async ({ filters, host, port, ui, headed, debug, project }) => {
1978
+ const nativePlaywrightConfig = await hasToolConfig("playwright");
1979
+ await Promise.all([useTool("playwright"), ...nativePlaywrightConfig ? [] : [useTool("vite")]]);
1980
+ return e2e(filters, {
1981
+ debug,
1982
+ headed,
1983
+ host,
1984
+ port,
1985
+ project,
1986
+ ui
1987
+ });
1988
+ }
1989
+ });
1875
1990
  const test = async (filters, config = {}, options = {}, waitForTermination = untilTerminated, storybook = {}) => {
1876
1991
  if (options.uiPort !== void 0 && options.ui !== true) throw new Error("--ui-port requires --ui");
1877
1992
  logger.start("Running tests");
@@ -1956,4 +2071,4 @@ var test_default = defineCommand({
1956
2071
  return runTest(arguments_);
1957
2072
  }
1958
2073
  });
1959
- export { build, build_default, bundle, check, checkProject, check_default, clean, clean_default, copy, coverage, declaration, dev, dev_default, entry, environment, filters, fix$1 as fix, format, format_default, formats, host, lint, lint_default, logger, minify, mode, open, outDir, paths, platform, port, preview, preview_default, sourcemap, target, test, test_default, typecheck, typecheck_default, ui, uiPort, watch };
2074
+ export { build, build_default, bundle, check, checkProject, check_default, clean, clean_default, copy, coverage, debug, declaration, dev, dev_default, e2e, e2e_default, entry, environment, filters, fix$1 as fix, format, format_default, formats, headed, host, lint, lint_default, logger, minify, mode, open, outDir, paths, platform, port, preview, preview_default, project, sourcemap, target, test, test_default, typecheck, typecheck_default, ui, uiPort, watch };
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { build_default, check_default, clean_default, dev_default, format_default, lint_default, logger, preview_default, test_default, typecheck_default } from "./_chunks/commands.mjs";
1
+ import { build_default, check_default, clean_default, dev_default, e2e_default, format_default, lint_default, logger, preview_default, test_default, typecheck_default } from "./_chunks/commands.mjs";
2
2
  import { execute } from "cmdore";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { readPackageJSON } from "pkg-types";
@@ -9,6 +9,7 @@ const main = async (...varargs) => {
9
9
  check_default,
10
10
  clean_default,
11
11
  dev_default,
12
+ e2e_default,
12
13
  format_default,
13
14
  lint_default,
14
15
  preview_default,
package/dist/e2e.d.mts ADDED
@@ -0,0 +1,2 @@
1
+ import { defineConfig, devices, expect, test } from "@playwright/test";
2
+ export { defineConfig, devices, expect, test };
package/dist/e2e.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import { defineConfig, devices, expect, test } from "@playwright/test";
2
+ export { defineConfig, devices, expect, test };
package/dist/index.d.mts CHANGED
@@ -35,7 +35,7 @@ declare const isUnpluginAdapter: (plugin: unknown) => plugin is UnpluginAdapter;
35
35
  declare const isWebAnvilPlugin: (plugin: unknown) => plugin is WebAnvilPlugin;
36
36
  declare const resolveRolldownPlugins: (plugins: WebAnvilPlugin[]) => Plugin[];
37
37
  declare const resolveVitePlugins: (plugins: WebAnvilPlugin[]) => PluginOption[];
38
- type ToolName = "vite" | "vitest" | "rolldown" | "oxlint" | "oxfmt" | "storybook" | "typescript" | "typescript-native";
38
+ type ToolName = "vite" | "vitest" | "playwright" | "rolldown" | "oxlint" | "oxfmt" | "storybook" | "typescript" | "typescript-native";
39
39
  type OptionalToolName = "svelte-check";
40
40
  type AnyToolName = ToolName | OptionalToolName;
41
41
  type ToolSource = "project" | "webanvil";
@@ -293,7 +293,7 @@ type WebBuild = {
293
293
  vite: ViteApi;
294
294
  };
295
295
  declare const build: {
296
- (mode: "web" | "node", entry: string, outDir: string, options?: BuildOptions, plugins?: WebAnvilPlugin[], viteConfig?: UserConfig$1, rolldownConfig?: RolldownConfig, toolchain?: Toolchain, explicit?: ExplicitWebBuild): Promise<void>;
296
+ (mode: "web" | "node", entry: string, outDir: string, options?: BuildOptions, plugins?: WebAnvilPlugin[], viteConfig?: UserConfig$1, rolldownConfig?: RolldownConfig, toolchain?: Toolchain, explicit?: ExplicitWebBuild): Promise<string>;
297
297
  webConfig(entry: string, outDir: string, options: BuildOptions, plugins: WebAnvilPlugin[], viteConfig?: UserConfig$1, toolchain?: Toolchain, explicit?: ExplicitWebBuild): Promise<WebBuild>;
298
298
  publicOutputFiles({ outDir, publicDir }: WebBuild): Promise<string[]>;
299
299
  web(web: WebBuild): Promise<string[]>;
@@ -379,7 +379,7 @@ type TypecheckOptions = {
379
379
  svelteCheck: ResolvedTool | undefined;
380
380
  };
381
381
  declare const typecheck: (paths: string[], options?: TypecheckOptions) => Promise<void>;
382
- declare const _default$8: import("cmdore").Command<readonly import("cmdore").Option[], readonly [{
382
+ declare const _default$9: import("cmdore").Command<readonly import("cmdore").Option[], readonly [{
383
383
  readonly name: "paths";
384
384
  readonly description: "Files or directories to check.";
385
385
  readonly variadic: true;
@@ -484,8 +484,48 @@ declare const _default$3: import("cmdore").Command<readonly [{
484
484
  readonly name: "entry";
485
485
  readonly description: "Web entry or Node public root; unbundled Node builds emit its reachable graph with preserveModules.";
486
486
  }]>;
487
- declare const format: (paths: string[], check?: boolean, config?: FormatConfig) => Promise<void>;
487
+ type E2EOptions = {
488
+ debug?: boolean;
489
+ headed?: boolean;
490
+ host?: string;
491
+ port?: number;
492
+ project?: string;
493
+ ui?: boolean;
494
+ };
495
+ declare const e2e: (filters: string[], options?: E2EOptions) => Promise<void>;
488
496
  declare const _default$4: import("cmdore").Command<readonly [{
497
+ readonly name: "host";
498
+ readonly description: "Host interface for the web server.";
499
+ readonly arity: 1;
500
+ }, {
501
+ readonly name: "port";
502
+ readonly description: "Port for the web server.";
503
+ readonly arity: 1;
504
+ readonly schema: import("zod").ZodCoercedNumber<unknown>;
505
+ }, {
506
+ readonly name: "ui";
507
+ readonly description: "Start the test user interface.";
508
+ readonly arity: 0;
509
+ }, {
510
+ readonly name: "headed";
511
+ readonly description: "Run browser tests with a visible browser window.";
512
+ readonly arity: 0;
513
+ }, {
514
+ readonly name: "debug";
515
+ readonly description: "Run browser tests in Playwright debug mode.";
516
+ readonly arity: 0;
517
+ }, {
518
+ readonly name: "project";
519
+ readonly description: "Run one named Playwright project.";
520
+ readonly arity: 1;
521
+ readonly schema: import("zod").ZodString;
522
+ }], readonly [{
523
+ readonly name: "filters";
524
+ readonly description: "Test files or names to run.";
525
+ readonly variadic: true;
526
+ }]>;
527
+ declare const format: (paths: string[], check?: boolean, config?: FormatConfig) => Promise<void>;
528
+ declare const _default$5: import("cmdore").Command<readonly [{
489
529
  readonly name: "check";
490
530
  readonly description: "Check formatting without writing files.";
491
531
  readonly arity: 0;
@@ -495,7 +535,7 @@ declare const _default$4: import("cmdore").Command<readonly [{
495
535
  readonly variadic: true;
496
536
  }]>;
497
537
  declare const lint: (paths: string[], fix?: boolean, config?: LintConfig) => Promise<void>;
498
- declare const _default$5: import("cmdore").Command<readonly [{
538
+ declare const _default$6: import("cmdore").Command<readonly [{
499
539
  readonly name: "fix";
500
540
  readonly description: "Apply safe lint fixes.";
501
541
  readonly arity: 0;
@@ -505,7 +545,7 @@ declare const _default$5: import("cmdore").Command<readonly [{
505
545
  readonly variadic: true;
506
546
  }]>;
507
547
  declare const preview: (outDir: string, host?: string, port?: number, useOutDir?: boolean, waitForTermination?: () => Promise<void>, openBrowser?: boolean, viteConfig?: UserConfig$1) => Promise<void>;
508
- declare const _default$6: import("cmdore").Command<readonly [{
548
+ declare const _default$7: import("cmdore").Command<readonly [{
509
549
  readonly name: "out-dir";
510
550
  readonly description: "Directory where the build output is written.";
511
551
  readonly arity: 1;
@@ -530,7 +570,7 @@ declare const test: (filters: string[], config?: TestConfig, options?: {
530
570
  uiPort?: number;
531
571
  watch?: boolean;
532
572
  }, waitForTermination?: () => Promise<void>, storybook?: StorybookConfig) => Promise<void>;
533
- declare const _default$7: import("cmdore").Command<readonly [{
573
+ declare const _default$8: import("cmdore").Command<readonly [{
534
574
  readonly name: "environment";
535
575
  readonly description: "Vitest environment to use for this run.";
536
576
  readonly arity: 1;
@@ -544,7 +584,7 @@ declare const _default$7: import("cmdore").Command<readonly [{
544
584
  readonly arity: 0;
545
585
  }, {
546
586
  readonly name: "ui";
547
- readonly description: "Start the Vitest user interface.";
587
+ readonly description: "Start the test user interface.";
548
588
  readonly arity: 0;
549
589
  }, {
550
590
  readonly name: "ui-port";
@@ -588,6 +628,11 @@ declare const declaration: {
588
628
  false: "false";
589
629
  }>, z.ZodTransform<boolean, "true" | "false">>;
590
630
  };
631
+ declare const debug: {
632
+ readonly name: "debug";
633
+ readonly description: "Run browser tests in Playwright debug mode.";
634
+ readonly arity: 0;
635
+ };
591
636
  declare const environment: {
592
637
  readonly name: "environment";
593
638
  readonly description: "Vitest environment to use for this run.";
@@ -612,6 +657,11 @@ declare const host: {
612
657
  readonly description: "Host interface for the web server.";
613
658
  readonly arity: 1;
614
659
  };
660
+ declare const headed: {
661
+ readonly name: "headed";
662
+ readonly description: "Run browser tests with a visible browser window.";
663
+ readonly arity: 0;
664
+ };
615
665
  declare const minify$1: {
616
666
  readonly name: "minify";
617
667
  readonly description: "Minify the build output: true or false.";
@@ -650,6 +700,12 @@ declare const platform$1: {
650
700
  neutral: "neutral";
651
701
  }>;
652
702
  };
703
+ declare const project: {
704
+ readonly name: "project";
705
+ readonly description: "Run one named Playwright project.";
706
+ readonly arity: 1;
707
+ readonly schema: z.ZodString;
708
+ };
653
709
  declare const port: {
654
710
  readonly name: "port";
655
711
  readonly description: "Port for the web server.";
@@ -673,7 +729,7 @@ declare const target$1: {
673
729
  };
674
730
  declare const ui: {
675
731
  readonly name: "ui";
676
- readonly description: "Start the Vitest user interface.";
732
+ readonly description: "Start the test user interface.";
677
733
  readonly arity: 0;
678
734
  };
679
735
  declare const uiPort: {
@@ -689,4 +745,4 @@ declare const watch: {
689
745
  };
690
746
  declare function defineConfig(config: UserConfig): UserConfig;
691
747
  declare function defineConfig(config: UserConfigFactory): UserConfigFactory;
692
- export { BuildConfig, ConfigExport, CopyMapping, FormatConfig, LintConfig, ResolvedConfig, RolldownConfig, StorybookConfig, SyntaxTarget, TestConfig, UnpluginAdapter, UserConfig, UserConfigFactory, ViteConfig, WebAnvilPlugin, WebAnvilUnplugin, assertSyntaxTarget, build, _default as buildCommand, buildConfigSchema, bundle$1 as bundle, check, _default$1 as checkCommand, checkProject, clean, _default$2 as cleanCommand, copy, copyMappingSchema, coverage, declaration, defaultConfig, defineConfig, definePlugin, dev, _default$3 as devCommand, effectiveUserConfigSchema, entry$1 as entry, environment, filters, fix, format, _default$4 as formatCommand, formatConfigSchema, formats$1 as formats, host, isUnpluginAdapter, isWebAnvilPlugin, lint, _default$5 as lintCommand, lintConfigSchema, loadConfig, minify$1 as minify, mode, open, outDir$1 as outDir, paths, platform$1 as platform, port, preview, _default$6 as previewCommand, resolveEffectiveBuildConfig, resolveRolldownPlugins, resolveVitePlugins, rolldownConfigSchema, sourcemap$1 as sourcemap, storybookConfigSchema, syntaxTargetSchema, target$1 as target, test, _default$7 as testCommand, testConfigSchema, typecheck, _default$8 as typecheckCommand, ui, uiPort, userConfigSchema, viteConfigSchema, watch, withConfig };
748
+ export { BuildConfig, ConfigExport, CopyMapping, FormatConfig, LintConfig, ResolvedConfig, RolldownConfig, StorybookConfig, SyntaxTarget, TestConfig, UnpluginAdapter, UserConfig, UserConfigFactory, ViteConfig, WebAnvilPlugin, WebAnvilUnplugin, assertSyntaxTarget, build, _default as buildCommand, buildConfigSchema, bundle$1 as bundle, check, _default$1 as checkCommand, checkProject, clean, _default$2 as cleanCommand, copy, copyMappingSchema, coverage, debug, declaration, defaultConfig, defineConfig, definePlugin, dev, _default$3 as devCommand, e2e, _default$4 as e2eCommand, effectiveUserConfigSchema, entry$1 as entry, environment, filters, fix, format, _default$5 as formatCommand, formatConfigSchema, formats$1 as formats, headed, host, isUnpluginAdapter, isWebAnvilPlugin, lint, _default$6 as lintCommand, lintConfigSchema, loadConfig, minify$1 as minify, mode, open, outDir$1 as outDir, paths, platform$1 as platform, port, preview, _default$7 as previewCommand, project, resolveEffectiveBuildConfig, resolveRolldownPlugins, resolveVitePlugins, rolldownConfigSchema, sourcemap$1 as sourcemap, storybookConfigSchema, syntaxTargetSchema, target$1 as target, test, _default$8 as testCommand, testConfigSchema, typecheck, _default$9 as typecheckCommand, ui, uiPort, userConfigSchema, viteConfigSchema, watch, withConfig };
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { build, build_default, bundle, check, checkProject, check_default, clean, clean_default, copy, coverage, declaration, dev, dev_default, entry, environment, filters, fix, format, format_default, formats, host, lint, lint_default, minify, mode, open, outDir, paths, platform, port, preview, preview_default, sourcemap, target, test, test_default, typecheck, typecheck_default, ui, uiPort, watch } from "./_chunks/commands.mjs";
1
+ import { build, build_default, bundle, check, checkProject, check_default, clean, clean_default, copy, coverage, debug, declaration, dev, dev_default, e2e, e2e_default, entry, environment, filters, fix, format, format_default, formats, headed, host, lint, lint_default, minify, mode, open, outDir, paths, platform, port, preview, preview_default, project, sourcemap, target, test, test_default, typecheck, typecheck_default, ui, uiPort, watch } from "./_chunks/commands.mjs";
2
2
  import { assertSyntaxTarget, buildConfigSchema, copyMappingSchema, defaultConfig, defineConfig as defineConfig$1, definePlugin, effectiveUserConfigSchema, formatConfigSchema, isUnpluginAdapter, isWebAnvilPlugin, lintConfigSchema, loadConfig, resolveEffectiveBuildConfig, resolveRolldownPlugins, resolveVitePlugins, rolldownConfigSchema, storybookConfigSchema, syntaxTargetSchema, testConfigSchema, userConfigSchema, viteConfigSchema, withConfig } from "./_chunks/config.mjs";
3
3
  function defineConfig(config) {
4
4
  return defineConfig$1(config);
5
5
  }
6
- export { assertSyntaxTarget, build, build_default as buildCommand, buildConfigSchema, bundle, check, check_default as checkCommand, checkProject, clean, clean_default as cleanCommand, copy, copyMappingSchema, coverage, declaration, defaultConfig, defineConfig, definePlugin, dev, dev_default as devCommand, effectiveUserConfigSchema, entry, environment, filters, fix, format, format_default as formatCommand, formatConfigSchema, formats, host, isUnpluginAdapter, isWebAnvilPlugin, lint, lint_default as lintCommand, lintConfigSchema, loadConfig, minify, mode, open, outDir, paths, platform, port, preview, preview_default as previewCommand, resolveEffectiveBuildConfig, resolveRolldownPlugins, resolveVitePlugins, rolldownConfigSchema, sourcemap, storybookConfigSchema, syntaxTargetSchema, target, test, test_default as testCommand, testConfigSchema, typecheck, typecheck_default as typecheckCommand, ui, uiPort, userConfigSchema, viteConfigSchema, watch, withConfig };
6
+ export { assertSyntaxTarget, build, build_default as buildCommand, buildConfigSchema, bundle, check, check_default as checkCommand, checkProject, clean, clean_default as cleanCommand, copy, copyMappingSchema, coverage, debug, declaration, defaultConfig, defineConfig, definePlugin, dev, dev_default as devCommand, e2e, e2e_default as e2eCommand, effectiveUserConfigSchema, entry, environment, filters, fix, format, format_default as formatCommand, formatConfigSchema, formats, headed, host, isUnpluginAdapter, isWebAnvilPlugin, lint, lint_default as lintCommand, lintConfigSchema, loadConfig, minify, mode, open, outDir, paths, platform, port, preview, preview_default as previewCommand, project, resolveEffectiveBuildConfig, resolveRolldownPlugins, resolveVitePlugins, rolldownConfigSchema, sourcemap, storybookConfigSchema, syntaxTargetSchema, target, test, test_default as testCommand, testConfigSchema, typecheck, typecheck_default as typecheckCommand, ui, uiPort, userConfigSchema, viteConfigSchema, watch, withConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webanvil",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "description": "A unified CLI for building, testing, linting, formatting, and type-checking JavaScript and TypeScript projects.",
5
5
  "keywords": [
6
6
  "build-tool",
@@ -41,6 +41,11 @@
41
41
  "import": "./dist/index.mjs",
42
42
  "default": "./dist/index.mjs"
43
43
  },
44
+ "./e2e": {
45
+ "types": "./dist/e2e.d.mts",
46
+ "import": "./dist/e2e.mjs",
47
+ "default": "./dist/e2e.mjs"
48
+ },
44
49
  "./storybook/test/preset": {
45
50
  "types": "./dist/storybook/test/preset.d.mts",
46
51
  "import": "./dist/storybook/test/preset.mjs",
@@ -106,6 +111,7 @@
106
111
  },
107
112
  "dependencies": {
108
113
  "@playwright/browser-chromium": "1.58.2",
114
+ "@playwright/test": "1.58.2",
109
115
  "@storybook/addon-vitest": "10.5.9",
110
116
  "@storybook/react-vite": "10.5.9",
111
117
  "@storybook/svelte-vite": "10.5.9",