@forgebook/testing 0.0.0-stage → 0.1.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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -2
  3. package/dist/bin/forgebook-heights/forgebook-heights.d.mts +3 -0
  4. package/dist/bin/forgebook-heights/forgebook-heights.d.mts.map +1 -0
  5. package/dist/bin/forgebook-heights/forgebook-heights.mjs +124 -0
  6. package/dist/bin/forgebook-heights/forgebook-heights.mjs.map +1 -0
  7. package/dist/bin/forgebook-heights/measureHeights.d.ts +84 -0
  8. package/dist/bin/forgebook-heights/measureHeights.d.ts.map +1 -0
  9. package/dist/bin/forgebook-heights/measureHeights.js +180 -0
  10. package/dist/bin/forgebook-heights/measureHeights.js.map +1 -0
  11. package/dist/bin/forgebook-heights/measureHeights.types.d.ts +27 -0
  12. package/dist/bin/forgebook-heights/measureHeights.types.d.ts.map +1 -0
  13. package/dist/bin/forgebook-heights/measureHeights.types.js +7 -0
  14. package/dist/bin/forgebook-heights/measureHeights.types.js.map +1 -0
  15. package/dist/bin/forgebook-shot/forgebook-shot.d.mts +3 -0
  16. package/dist/bin/forgebook-shot/forgebook-shot.d.mts.map +1 -0
  17. package/dist/bin/forgebook-shot/forgebook-shot.mjs +110 -0
  18. package/dist/bin/forgebook-shot/forgebook-shot.mjs.map +1 -0
  19. package/dist/bin/forgebook-shot/storyShot.d.ts +34 -0
  20. package/dist/bin/forgebook-shot/storyShot.d.ts.map +1 -0
  21. package/dist/bin/forgebook-shot/storyShot.js +83 -0
  22. package/dist/bin/forgebook-shot/storyShot.js.map +1 -0
  23. package/dist/bin/forgebook-shot/storyShot.types.d.ts +32 -0
  24. package/dist/bin/forgebook-shot/storyShot.types.d.ts.map +1 -0
  25. package/dist/bin/forgebook-shot/storyShot.types.js +1 -0
  26. package/dist/bin/forgebook-shot/storyShot.types.js.map +1 -0
  27. package/dist/src/browserTests.d.ts +55 -0
  28. package/dist/src/browserTests.d.ts.map +1 -0
  29. package/dist/src/browserTests.js +137 -0
  30. package/dist/src/browserTests.js.map +1 -0
  31. package/dist/src/fonts/Inter-OFL.txt +92 -0
  32. package/dist/src/fonts/Inter-latin-ext.woff2 +0 -0
  33. package/dist/src/fonts/Inter-latin.woff2 +0 -0
  34. package/dist/src/fonts/JetBrainsMono-OFL.txt +93 -0
  35. package/dist/src/fonts/JetBrainsMono-latin-ext.woff2 +0 -0
  36. package/dist/src/fonts/JetBrainsMono-latin.woff2 +0 -0
  37. package/dist/src/fonts/fonts.css +34 -0
  38. package/dist/src/overlays.d.ts +87 -0
  39. package/dist/src/overlays.d.ts.map +1 -0
  40. package/dist/src/overlays.js +103 -0
  41. package/dist/src/overlays.js.map +1 -0
  42. package/dist/src/playwrightConfig.d.ts +26 -0
  43. package/dist/src/playwrightConfig.d.ts.map +1 -0
  44. package/dist/src/playwrightConfig.js +62 -0
  45. package/dist/src/playwrightConfig.js.map +1 -0
  46. package/dist/src/serverTests.d.ts +44 -0
  47. package/dist/src/serverTests.d.ts.map +1 -0
  48. package/dist/src/serverTests.js +101 -0
  49. package/dist/src/serverTests.js.map +1 -0
  50. package/dist/src/spills.d.ts +28 -0
  51. package/dist/src/spills.d.ts.map +1 -0
  52. package/dist/src/spills.js +53 -0
  53. package/dist/src/spills.js.map +1 -0
  54. package/dist/src/storyControls.d.ts +24 -0
  55. package/dist/src/storyControls.d.ts.map +1 -0
  56. package/dist/src/storyControls.js +29 -0
  57. package/dist/src/storyControls.js.map +1 -0
  58. package/dist/src/storyFiles.d.ts +34 -0
  59. package/dist/src/storyFiles.d.ts.map +1 -0
  60. package/dist/src/storyFiles.js +66 -0
  61. package/dist/src/storyFiles.js.map +1 -0
  62. package/dist/src/testViteConfig.d.ts +21 -0
  63. package/dist/src/testViteConfig.d.ts.map +1 -0
  64. package/dist/src/testViteConfig.js +26 -0
  65. package/dist/src/testViteConfig.js.map +1 -0
  66. package/dist/src/visualBrowser.d.ts +18 -0
  67. package/dist/src/visualBrowser.d.ts.map +1 -0
  68. package/dist/src/visualBrowser.js +78 -0
  69. package/dist/src/visualBrowser.js.map +1 -0
  70. package/package.json +84 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forgebook-shot.mjs","sourceRoot":"","sources":["../../../bin/forgebook-shot/forgebook-shot.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { StoryShot } from "./storyShot.types.ts";
2
+ /** What a shot is taken of, and how. */
3
+ export type ShotRequest = {
4
+ /** The catalogue's address (`http://localhost:5310/`). */
5
+ readonly catalogue: string;
6
+ /** The story's id (`acme-ui:feedback-counter--plain`). */
7
+ readonly story: string;
8
+ /** The view, as the catalogue's address writes it (`theme=dark&lang=it`); empty for the defaults. */
9
+ readonly view: string;
10
+ /** The width the story is drawn at, in CSS px. */
11
+ readonly width: number;
12
+ /** Where the picture goes; none for no picture. */
13
+ readonly out: string | undefined;
14
+ /** Whether to check the story's accessibility. */
15
+ readonly isA11y: boolean;
16
+ /** How long to wait for the story, in ms. */
17
+ readonly timeout: number;
18
+ };
19
+ /**
20
+ * The frame's address of a story with a view: the catalogue's own `frame.html`, with only what the frame reads.
21
+ *
22
+ * @param catalogue - the catalogue's address.
23
+ * @param story - the story's id.
24
+ * @param view - the view as the catalogue's address writes it.
25
+ */
26
+ export declare const shotAddress: (catalogue: string, story: string, view: string) => string;
27
+ /**
28
+ * Opens a story's frame, waits for it, and reports what it shows.
29
+ *
30
+ * @param request - the story, the view and what to do.
31
+ * @returns the report; a frame that never answers is `timeout`, not an exception.
32
+ */
33
+ export declare const takeShot: (request: ShotRequest) => Promise<StoryShot>;
34
+ //# sourceMappingURL=storyShot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storyShot.d.ts","sourceRoot":"","sources":["../../../bin/forgebook-shot/storyShot.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAc,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAElE,wCAAwC;AACxC,MAAM,MAAM,WAAW,GAAG;IACxB,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qGAAqG;IACrG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,cAAe,MAAM,SAAS,MAAM,QAAQ,MAAM,KAAG,MAEpE,CAAC;AAEV;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,YAAmB,WAAW,KAAG,OAAO,CAAC,SAAS,CA0DtE,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * The logic of `forgebook-shot`: the frame's address of a story with a view, and the run in a browser that opens it,
3
+ * waits for its story and reports.
4
+ *
5
+ * @remarks
6
+ * The frame page is the address the catalogue and the generated tests open: what an agent sees is what a
7
+ * person sees in the stage. `shotAddress` is pure; `takeShot` drives Chromium through Playwright.
8
+ *
9
+ * @module
10
+ */
11
+ import { AxeBuilder } from "@axe-core/playwright";
12
+ import { chromium } from "@playwright/test";
13
+ import { DEFAULT_A11Y_TAGS } from "forgebook/catalogue";
14
+ import { STATUS_ATTRIBUTE } from "forgebook/frame-status";
15
+ import { frameAddressOf } from "forgebook/view-state";
16
+ /**
17
+ * The frame's address of a story with a view: the catalogue's own `frame.html`, with only what the frame reads.
18
+ *
19
+ * @param catalogue - the catalogue's address.
20
+ * @param story - the story's id.
21
+ * @param view - the view as the catalogue's address writes it.
22
+ */
23
+ export const shotAddress = (catalogue, story, view) => new URL(frameAddressOf("frame.html", story, view), catalogue.endsWith("/") ? catalogue : `${catalogue}/`)
24
+ .href;
25
+ /**
26
+ * Opens a story's frame, waits for it, and reports what it shows.
27
+ *
28
+ * @param request - the story, the view and what to do.
29
+ * @returns the report; a frame that never answers is `timeout`, not an exception.
30
+ */
31
+ export const takeShot = async (request) => {
32
+ const address = shotAddress(request.catalogue, request.story, request.view);
33
+ const browser = await chromium.launch();
34
+ try {
35
+ // a context of its own: axe works only on a page made by one
36
+ const context = await browser.newContext({ viewport: { width: request.width, height: 800 } });
37
+ const page = await context.newPage();
38
+ const consoleErrors = [];
39
+ page.on("pageerror", (error) => consoleErrors.push(error.message));
40
+ page.on("console", (message) => {
41
+ if (message.type() === "error")
42
+ consoleErrors.push(message.text());
43
+ });
44
+ await page.goto(address);
45
+ // a text expression: the command runs on Node, where the page's own globals are not typed
46
+ const status = await page
47
+ .waitForFunction(`document.documentElement.getAttribute(${JSON.stringify(STATUS_ATTRIBUTE)})`, undefined, {
48
+ timeout: request.timeout
49
+ })
50
+ .then(async (handle) => ((await handle.jsonValue()) === "ready" ? "ready" : "error"))
51
+ .catch(() => "timeout");
52
+ const error = status === "error"
53
+ ? ((await page.locator(".forgebook-frame-error__message").first().textContent()) ?? undefined)
54
+ : undefined;
55
+ const box = await page.locator("body").boundingBox();
56
+ const size = { width: Math.ceil(box?.width ?? 0), height: Math.ceil(box?.height ?? 0) };
57
+ if (request.out !== undefined)
58
+ await page.screenshot({ path: request.out, fullPage: true, animations: "disabled" });
59
+ const violations = request.isA11y
60
+ ? (await new AxeBuilder({ page }).withTags([...DEFAULT_A11Y_TAGS]).analyze()).violations.map((violation) => ({
61
+ id: violation.id,
62
+ help: violation.help,
63
+ impact: violation.impact ?? undefined,
64
+ helpUrl: violation.helpUrl,
65
+ targets: violation.nodes.map((node) => node.target.map(String).join(" "))
66
+ }))
67
+ : undefined;
68
+ return {
69
+ story: request.story,
70
+ address,
71
+ status,
72
+ ...(error === undefined ? {} : { error }),
73
+ size,
74
+ ...(request.out === undefined ? {} : { screenshot: request.out }),
75
+ consoleErrors,
76
+ ...(violations === undefined ? {} : { violations })
77
+ };
78
+ }
79
+ finally {
80
+ await browser.close();
81
+ }
82
+ };
83
+ //# sourceMappingURL=storyShot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storyShot.js","sourceRoot":"","sources":["../../../bin/forgebook-shot/storyShot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The `--json` document of `forgebook-shot`: how a story's frame ended, its size, where its picture went and, when
3
+ * asked, the accessibility rules it breaks.
4
+ *
5
+ * @module
6
+ */
7
+ import type { Violation } from "forgebook/a11y";
8
+ /** How the frame ended: its story shown, its error shown, or no answer before the time ran out. */
9
+ export type ShotStatus = "ready" | "error" | "timeout";
10
+ /** What `forgebook-shot` reports. */
11
+ export type StoryShot = {
12
+ /** The story's id. */
13
+ readonly story: string;
14
+ /** The frame's address that was opened. */
15
+ readonly address: string;
16
+ /** How the frame ended. */
17
+ readonly status: ShotStatus;
18
+ /** The frame's error, when its story could not be shown. */
19
+ readonly error?: string;
20
+ /** The story's size in CSS px, at the width it was drawn at. */
21
+ readonly size: {
22
+ readonly width: number;
23
+ readonly height: number;
24
+ };
25
+ /** The picture's path, when one was written. */
26
+ readonly screenshot?: string;
27
+ /** The errors the page printed or threw. */
28
+ readonly consoleErrors: readonly string[];
29
+ /** The accessibility rules the story breaks, when asked (`--a11y`). */
30
+ readonly violations?: readonly Violation[];
31
+ };
32
+ //# sourceMappingURL=storyShot.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storyShot.types.d.ts","sourceRoot":"","sources":["../../../bin/forgebook-shot/storyShot.types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,mGAAmG;AACnG,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;AAEvD,qCAAqC;AACrC,MAAM,MAAM,SAAS,GAAG;IACtB,sBAAsB;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,gDAAgD;IAChD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,4CAA4C;IAC5C,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,uEAAuE;IACvE,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CAC5C,CAAC"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=storyShot.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storyShot.types.js","sourceRoot":"","sources":["../../../bin/forgebook-shot/storyShot.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,55 @@
1
+ import { type Page } from "@playwright/test";
2
+ import { type CatalogueLists } from "forgebook/catalogue";
3
+ import { type ViewSwitch } from "forgebook/switches";
4
+ import { type ViewState } from "forgebook/view-state";
5
+ import { type StoryFilesOptions } from "./storyFiles.ts";
6
+ /** One way of showing every story. */
7
+ export type StoryVariant = {
8
+ /** The variant's name, in the test's title and the reference image's name. */
9
+ readonly name: string;
10
+ /**
11
+ * What it sets over the defaults: switches' values, the style sheets, the text size; never the backdrop, since
12
+ * every test draws the story on its page's colour.
13
+ */
14
+ readonly view: Partial<Omit<ViewState, "backdrop">>;
15
+ /** The frame's width in CSS px; the test browser's default when none. */
16
+ readonly width?: number;
17
+ };
18
+ /** The narrow variant's width: about the catalogue's stage beside the props panel in a laptop window, in CSS px. */
19
+ export declare const NARROW_WIDTH = 560;
20
+ /**
21
+ * The variants every story is tested in, from the catalogue's switches: each scheme of its colour scheme switch (the
22
+ * system's left out, it draws one of them), each at more contrast when it has a contrast switch (`dark-more`), then the
23
+ * first scheme with the structure only, and in a narrow frame.
24
+ *
25
+ * @param switches - the catalogue's switches.
26
+ */
27
+ export declare const storyVariants: (switches: readonly ViewSwitch[]) => StoryVariant[];
28
+ /** The variants of a catalogue with the default switches: light, dark, both at more contrast, structure, narrow. */
29
+ export declare const STORY_VARIANTS: readonly StoryVariant[];
30
+ /** The generated tests' options. */
31
+ export type StoryBrowserTestsOptions = StoryFilesOptions & {
32
+ /** The frame page, relative to the test's `baseURL`; `frame.html` by default. */
33
+ readonly frameUrl?: string;
34
+ /** The catalogue's switches, as the frame page's configuration gives them; the theme and the contrast by default. */
35
+ readonly switches?: readonly ViewSwitch[];
36
+ /** The catalogue's lists, as its configuration gives them: its accessibility rules, backgrounds, text sizes. */
37
+ readonly lists?: CatalogueLists;
38
+ /** The variants; `storyVariants` of the switches by default. */
39
+ readonly variants?: readonly StoryVariant[];
40
+ /** Compare each frame with its reference image instead of running the checks; `false` by default. */
41
+ readonly screenshot?: boolean;
42
+ /**
43
+ * A check of the source's own, run on every story's frame after axe (a rule of its components that axe does not
44
+ * know); it fails the test with Playwright's `expect`. None by default; skipped with `screenshot`.
45
+ */
46
+ readonly check?: (page: Page) => Promise<void>;
47
+ };
48
+ /**
49
+ * Declares the tests, one `describe` per component and one test per story and variant.
50
+ *
51
+ * @param options - where the stories are, the frame page, the variants, whether to compare screenshots, and a check of
52
+ * the source's own.
53
+ */
54
+ export declare const storyBrowserTests: (options: StoryBrowserTestsOptions) => void;
55
+ //# sourceMappingURL=browserTests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browserTests.d.ts","sourceRoot":"","sources":["../../src/browserTests.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAU,KAAK,IAAI,EAAQ,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,qBAAqB,CAAC;AAI7E,OAAO,EAAoC,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjF,OAAO,EAAiB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAExE,sCAAsC;AACtC,MAAM,MAAM,YAAY,GAAG;IACzB,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IACpD,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,oHAAoH;AACpH,eAAO,MAAM,YAAY,MAAM,CAAC;AAEhC;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,aAAc,SAAS,UAAU,EAAE,KAAG,YAAY,EAuB3E,CAAC;AAEF,oHAAoH;AACpH,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAAoC,CAAC;AAEvF,oCAAoC;AACpC,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,GAAG;IACzD,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,qHAAqH;IACrH,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAC1C,gHAAgH;IAChH,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;IAChC,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C,qGAAqG;IACrG,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD,CAAC;AAwBF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,YAAa,wBAAwB,KAAG,IAsDrE,CAAC"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * One Playwright test per story and variant, on the catalogue's frame pages: the address the catalogue shows is the
3
+ * address the tests open.
4
+ *
5
+ * @remarks
6
+ * Each test opens the frame for a story in a variant (the theme, the contrast, the style sheets), waits for the
7
+ * frame to say the story is shown (`data-forgebook-status`), its story clock held at its start, and fails on an error in the console or the page, or on
8
+ * an axe violation of WCAG 2.2 A and AA, on an element that spills out of its parent (`spills.ts`: what overlaps a
9
+ * neighbour when the story is narrower than it was drawn for), on an overlay its play leaves open past the frame the
10
+ * catalogue would give it (`overlays.ts`: the story then declares `parameters.height`), or on the source's own
11
+ * `check`. The variants include a
12
+ * narrow frame, as wide as the catalogue's stage beside the props panel. With `screenshot` it compares the frame with its reference image instead,
13
+ * for the visual tests, which run in the Playwright container so fonts and rendering are the same everywhere.
14
+ *
15
+ * @module
16
+ */
17
+ import { AxeBuilder } from "@axe-core/playwright";
18
+ import { expect, test } from "@playwright/test";
19
+ import { catalogueSettings } from "forgebook/catalogue";
20
+ import { STATUS_ATTRIBUTE } from "forgebook/frame-status";
21
+ import { heldClockAddress } from "forgebook/story-clock";
22
+ import { storyTree, testedStoryLocations } from "forgebook/story-tree";
23
+ import { DEFAULT_SWITCHES, switchWithRole } from "forgebook/switches";
24
+ import { defaultView, frameAddress } from "forgebook/view-state";
25
+ import { findOverlaysPastFrame, isOverlayChecked } from "./overlays.js";
26
+ import { findSpills } from "./spills.js";
27
+ import { indexedSource } from "./storyFiles.js";
28
+ /** The narrow variant's width: about the catalogue's stage beside the props panel in a laptop window, in CSS px. */
29
+ export const NARROW_WIDTH = 560;
30
+ /**
31
+ * The variants every story is tested in, from the catalogue's switches: each scheme of its colour scheme switch (the
32
+ * system's left out, it draws one of them), each at more contrast when it has a contrast switch (`dark-more`), then the
33
+ * first scheme with the structure only, and in a narrow frame.
34
+ *
35
+ * @param switches - the catalogue's switches.
36
+ */
37
+ export const storyVariants = (switches) => {
38
+ const scheme = switchWithRole(switches, "colorScheme");
39
+ const contrast = switchWithRole(switches, "contrast");
40
+ const more = contrast?.values.find((value) => value.isMore === true);
41
+ const schemes = (scheme?.values ?? []).filter((value) => value.isUnset !== true);
42
+ const schemeView = (value) => scheme === undefined || value === undefined ? {} : { [scheme.id]: value };
43
+ const first = schemeView(schemes[0]?.value);
44
+ const named = schemes.length > 0 ? schemes : [undefined];
45
+ return [
46
+ ...named.map((value) => ({
47
+ name: value?.value ?? "default",
48
+ view: { switches: schemeView(value?.value) }
49
+ })),
50
+ ...(contrast === undefined || more === undefined
51
+ ? []
52
+ : named.map((value) => ({
53
+ name: `${value?.value ?? "default"}-more`,
54
+ view: { switches: { ...schemeView(value?.value), [contrast.id]: more.value } }
55
+ }))),
56
+ { name: "structure", view: { switches: first, sheets: "structure" } },
57
+ { name: "narrow", view: { switches: first }, width: NARROW_WIDTH }
58
+ ];
59
+ };
60
+ /** The variants of a catalogue with the default switches: light, dark, both at more contrast, structure, narrow. */
61
+ export const STORY_VARIANTS = storyVariants(DEFAULT_SWITCHES);
62
+ /**
63
+ * The overlays a story's play leaves open past its frame, as the test's messages; none in a view that is not checked
64
+ * (`isOverlayChecked`).
65
+ *
66
+ * @param page - the story's frame page, its play over.
67
+ * @param variant - the variant the test shows the story in.
68
+ * @param sceneHeight - the height the story declares, in CSS px, if any.
69
+ * @returns one message per overlay past the frame.
70
+ */
71
+ const overlayProblems = async (page, variant, sceneHeight) => {
72
+ if (!isOverlayChecked(variant.view))
73
+ return [];
74
+ const overlays = await findOverlaysPastFrame(page, sceneHeight);
75
+ return overlays.map((overlay) => `${overlay.element} ends ${overlay.by}px below the frame's ${overlay.frameHeight}px: declare parameters.height`);
76
+ };
77
+ /**
78
+ * Declares the tests, one `describe` per component and one test per story and variant.
79
+ *
80
+ * @param options - where the stories are, the frame page, the variants, whether to compare screenshots, and a check of
81
+ * the source's own.
82
+ */
83
+ export const storyBrowserTests = (options) => {
84
+ const { frameUrl = "frame.html", switches = DEFAULT_SWITCHES, screenshot = false, check } = options;
85
+ const variants = options.variants ?? storyVariants(switches);
86
+ const catalogue = catalogueSettings("", switches, options.lists);
87
+ const defaults = defaultView(catalogue);
88
+ const tree = storyTree([indexedSource(options)]);
89
+ const groups = Map.groupBy(testedStoryLocations(tree), (location) => location.component.title);
90
+ for (const [title, locations] of groups) {
91
+ test.describe(title, () => {
92
+ for (const { story } of locations) {
93
+ for (const variant of variants) {
94
+ test(`${story.name} · ${variant.name}`, async ({ page }) => {
95
+ const errors = [];
96
+ page.on("pageerror", (error) => errors.push(error.message));
97
+ page.on("console", (message) => {
98
+ if (message.type() === "error")
99
+ errors.push(message.text());
100
+ });
101
+ if (variant.width !== undefined)
102
+ await page.setViewportSize({ width: variant.width, height: 800 });
103
+ // a Live story is checked and pictured at its start: its clock held, so its image never changes;
104
+ // always on its page's own colour, whatever a variant names: a backdrop is for looking
105
+ const view = {
106
+ ...defaults,
107
+ ...variant.view,
108
+ switches: { ...defaults.switches, ...variant.view.switches },
109
+ backdrop: "plain"
110
+ };
111
+ await page.goto(heldClockAddress(frameAddress(frameUrl, story.id, view, switches)));
112
+ await expect(page.locator("html")).toHaveAttribute(STATUS_ATTRIBUTE, "ready");
113
+ if (screenshot) {
114
+ await expect(page).toHaveScreenshot(`${story.id.replace(":", "--")}--${variant.name}.png`, {
115
+ fullPage: true,
116
+ animations: "disabled"
117
+ });
118
+ return;
119
+ }
120
+ const { violations } = await new AxeBuilder({ page })
121
+ .withTags([...catalogue.a11y.tags])
122
+ .disableRules([...catalogue.a11y.disabledRules])
123
+ .analyze();
124
+ expect(violations.map((violation) => `${violation.id}: ${violation.help}`)).toEqual([]);
125
+ const spills = await page.evaluate(findSpills, ".forgebook-frame");
126
+ expect(spills.map((spill) => `${spill.element} spills out of ${spill.parent} by ${spill.by}px`)).toEqual([]);
127
+ await check?.(page);
128
+ // last: it resizes the window, which may close what the story left open
129
+ expect(await overlayProblems(page, variant, story.height)).toEqual([]);
130
+ expect(errors).toEqual([]);
131
+ });
132
+ }
133
+ }
134
+ });
135
+ }
136
+ };
137
+ //# sourceMappingURL=browserTests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browserTests.js","sourceRoot":"","sources":["../../src/browserTests.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+ -----------------------------------------------------------
8
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
9
+ -----------------------------------------------------------
10
+
11
+ PREAMBLE
12
+ The goals of the Open Font License (OFL) are to stimulate worldwide
13
+ development of collaborative font projects, to support the font creation
14
+ efforts of academic and linguistic communities, and to provide a free and
15
+ open framework in which fonts may be shared and improved in partnership
16
+ with others.
17
+
18
+ The OFL allows the licensed fonts to be used, studied, modified and
19
+ redistributed freely as long as they are not sold by themselves. The
20
+ fonts, including any derivative works, can be bundled, embedded,
21
+ redistributed and/or sold with any software provided that any reserved
22
+ names are not used by derivative works. The fonts and derivatives,
23
+ however, cannot be released under any other type of license. The
24
+ requirement for fonts to remain under this license does not apply
25
+ to any document created using the fonts or their derivatives.
26
+
27
+ DEFINITIONS
28
+ "Font Software" refers to the set of files released by the Copyright
29
+ Holder(s) under this license and clearly marked as such. This may
30
+ include source files, build scripts and documentation.
31
+
32
+ "Reserved Font Name" refers to any names specified as such after the
33
+ copyright statement(s).
34
+
35
+ "Original Version" refers to the collection of Font Software components as
36
+ distributed by the Copyright Holder(s).
37
+
38
+ "Modified Version" refers to any derivative made by adding to, deleting,
39
+ or substituting -- in part or in whole -- any of the components of the
40
+ Original Version, by changing formats or by porting the Font Software to a
41
+ new environment.
42
+
43
+ "Author" refers to any designer, engineer, programmer, technical
44
+ writer or other person who contributed to the Font Software.
45
+
46
+ PERMISSION AND CONDITIONS
47
+ Permission is hereby granted, free of charge, to any person obtaining
48
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
49
+ redistribute, and sell modified and unmodified copies of the Font
50
+ Software, subject to the following conditions:
51
+
52
+ 1) Neither the Font Software nor any of its individual components,
53
+ in Original or Modified Versions, may be sold by itself.
54
+
55
+ 2) Original or Modified Versions of the Font Software may be bundled,
56
+ redistributed and/or sold with any software, provided that each copy
57
+ contains the above copyright notice and this license. These can be
58
+ included either as stand-alone text files, human-readable headers or
59
+ in the appropriate machine-readable metadata fields within text or
60
+ binary files as long as those fields can be easily viewed by the user.
61
+
62
+ 3) No Modified Version of the Font Software may use the Reserved Font
63
+ Name(s) unless explicit written permission is granted by the corresponding
64
+ Copyright Holder. This restriction only applies to the primary font name as
65
+ presented to the users.
66
+
67
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
68
+ Software shall not be used to promote, endorse or advertise any
69
+ Modified Version, except to acknowledge the contribution(s) of the
70
+ Copyright Holder(s) and the Author(s) or with their explicit written
71
+ permission.
72
+
73
+ 5) The Font Software, modified or unmodified, in part or in whole,
74
+ must be distributed entirely under this license, and must not be
75
+ distributed under any other license. The requirement for fonts to
76
+ remain under this license does not apply to any document created
77
+ using the Font Software.
78
+
79
+ TERMINATION
80
+ This license becomes null and void if any of the above conditions are
81
+ not met.
82
+
83
+ DISCLAIMER
84
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
85
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
86
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
87
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
88
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
89
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
90
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
91
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
92
+ OTHER DEALINGS IN THE FONT SOFTWARE.
Binary file
@@ -0,0 +1,93 @@
1
+ Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ https://openfontlicense.org
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,34 @@
1
+ /*
2
+ * The fonts of the visual tests: Inter and JetBrains Mono (SIL Open Font License 1.1, the licences beside them).
3
+ * The visual tests run in the Playwright container, on Linux, where `-apple-system` and `SF Mono` do not exist: a
4
+ * library's font stacks fall back to these, the same on every run. Published as `./testing/fonts.css` and imported
5
+ * only by a package's test frame page, never by a catalogue.
6
+ */
7
+ @font-face {
8
+ font-family: "Inter";
9
+ font-style: normal;
10
+ font-weight: 100 900;
11
+ src: url("./Inter-latin-ext.woff2") format("woff2");
12
+ unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
13
+ }
14
+ @font-face {
15
+ font-family: "Inter";
16
+ font-style: normal;
17
+ font-weight: 100 900;
18
+ src: url("./Inter-latin.woff2") format("woff2");
19
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
20
+ }
21
+ @font-face {
22
+ font-family: "JetBrains Mono";
23
+ font-style: normal;
24
+ font-weight: 100 800;
25
+ src: url("./JetBrainsMono-latin-ext.woff2") format("woff2");
26
+ unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
27
+ }
28
+ @font-face {
29
+ font-family: "JetBrains Mono";
30
+ font-style: normal;
31
+ font-weight: 100 800;
32
+ src: url("./JetBrainsMono-latin.woff2") format("woff2");
33
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
34
+ }