@forgebook/testing 0.2.0 → 0.2.2

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
@@ -149,6 +149,9 @@ export default defineConfig({
149
149
  });
150
150
  ```
151
151
 
152
+ The plugin keeps a module that imports story files out of Vitest's module cache (`fsModuleCache`), as a group must be
153
+ listed anew on each run; every other module stays cached.
154
+
152
155
  `storyServerTests` also takes `wrap`: a second pass with every story inside a decorator (a provider with a partial
153
156
  translation catalogue), its HTML checked.
154
157
 
@@ -65,17 +65,18 @@ export const STORY_VARIANTS = storyVariants(DEFAULT_SWITCHES);
65
65
  /** A problem list's messages, so a failing test names each problem. */
66
66
  const messages = (problems) => problems.map((problem) => problem.message);
67
67
  /**
68
- * Runs the checks of one planned test on a shown story: axe, then for a story about its looks the spills, the
69
- * source's own check, and the overlays last (it resizes the window, which may close what the story left open). A story
70
- * about logic gets axe only.
68
+ * Runs the checks of one planned test on a shown story: axe (unless the catalogue checks no accessibility), then for a
69
+ * story about its looks the spills, the source's own check, and the overlays last (it resizes the window, which may
70
+ * close what the story left open). A story about logic gets axe only.
71
71
  *
72
72
  * @param page - the story's frame, ready.
73
73
  * @param planned - the story, its variant and whether its layout is checked.
74
- * @param a11y - the catalogue's accessibility rules.
74
+ * @param a11y - the catalogue's accessibility rules; none when it checks no accessibility (`a11y: false`).
75
75
  * @param check - the source's own check, if any.
76
76
  */
77
77
  const expectChecksPass = async (page, planned, a11y, check) => {
78
- expect(messages(await axeProblems(page, a11y))).toEqual([]);
78
+ if (a11y !== undefined)
79
+ expect(messages(await axeProblems(page, a11y))).toEqual([]);
79
80
  if (!planned.hasLookChecks)
80
81
  return;
81
82
  expect(messages(await spillProblems(page))).toEqual([]);
@@ -31,7 +31,7 @@ const checkedPage = async (address, open, a11y) => {
31
31
  return result([{ kind: "frame", message: `It answered ${response.status()}` }]);
32
32
  }
33
33
  return result([
34
- ...(await axeProblems(page, a11y)),
34
+ ...(a11y === undefined ? [] : await axeProblems(page, a11y)),
35
35
  ...(await spillProblems(page, "body")),
36
36
  ...(await focusProblems(page)),
37
37
  ...errorProblems(errors)
@@ -60,7 +60,7 @@ export const checkPages = async ({ addresses, lists }) => {
60
60
  for (const address of addresses) {
61
61
  results.push(await checkedPage(address, () => context.newPage(), a11y));
62
62
  }
63
- return { schema: 1, results };
63
+ return { schema: 1, results, ...(a11y === undefined ? { a11y: "off" } : {}) };
64
64
  }
65
65
  finally {
66
66
  await browser.close();
@@ -9,7 +9,7 @@ import { hasLookChecks } from "./storyTestPlan.js";
9
9
  *
10
10
  * @param page - a fresh page.
11
11
  * @param storyPage - the story and the view.
12
- * @param a11y - the catalogue's accessibility settings.
12
+ * @param a11y - the catalogue's accessibility settings; none when it checks no accessibility (`a11y: false`).
13
13
  */
14
14
  const checkedPage = async (page, storyPage, a11y, semantic) => {
15
15
  const errors = watchedErrors(page);
@@ -35,7 +35,7 @@ const checkedPage = async (page, storyPage, a11y, semantic) => {
35
35
  ...(await overlayProblems(page, isOverlayChecked(storyPage.view), storyPage.story.height))
36
36
  ]
37
37
  : [];
38
- const axe = await axeProblems(page, a11y);
38
+ const axe = a11y === undefined ? [] : await axeProblems(page, a11y);
39
39
  const checked = result([...axe, ...lookProblems, ...(await focusProblems(page)), ...errorProblems(errors)]);
40
40
  return semantic === undefined
41
41
  ? checked
@@ -50,5 +50,5 @@ const checkedPage = async (page, storyPage, a11y, semantic) => {
50
50
  export const checkStories = async (request) => {
51
51
  const { a11y } = catalogueSettings("", request.switches, request.lists);
52
52
  const results = await eachStoryPage(request, (page, storyPage) => checkedPage(page, storyPage, a11y, request.semantic));
53
- return { schema: 1, results };
53
+ return { schema: 1, results, ...(a11y === undefined ? { a11y: "off" } : {}) };
54
54
  };
@@ -1,3 +1,14 @@
1
+ /**
2
+ * A package's story files and their index, read from the disk: what a test runner that does not go through Vite
3
+ * (Playwright) needs to declare one test per story.
4
+ *
5
+ * @remarks
6
+ * A `StorySource` names its files with `?forgebook-files` imports, which only the catalogue's Vite plugin answers; this
7
+ * reads the same files from the same patterns, with the plugin's static index. A package keeps the two lists equal with
8
+ * `storyFilesMismatch`, run in Vitest, which goes through Vite.
9
+ *
10
+ * @module
11
+ */
1
12
  import type { StorySource } from "@forgebook/story-format/source";
2
13
  /** Where a package's story files are. */
3
14
  export type StoryFilesOptions = {
@@ -7,20 +18,24 @@ export type StoryFilesOptions = {
7
18
  readonly name: string;
8
19
  /** The folder the patterns are relative to: the folder of the module that declares the source. */
9
20
  readonly root: string;
10
- /** The same patterns as the source's `?forgebook-files` imports, relative to `root` (`../src/**\/*.stories.tsx`). */
21
+ /**
22
+ * The same patterns as the source's `?forgebook-files` imports, relative to `root` (`../src/**\/*.stories.tsx`), or
23
+ * the catalogue's `stories`: a `!` pattern leaves out what it matches from what the others list.
24
+ */
11
25
  readonly patterns: readonly string[];
12
26
  };
13
27
  /**
14
- * The story files the patterns match, as the source's keys (`./x` or `../x`, relative to `root`), sorted.
28
+ * The story files the patterns list, as the source's keys (`./x` or `../x`, relative to `root`), each once, sorted.
15
29
  *
16
30
  * @param options - where the files are.
31
+ * @throws When every pattern is a `!` one: they leave files out, and nothing lists any.
17
32
  */
18
33
  export declare const storyFiles: (options: StoryFilesOptions) => string[];
19
34
  /**
20
35
  * A source with its index read from the disk and no loaders: enough for the story tree, the ids and the tests.
21
36
  *
22
37
  * @param options - where the files are.
23
- * @throws When a story file cannot be indexed.
38
+ * @throws When a story file cannot be indexed, or every pattern is a `!` one.
24
39
  */
25
40
  export declare const indexedSource: (options: StoryFilesOptions) => StorySource;
26
41
  /**
@@ -1,44 +1,22 @@
1
- /**
2
- * A package's story files and their index, read from the disk: what a test runner that does not go through Vite
3
- * (Playwright) needs to declare one test per story.
4
- *
5
- * @remarks
6
- * A `StorySource` names its files with `?forgebook-files` imports, which only the catalogue's Vite plugin answers; this
7
- * reads the same files from the same patterns, with the plugin's static index. A package keeps the two lists equal with
8
- * `storyFilesMismatch`, run in Vitest, which goes through Vite.
9
- *
10
- * @module
11
- */
12
- import { readFileSync } from "node:fs";
13
- import { join } from "node:path";
14
1
  import { sourceFiles } from "forgebook/source-files";
15
- import { autoTitle, patternBase } from "forgebook/vite/auto-title";
16
- import { indexStoryFile } from "forgebook/vite/index-story-file";
17
- import { storyFileKeys } from "forgebook/vite/story-files-module";
2
+ import { indexedStoryFiles, storyFileKeys } from "forgebook/vite/story-files-module";
18
3
  /**
19
- * The story files the patterns match, as the source's keys (`./x` or `../x`, relative to `root`), sorted.
4
+ * The story files the patterns list, as the source's keys (`./x` or `../x`, relative to `root`), each once, sorted.
20
5
  *
21
6
  * @param options - where the files are.
7
+ * @throws When every pattern is a `!` one: they leave files out, and nothing lists any.
22
8
  */
23
9
  export const storyFiles = (options) => storyFileKeys(options.root, options.patterns);
24
10
  /**
25
11
  * A source with its index read from the disk and no loaders: enough for the story tree, the ids and the tests.
26
12
  *
27
13
  * @param options - where the files are.
28
- * @throws When a story file cannot be indexed.
14
+ * @throws When a story file cannot be indexed, or every pattern is a `!` one.
29
15
  */
30
16
  export const indexedSource = (options) => {
31
- const index = {};
32
- for (const file of storyFiles(options)) {
33
- // the title the plugin gives: from the first pattern that matches the file, as each pattern is one module
34
- const pattern = options.patterns.find((candidate) => storyFileKeys(options.root, [candidate]).includes(file));
35
- const title = pattern === undefined ? undefined : autoTitle(patternBase(pattern), file);
36
- const text = readFileSync(join(options.root, file), "utf8");
37
- const entry = indexStoryFile(file, text, title === undefined ? {} : { autoTitle: title });
38
- if (typeof entry === "string")
39
- throw new Error(entry);
40
- index[file] = entry;
41
- }
17
+ // indexed as the plugin indexes them: a file's title from the first pattern that lists it
18
+ const files = indexedStoryFiles(options.root, options.patterns, () => undefined);
19
+ const index = Object.fromEntries(files.map((file) => [file.key, file.index]));
42
20
  return {
43
21
  id: options.sourceId,
44
22
  name: options.name,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgebook/testing",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Tests from a package's stories: each story and variant in the browser with axe, spills and overlays, screenshots, and each story rendered on the server.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -80,13 +80,13 @@
80
80
  "dependencies": {
81
81
  "@axe-core/playwright": "4.14.0",
82
82
  "@ensiria/cli-kit": "^0.1.1",
83
- "@forgebook/story-format": "0.2.0"
83
+ "@forgebook/story-format": "0.2.2"
84
84
  },
85
85
  "peerDependencies": {
86
86
  "@playwright/test": "^1.64.0",
87
87
  "vite": "^8.0.0",
88
88
  "vitest": "^5.0.0",
89
- "forgebook": "^0.2.0"
89
+ "forgebook": "^0.3.1"
90
90
  },
91
91
  "devDependencies": {
92
92
  "@playwright/test": "1.64.1",
@@ -97,7 +97,7 @@
97
97
  "vitest": "5.0.5",
98
98
  "@forgebook/tools": "0.0.0",
99
99
  "@forgebook/typescript-config": "0.0.0",
100
- "forgebook": "0.2.0"
100
+ "forgebook": "0.3.1"
101
101
  },
102
102
  "publishConfig": {
103
103
  "access": "public"