@forgebook/testing 0.1.4 → 0.1.6
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/dist/src/browserTests.d.ts +16 -0
- package/dist/src/browserTests.d.ts.map +1 -1
- package/dist/src/browserTests.js +8 -33
- package/dist/src/browserTests.js.map +1 -1
- package/dist/src/checkStories.d.ts +9 -0
- package/dist/src/checkStories.d.ts.map +1 -0
- package/dist/src/checkStories.js +47 -0
- package/dist/src/checkStories.js.map +1 -0
- package/dist/src/shotStories.d.ts +16 -0
- package/dist/src/shotStories.d.ts.map +1 -0
- package/dist/src/shotStories.js +52 -0
- package/dist/src/shotStories.js.map +1 -0
- package/dist/src/storyCheck.d.ts +38 -0
- package/dist/src/storyCheck.d.ts.map +1 -0
- package/dist/src/storyCheck.js +85 -0
- package/dist/src/storyCheck.js.map +1 -0
- package/dist/src/storyFiles.d.ts +2 -1
- package/dist/src/storyFiles.d.ts.map +1 -1
- package/dist/src/storyFiles.js +22 -12
- package/dist/src/storyFiles.js.map +1 -1
- package/dist/src/storyPages.d.ts +55 -0
- package/dist/src/storyPages.d.ts.map +1 -0
- package/dist/src/storyPages.js +105 -0
- package/dist/src/storyPages.js.map +1 -0
- package/dist/src/touchWindow.d.ts +8 -0
- package/dist/src/touchWindow.d.ts.map +1 -0
- package/dist/src/touchWindow.js +64 -0
- package/dist/src/touchWindow.js.map +1 -0
- package/package.json +17 -5
- package/dist/src/spills.d.ts +0 -28
- package/dist/src/spills.d.ts.map +0 -1
- package/dist/src/spills.js +0 -53
- package/dist/src/spills.js.map +0 -1
|
@@ -1,3 +1,19 @@
|
|
|
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 (`forgebook/spills`: 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
|
+
*/
|
|
1
17
|
import { type Page } from "@playwright/test";
|
|
2
18
|
import { type CatalogueLists } from "forgebook/catalogue";
|
|
3
19
|
import { type ViewSwitch } from "forgebook/switches";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserTests.d.ts","sourceRoot":"","sources":["../../src/browserTests.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"browserTests.d.ts","sourceRoot":"","sources":["../../src/browserTests.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAU,KAAK,IAAI,EAAQ,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,qBAAqB,CAAC;AAK7E,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;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,YAAa,wBAAwB,KAAG,IA+CrE,CAAC"}
|
package/dist/src/browserTests.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @remarks
|
|
6
6
|
* Each test opens the frame for a story in a variant (the theme, the contrast, the style sheets), waits for the
|
|
7
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
|
|
8
|
+
* an axe violation of WCAG 2.2 A and AA, on an element that spills out of its parent (`forgebook/spills`: what overlaps a
|
|
9
9
|
* neighbour when the story is narrower than it was drawn for), on an overlay its play leaves open past the frame the
|
|
10
10
|
* catalogue would give it (`overlays.ts`: the story then declares `parameters.height`), or on the source's own
|
|
11
11
|
* `check`. The variants include a
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @module
|
|
16
16
|
*/
|
|
17
|
-
import { AxeBuilder } from "@axe-core/playwright";
|
|
18
17
|
import { expect, test } from "@playwright/test";
|
|
19
18
|
import { catalogueSettings } from "forgebook/catalogue";
|
|
20
19
|
import { STATUS_ATTRIBUTE } from "forgebook/frame-status";
|
|
@@ -22,8 +21,8 @@ import { heldClockAddress } from "forgebook/story-clock";
|
|
|
22
21
|
import { storyTree, testedStoryLocations } from "forgebook/story-tree";
|
|
23
22
|
import { DEFAULT_SWITCHES, switchWithRole } from "forgebook/switches";
|
|
24
23
|
import { defaultView, frameAddress } from "forgebook/view-state";
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
24
|
+
import { isOverlayChecked } from "./overlays.js";
|
|
25
|
+
import { axeProblems, overlayProblems, spillProblems, watchedErrors } from "./storyCheck.js";
|
|
27
26
|
import { indexedSource } from "./storyFiles.js";
|
|
28
27
|
/** The narrow variant's width: about the catalogue's stage beside the props panel in a laptop window, in CSS px. */
|
|
29
28
|
export const NARROW_WIDTH = 560;
|
|
@@ -59,21 +58,6 @@ export const storyVariants = (switches) => {
|
|
|
59
58
|
};
|
|
60
59
|
/** The variants of a catalogue with the default switches: light, dark, both at more contrast, structure, narrow. */
|
|
61
60
|
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
61
|
/**
|
|
78
62
|
* Declares the tests, one `describe` per component and one test per story and variant.
|
|
79
63
|
*
|
|
@@ -92,12 +76,7 @@ export const storyBrowserTests = (options) => {
|
|
|
92
76
|
for (const { story } of locations) {
|
|
93
77
|
for (const variant of variants) {
|
|
94
78
|
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
|
-
});
|
|
79
|
+
const errors = watchedErrors(page);
|
|
101
80
|
if (variant.width !== undefined)
|
|
102
81
|
await page.setViewportSize({ width: variant.width, height: 800 });
|
|
103
82
|
// a Live story is checked and pictured at its start: its clock held, so its image never changes;
|
|
@@ -117,16 +96,12 @@ export const storyBrowserTests = (options) => {
|
|
|
117
96
|
});
|
|
118
97
|
return;
|
|
119
98
|
}
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
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([]);
|
|
99
|
+
const messages = (problems) => problems.map((problem) => problem.message);
|
|
100
|
+
expect(messages(await axeProblems(page, catalogue.a11y))).toEqual([]);
|
|
101
|
+
expect(messages(await spillProblems(page))).toEqual([]);
|
|
127
102
|
await check?.(page);
|
|
128
103
|
// last: it resizes the window, which may close what the story left open
|
|
129
|
-
expect(await overlayProblems(page, variant, story.height)).toEqual([]);
|
|
104
|
+
expect(messages(await overlayProblems(page, isOverlayChecked(variant.view), story.height))).toEqual([]);
|
|
130
105
|
expect(errors).toEqual([]);
|
|
131
106
|
});
|
|
132
107
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserTests.js","sourceRoot":"","sources":["../../src/browserTests.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"browserTests.js","sourceRoot":"","sources":["../../src/browserTests.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { StoryCheckReport, StoryCheckRequest } from "forgebook/story-check";
|
|
2
|
+
/**
|
|
3
|
+
* Checks the stories a request names, in its views, on one browser.
|
|
4
|
+
*
|
|
5
|
+
* @param request - the stories, the views and the catalogue's settings.
|
|
6
|
+
* @returns one result per story and view, in the request's order.
|
|
7
|
+
*/
|
|
8
|
+
export declare const checkStories: (request: StoryCheckRequest) => Promise<StoryCheckReport>;
|
|
9
|
+
//# sourceMappingURL=checkStories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkStories.d.ts","sourceRoot":"","sources":["../../src/checkStories.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EAGlB,MAAM,uBAAuB,CAAC;AA0C/B;;;;;GAKG;AACH,eAAO,MAAM,YAAY,YAAmB,iBAAiB,KAAG,OAAO,CAAC,gBAAgB,CAIvF,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { catalogueSettings } from "forgebook/catalogue";
|
|
2
|
+
import { isOverlayChecked } from "./overlays.js";
|
|
3
|
+
import { axeProblems, errorProblems, overlayProblems, spillProblems, watchedErrors } from "./storyCheck.js";
|
|
4
|
+
import { eachStoryPage, openedStory, READY_MS } from "./storyPages.js";
|
|
5
|
+
/**
|
|
6
|
+
* One story in one view, checked.
|
|
7
|
+
*
|
|
8
|
+
* @param page - a fresh page.
|
|
9
|
+
* @param storyPage - the story and the view.
|
|
10
|
+
* @param a11y - the catalogue's accessibility settings.
|
|
11
|
+
*/
|
|
12
|
+
const checkedPage = async (page, storyPage, a11y) => {
|
|
13
|
+
const errors = watchedErrors(page);
|
|
14
|
+
const status = await openedStory(page, storyPage);
|
|
15
|
+
const result = (problems) => ({
|
|
16
|
+
storyId: storyPage.story.id,
|
|
17
|
+
view: storyPage.name,
|
|
18
|
+
frame: storyPage.frame,
|
|
19
|
+
problems
|
|
20
|
+
});
|
|
21
|
+
if (status === "silent")
|
|
22
|
+
return result([
|
|
23
|
+
{ kind: "frame", message: `The frame did not say it was ready in ${READY_MS / 1000} s` },
|
|
24
|
+
...errorProblems(errors)
|
|
25
|
+
]);
|
|
26
|
+
if (status === "error")
|
|
27
|
+
return result([{ kind: "frame", message: "The story could not be shown" }, ...errorProblems(errors)]);
|
|
28
|
+
return result([
|
|
29
|
+
...(await axeProblems(page, a11y)),
|
|
30
|
+
...(await spillProblems(page)),
|
|
31
|
+
// last of the page's checks: it resizes the window, which may close what the story left open
|
|
32
|
+
...(await overlayProblems(page, isOverlayChecked(storyPage.view), storyPage.story.height)),
|
|
33
|
+
...errorProblems(errors)
|
|
34
|
+
]);
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Checks the stories a request names, in its views, on one browser.
|
|
38
|
+
*
|
|
39
|
+
* @param request - the stories, the views and the catalogue's settings.
|
|
40
|
+
* @returns one result per story and view, in the request's order.
|
|
41
|
+
*/
|
|
42
|
+
export const checkStories = async (request) => {
|
|
43
|
+
const { a11y } = catalogueSettings("", request.switches, request.lists);
|
|
44
|
+
const results = await eachStoryPage(request, (page, storyPage) => checkedPage(page, storyPage, a11y));
|
|
45
|
+
return { schema: 1, results };
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=checkStories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkStories.js","sourceRoot":"","sources":["../../src/checkStories.ts"],"names":[],"mappings":"AAYA,OAAO,EAAqB,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAQ3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC5G,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAkB,MAAM,iBAAiB,CAAC;AAEvF;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,KAAK,EACvB,IAAU,EACV,SAAoB,EACpB,IAAkB,EACS,EAAE;IAC7B,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,CAAC,QAAiC,EAAoB,EAAE,CAAC,CAAC;QACvE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE;QAC3B,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,QAAQ;KACT,CAAC,CAAC;IACH,IAAI,MAAM,KAAK,QAAQ;QACrB,OAAO,MAAM,CAAC;YACZ,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,yCAAyC,QAAQ,GAAG,IAAI,IAAI,EAAE;YACxF,GAAG,aAAa,CAAC,MAAM,CAAC;SACzB,CAAC,CAAC;IACL,IAAI,MAAM,KAAK,OAAO;QACpB,OAAO,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,8BAA8B,EAAE,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACxG,OAAO,MAAM,CAAC;QACZ,GAAG,CAAC,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAClC,GAAG,CAAC,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QAC9B,6FAA6F;QAC7F,GAAG,CAAC,MAAM,eAAe,CAAC,IAAI,EAAE,gBAAgB,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC1F,GAAG,aAAa,CAAC,MAAM,CAAC;KACzB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,OAA0B,EAA6B,EAAE;IAC1F,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,CAAC,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;IACtG,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StoryShotReport, StoryShotRequest } from "forgebook/story-check";
|
|
2
|
+
import { type StoryPage } from "./storyPages.ts";
|
|
3
|
+
/**
|
|
4
|
+
* A picture's file name: the story's id and the view's name, each kept to letters, digits and hyphens.
|
|
5
|
+
*
|
|
6
|
+
* @param storyPage - the story and the view.
|
|
7
|
+
*/
|
|
8
|
+
export declare const shotName: (storyPage: Pick<StoryPage, "story" | "name">) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Pictures the stories a request names, in its views, on one browser.
|
|
11
|
+
*
|
|
12
|
+
* @param request - the stories, the views, the catalogue's settings and the folder.
|
|
13
|
+
* @returns one picture per story and view, in the request's order.
|
|
14
|
+
*/
|
|
15
|
+
export declare const shotStories: (request: StoryShotRequest) => Promise<StoryShotReport>;
|
|
16
|
+
//# sourceMappingURL=shotStories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shotStories.d.ts","sourceRoot":"","sources":["../../src/shotStories.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAa,eAAe,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE1F,OAAO,EAA8B,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE7E;;;;GAIG;AACH,eAAO,MAAM,QAAQ,cAAe,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAC,KAAG,MAGvE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,YAAmB,gBAAgB,KAAG,OAAO,CAAC,eAAe,CAmBpF,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pictures of stories taken in a browser, as `forgebook shot` asks for them: each story opened in each view asked for
|
|
3
|
+
* (or every variant the browser tests check), pictured at its own height (as the shell sizes its frame), written as a
|
|
4
|
+
* PNG file.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Loaded from the project by the command only when it runs, as the check is. A story is pictured at its start (its
|
|
8
|
+
* clock held, animations off), so the same story in the same view gives the same picture. A frame that never says it
|
|
9
|
+
* is ready is pictured as it is, so the picture shows what is wrong. The file's name is the story's id and the view's,
|
|
10
|
+
* so the pictures of several views sit side by side.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import { mkdirSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { eachStoryPage, openedStory } from "./storyPages.js";
|
|
17
|
+
/**
|
|
18
|
+
* A picture's file name: the story's id and the view's name, each kept to letters, digits and hyphens.
|
|
19
|
+
*
|
|
20
|
+
* @param storyPage - the story and the view.
|
|
21
|
+
*/
|
|
22
|
+
export const shotName = (storyPage) => {
|
|
23
|
+
const safe = (text) => text.replace(/[^a-zA-Z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
24
|
+
return `${safe(storyPage.story.id)}--${safe(storyPage.name) || "default"}.png`;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Pictures the stories a request names, in its views, on one browser.
|
|
28
|
+
*
|
|
29
|
+
* @param request - the stories, the views, the catalogue's settings and the folder.
|
|
30
|
+
* @returns one picture per story and view, in the request's order.
|
|
31
|
+
*/
|
|
32
|
+
export const shotStories = async (request) => {
|
|
33
|
+
mkdirSync(request.outDir, { recursive: true });
|
|
34
|
+
const shots = await eachStoryPage(request, async (page, storyPage) => {
|
|
35
|
+
await openedStory(page, storyPage);
|
|
36
|
+
const file = join(request.outDir, shotName(storyPage));
|
|
37
|
+
// the story at its own height, not the window's: the body's, as the shell sizes a frame
|
|
38
|
+
const size = await page.evaluate(() => ({
|
|
39
|
+
width: document.documentElement.clientWidth,
|
|
40
|
+
height: Math.max(1, Math.ceil(document.body.getBoundingClientRect().height))
|
|
41
|
+
}));
|
|
42
|
+
await page.screenshot({
|
|
43
|
+
path: file,
|
|
44
|
+
fullPage: true,
|
|
45
|
+
clip: { x: 0, y: 0, ...size },
|
|
46
|
+
animations: "disabled"
|
|
47
|
+
});
|
|
48
|
+
return { storyId: storyPage.story.id, view: storyPage.name, frame: storyPage.frame, file };
|
|
49
|
+
});
|
|
50
|
+
return { schema: 1, shots };
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=shotStories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shotStories.js","sourceRoot":"","sources":["../../src/shotStories.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAkB,MAAM,iBAAiB,CAAC;AAE7E;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,SAA4C,EAAU,EAAE;IAC/E,MAAM,IAAI,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACpG,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,SAAS,MAAM,CAAC;AACjF,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,OAAyB,EAA4B,EAAE;IACvF,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAsB,EAAE;QACvF,MAAM,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;QACvD,wFAAwF;QACxF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;YACtC,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,WAAW;YAC3C,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC,CAAC;SAC7E,CAAC,CAAC,CAAC;QACJ,MAAM,IAAI,CAAC,UAAU,CAAC;YACpB,IAAI,EAAE,IAAI;YACV,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE;YAC7B,UAAU,EAAE,UAAU;SACvB,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;IAC7F,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Page } from "@playwright/test";
|
|
2
|
+
import type { A11ySettings } from "forgebook/catalogue";
|
|
3
|
+
import type { StoryProblem } from "forgebook/story-check";
|
|
4
|
+
/**
|
|
5
|
+
* The page's errors from now on: uncaught ones and the console's, in the order they come.
|
|
6
|
+
*
|
|
7
|
+
* @param page - the page, before it opens the story.
|
|
8
|
+
* @returns the list the errors are added to.
|
|
9
|
+
*/
|
|
10
|
+
export declare const watchedErrors: (page: Page) => string[];
|
|
11
|
+
/**
|
|
12
|
+
* The rules of the catalogue's accessibility settings the story breaks.
|
|
13
|
+
*
|
|
14
|
+
* @param page - the story's frame page, ready.
|
|
15
|
+
* @param a11y - the catalogue's accessibility settings.
|
|
16
|
+
*/
|
|
17
|
+
export declare const axeProblems: (page: Page, a11y: A11ySettings) => Promise<StoryProblem[]>;
|
|
18
|
+
/**
|
|
19
|
+
* The elements that spill out of their parents.
|
|
20
|
+
*
|
|
21
|
+
* @param page - the story's frame page, ready.
|
|
22
|
+
*/
|
|
23
|
+
export declare const spillProblems: (page: Page) => Promise<StoryProblem[]>;
|
|
24
|
+
/**
|
|
25
|
+
* The overlays the story leaves open past its frame; none in a view where they are not checked.
|
|
26
|
+
*
|
|
27
|
+
* @param page - the story's frame page, its play over.
|
|
28
|
+
* @param isChecked - whether the view checks overlays (`isOverlayChecked`).
|
|
29
|
+
* @param sceneHeight - the height the story declares, in CSS px, if any.
|
|
30
|
+
*/
|
|
31
|
+
export declare const overlayProblems: (page: Page, isChecked: boolean, sceneHeight: number | undefined) => Promise<StoryProblem[]>;
|
|
32
|
+
/**
|
|
33
|
+
* The page's errors as problems.
|
|
34
|
+
*
|
|
35
|
+
* @param errors - the errors `watchedErrors` collected.
|
|
36
|
+
*/
|
|
37
|
+
export declare const errorProblems: (errors: readonly string[]) => StoryProblem[];
|
|
38
|
+
//# sourceMappingURL=storyCheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storyCheck.d.ts","sourceRoot":"","sources":["../../src/storyCheck.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAI1D;;;;;GAKG;AACH,eAAO,MAAM,aAAa,SAAU,IAAI,KAAG,MAAM,EAOhD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,SAAgB,IAAI,QAAQ,YAAY,KAAG,OAAO,CAAC,YAAY,EAAE,CAWxF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,SAAgB,IAAI,KAAG,OAAO,CAAC,YAAY,EAAE,CAOtE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,SACpB,IAAI,aACC,OAAO,eACL,MAAM,GAAG,SAAS,KAC9B,OAAO,CAAC,YAAY,EAAE,CAQxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,WAAY,SAAS,MAAM,EAAE,KAAG,YAAY,EACf,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The checks the catalogue's browser tests run on a story's frame, as problems instead of failures: axe with the
|
|
3
|
+
* catalogue's rules, spills, overlays past the frame, and the page's errors. The suite (`browserTests.ts`) expects none;
|
|
4
|
+
* `forgebook check` (`checkStories.ts`) reports them.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* The messages are the suite's own, so a problem reads the same wherever it is found. A failed play is one of the
|
|
8
|
+
* page's errors: its rejection reaches the page. The overlays check resizes the window, so it runs last of the page's
|
|
9
|
+
* checks.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import { AxeBuilder } from "@axe-core/playwright";
|
|
14
|
+
import { findSpills } from "forgebook/spills";
|
|
15
|
+
import { findOverlaysPastFrame } from "./overlays.js";
|
|
16
|
+
/**
|
|
17
|
+
* The page's errors from now on: uncaught ones and the console's, in the order they come.
|
|
18
|
+
*
|
|
19
|
+
* @param page - the page, before it opens the story.
|
|
20
|
+
* @returns the list the errors are added to.
|
|
21
|
+
*/
|
|
22
|
+
export const watchedErrors = (page) => {
|
|
23
|
+
const errors = [];
|
|
24
|
+
page.on("pageerror", (error) => errors.push(error.message));
|
|
25
|
+
page.on("console", (message) => {
|
|
26
|
+
if (message.type() === "error")
|
|
27
|
+
errors.push(message.text());
|
|
28
|
+
});
|
|
29
|
+
return errors;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* The rules of the catalogue's accessibility settings the story breaks.
|
|
33
|
+
*
|
|
34
|
+
* @param page - the story's frame page, ready.
|
|
35
|
+
* @param a11y - the catalogue's accessibility settings.
|
|
36
|
+
*/
|
|
37
|
+
export const axeProblems = async (page, a11y) => {
|
|
38
|
+
const { violations } = await new AxeBuilder({ page })
|
|
39
|
+
.withTags([...a11y.tags])
|
|
40
|
+
.disableRules([...a11y.disabledRules])
|
|
41
|
+
.analyze();
|
|
42
|
+
return violations.map((violation) => ({
|
|
43
|
+
kind: "axe",
|
|
44
|
+
rule: violation.id,
|
|
45
|
+
...(violation.nodes[0] === undefined ? {} : { element: violation.nodes[0].target.join(" ") }),
|
|
46
|
+
message: `${violation.id}: ${violation.help}`
|
|
47
|
+
}));
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* The elements that spill out of their parents.
|
|
51
|
+
*
|
|
52
|
+
* @param page - the story's frame page, ready.
|
|
53
|
+
*/
|
|
54
|
+
export const spillProblems = async (page) => {
|
|
55
|
+
const spills = await page.evaluate(findSpills, ".forgebook-frame");
|
|
56
|
+
return spills.map((spill) => ({
|
|
57
|
+
kind: "spill",
|
|
58
|
+
element: spill.element,
|
|
59
|
+
message: `${spill.element} spills out of ${spill.parent} by ${spill.by}px`
|
|
60
|
+
}));
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* The overlays the story leaves open past its frame; none in a view where they are not checked.
|
|
64
|
+
*
|
|
65
|
+
* @param page - the story's frame page, its play over.
|
|
66
|
+
* @param isChecked - whether the view checks overlays (`isOverlayChecked`).
|
|
67
|
+
* @param sceneHeight - the height the story declares, in CSS px, if any.
|
|
68
|
+
*/
|
|
69
|
+
export const overlayProblems = async (page, isChecked, sceneHeight) => {
|
|
70
|
+
if (!isChecked)
|
|
71
|
+
return [];
|
|
72
|
+
const overlays = await findOverlaysPastFrame(page, sceneHeight);
|
|
73
|
+
return overlays.map((overlay) => ({
|
|
74
|
+
kind: "overlay",
|
|
75
|
+
element: overlay.element,
|
|
76
|
+
message: `${overlay.element} ends ${overlay.by}px below the frame's ${overlay.frameHeight}px: declare parameters.height`
|
|
77
|
+
}));
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* The page's errors as problems.
|
|
81
|
+
*
|
|
82
|
+
* @param errors - the errors `watchedErrors` collected.
|
|
83
|
+
*/
|
|
84
|
+
export const errorProblems = (errors) => errors.map((message) => ({ kind: "error", message }));
|
|
85
|
+
//# sourceMappingURL=storyCheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storyCheck.js","sourceRoot":"","sources":["../../src/storyCheck.ts"],"names":[],"mappings":"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"}
|
package/dist/src/storyFiles.d.ts
CHANGED
|
@@ -11,7 +11,8 @@ export type StoryFilesOptions = {
|
|
|
11
11
|
readonly patterns: readonly string[];
|
|
12
12
|
};
|
|
13
13
|
/**
|
|
14
|
-
* The story files the patterns match, as the source's keys (
|
|
14
|
+
* The story files the patterns match, as the source's keys (the plugin's: relative to each pattern's folder once its
|
|
15
|
+
* leading `../` moved into it, `./src/x.stories.tsx`), sorted.
|
|
15
16
|
*
|
|
16
17
|
* @param options - where the files are.
|
|
17
18
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storyFiles.d.ts","sourceRoot":"","sources":["../../src/storyFiles.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAMlF,yCAAyC;AACzC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,yBAAyB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kGAAkG;IAClG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qHAAqH;IACrH,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,CAAC;
|
|
1
|
+
{"version":3,"file":"storyFiles.d.ts","sourceRoot":"","sources":["../../src/storyFiles.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAMlF,yCAAyC;AACzC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,yBAAyB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kGAAkG;IAClG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qHAAqH;IACrH,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,CAAC;AAUF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,YAAa,iBAAiB,KAAG,MAAM,EACyC,CAAC;AAExG;;;;;GAKG;AACH,eAAO,MAAM,aAAa,YAAa,iBAAiB,KAAG,WAmB1D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,YAAa,iBAAiB,UAAU,WAAW,KAAG,MAAM,EAS1F,CAAC"}
|
package/dist/src/storyFiles.js
CHANGED
|
@@ -14,13 +14,20 @@ import { join } from "node:path";
|
|
|
14
14
|
import { sourceFiles } from "forgebook/source-files";
|
|
15
15
|
import { autoTitle, patternBase } from "forgebook/vite/auto-title";
|
|
16
16
|
import { indexStoryFile } from "forgebook/vite/index-story-file";
|
|
17
|
-
import { storyFileKeys } from "forgebook/vite/story-files-module";
|
|
17
|
+
import { storyFileKeys, storyFilesGroup } from "forgebook/vite/story-files-module";
|
|
18
18
|
/**
|
|
19
|
-
* The
|
|
19
|
+
* The groups the patterns make, each read as the catalogue's plugin reads it (`storyFilesGroup`): one per pattern.
|
|
20
20
|
*
|
|
21
21
|
* @param options - where the files are.
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
const groupsOf = (options) => options.patterns.map((pattern) => storyFilesGroup(options.root, pattern));
|
|
24
|
+
/**
|
|
25
|
+
* The story files the patterns match, as the source's keys (the plugin's: relative to each pattern's folder once its
|
|
26
|
+
* leading `../` moved into it, `./src/x.stories.tsx`), sorted.
|
|
27
|
+
*
|
|
28
|
+
* @param options - where the files are.
|
|
29
|
+
*/
|
|
30
|
+
export const storyFiles = (options) => [...new Set(groupsOf(options).flatMap((group) => storyFileKeys(group.root, [group.pattern])))].sort();
|
|
24
31
|
/**
|
|
25
32
|
* A source with its index read from the disk and no loaders: enough for the story tree, the ids and the tests.
|
|
26
33
|
*
|
|
@@ -29,15 +36,18 @@ export const storyFiles = (options) => storyFileKeys(options.root, options.patte
|
|
|
29
36
|
*/
|
|
30
37
|
export const indexedSource = (options) => {
|
|
31
38
|
const index = {};
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
// as the plugin does: each pattern is one group, and a file's title comes from the first group that matches it
|
|
40
|
+
for (const group of groupsOf(options)) {
|
|
41
|
+
for (const file of storyFileKeys(group.root, [group.pattern])) {
|
|
42
|
+
if (index[file] !== undefined)
|
|
43
|
+
continue;
|
|
44
|
+
const title = autoTitle(patternBase(group.pattern), file);
|
|
45
|
+
const text = readFileSync(join(group.root, file), "utf8");
|
|
46
|
+
const entry = indexStoryFile(file, text, title === undefined ? {} : { autoTitle: title });
|
|
47
|
+
if (typeof entry === "string")
|
|
48
|
+
throw new Error(entry);
|
|
49
|
+
index[file] = entry;
|
|
50
|
+
}
|
|
41
51
|
}
|
|
42
52
|
return {
|
|
43
53
|
id: options.sourceId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storyFiles.js","sourceRoot":"","sources":["../../src/storyFiles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,
|
|
1
|
+
{"version":3,"file":"storyFiles.js","sourceRoot":"","sources":["../../src/storyFiles.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stories a check or a picture run asks for, opened as the catalogue's browser tests open them: each story in each
|
|
3
|
+
* view (or every variant the tests check), its clock held, on its page's own colour, the window as wide as the view's
|
|
4
|
+
* width, one browser for the run and a context of its own per page.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Shared by `checkStories.ts` and `shotStories.ts`, which `forgebook check` and `forgebook shot` load from the project.
|
|
8
|
+
* A frame that never says it is ready is told apart from one that says it failed, so a story stuck loading is never
|
|
9
|
+
* taken for one that passed.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import { type Page } from "@playwright/test";
|
|
14
|
+
import type { StoryCheckRequest, StoryCheckStory } from "forgebook/story-check";
|
|
15
|
+
import { type ViewState } from "forgebook/view-state";
|
|
16
|
+
/** How long a frame may take to say it is ready, in ms. */
|
|
17
|
+
export declare const READY_MS = 30000;
|
|
18
|
+
/** One story in one view: what to open and how. */
|
|
19
|
+
export type StoryPage = {
|
|
20
|
+
/** The story. */
|
|
21
|
+
readonly story: StoryCheckStory;
|
|
22
|
+
/** The view's name in the report: as asked, or the variant's. */
|
|
23
|
+
readonly name: string;
|
|
24
|
+
/** The view, on the page's own colour. */
|
|
25
|
+
readonly view: ViewState;
|
|
26
|
+
/** The window's width, when the view sets one. */
|
|
27
|
+
readonly width: number | undefined;
|
|
28
|
+
/** The frame's address in that view, its clock held. */
|
|
29
|
+
readonly frame: string;
|
|
30
|
+
};
|
|
31
|
+
/** What a frame said once opened: ready, failed, or nothing in time. */
|
|
32
|
+
export type FrameStatus = "ready" | "error" | "silent";
|
|
33
|
+
/**
|
|
34
|
+
* Every story in every view a request names, in its order.
|
|
35
|
+
*
|
|
36
|
+
* @param request - the request.
|
|
37
|
+
*/
|
|
38
|
+
export declare const storyPagesOf: (request: StoryCheckRequest) => StoryPage[];
|
|
39
|
+
/**
|
|
40
|
+
* Opens a story's frame in its window and waits until it says it is ready or that it failed.
|
|
41
|
+
*
|
|
42
|
+
* @param page - a fresh page.
|
|
43
|
+
* @param storyPage - the story and the view.
|
|
44
|
+
*/
|
|
45
|
+
export declare const openedStory: (page: Page, storyPage: StoryPage) => Promise<FrameStatus>;
|
|
46
|
+
/**
|
|
47
|
+
* Visits every story page of a request on one browser, each on a page in a context of its own (axe asks for one, and no
|
|
48
|
+
* story's storage reaches the next).
|
|
49
|
+
*
|
|
50
|
+
* @param request - the request.
|
|
51
|
+
* @param visit - what to do on each: its answer is collected.
|
|
52
|
+
* @returns the answers, in the request's order.
|
|
53
|
+
*/
|
|
54
|
+
export declare const eachStoryPage: <TResult>(request: StoryCheckRequest, visit: (page: Page, storyPage: StoryPage) => Promise<TResult>) => Promise<TResult[]>;
|
|
55
|
+
//# sourceMappingURL=storyPages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storyPages.d.ts","sourceRoot":"","sources":["../../src/storyPages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAY,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEhF,OAAO,EAAwC,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAO5F,2DAA2D;AAC3D,eAAO,MAAM,QAAQ,QAAS,CAAC;AAE/B,mDAAmD;AACnD,MAAM,MAAM,SAAS,GAAG;IACtB,iBAAiB;IACjB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,wEAAwE;AACxE,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AAyBvD;;;;GAIG;AACH,eAAO,MAAM,YAAY,YAAa,iBAAiB,KAAG,SAAS,EAclE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,SAAgB,IAAI,aAAa,SAAS,KAAG,OAAO,CAAC,WAAW,CAavF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAU,OAAO,WAChC,iBAAiB,SACnB,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,OAAO,CAAC,KAC5D,OAAO,CAAC,OAAO,EAAE,CAgBnB,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stories a check or a picture run asks for, opened as the catalogue's browser tests open them: each story in each
|
|
3
|
+
* view (or every variant the tests check), its clock held, on its page's own colour, the window as wide as the view's
|
|
4
|
+
* width, one browser for the run and a context of its own per page.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Shared by `checkStories.ts` and `shotStories.ts`, which `forgebook check` and `forgebook shot` load from the project.
|
|
8
|
+
* A frame that never says it is ready is told apart from one that says it failed, so a story stuck loading is never
|
|
9
|
+
* taken for one that passed.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import { chromium } from "@playwright/test";
|
|
14
|
+
import { catalogueSettings } from "forgebook/catalogue";
|
|
15
|
+
import { STATUS_ATTRIBUTE } from "forgebook/frame-status";
|
|
16
|
+
import { heldClockAddress } from "forgebook/story-clock";
|
|
17
|
+
import { defaultView, frameAddress, parseView } from "forgebook/view-state";
|
|
18
|
+
import { storyVariants } from "./browserTests.js";
|
|
19
|
+
/** The window's size when a view sets no width, in CSS px: the browser tests' own. */
|
|
20
|
+
const WINDOW = { width: 1280, height: 800 };
|
|
21
|
+
/** How long a frame may take to say it is ready, in ms. */
|
|
22
|
+
export const READY_MS = 30_000;
|
|
23
|
+
/**
|
|
24
|
+
* The views a request names: every variant of the browser tests, or each view given (the default view without any).
|
|
25
|
+
*
|
|
26
|
+
* @param request - the request.
|
|
27
|
+
*/
|
|
28
|
+
const viewsOf = (request) => {
|
|
29
|
+
const catalogue = catalogueSettings("", request.switches, request.lists);
|
|
30
|
+
const defaults = defaultView(catalogue);
|
|
31
|
+
if (request.isAllVariants)
|
|
32
|
+
return storyVariants(request.switches).map((variant) => ({
|
|
33
|
+
name: variant.name,
|
|
34
|
+
view: { ...defaults, ...variant.view, switches: { ...defaults.switches, ...variant.view.switches } },
|
|
35
|
+
width: variant.width
|
|
36
|
+
}));
|
|
37
|
+
const queries = request.views.length === 0 ? [""] : request.views;
|
|
38
|
+
return queries.map((query) => {
|
|
39
|
+
const view = parseView(query, catalogue);
|
|
40
|
+
return { name: query, view, width: view.width === "fill" ? undefined : view.width };
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Every story in every view a request names, in its order.
|
|
45
|
+
*
|
|
46
|
+
* @param request - the request.
|
|
47
|
+
*/
|
|
48
|
+
export const storyPagesOf = (request) => {
|
|
49
|
+
const views = viewsOf(request);
|
|
50
|
+
return request.stories.flatMap((story) => views.map(({ name, view, width }) => {
|
|
51
|
+
const shown = { ...view, backdrop: "plain" };
|
|
52
|
+
return {
|
|
53
|
+
story,
|
|
54
|
+
name,
|
|
55
|
+
view: shown,
|
|
56
|
+
width,
|
|
57
|
+
frame: heldClockAddress(frameAddress(request.frameUrl, story.id, shown, request.switches))
|
|
58
|
+
};
|
|
59
|
+
}));
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Opens a story's frame in its window and waits until it says it is ready or that it failed.
|
|
63
|
+
*
|
|
64
|
+
* @param page - a fresh page.
|
|
65
|
+
* @param storyPage - the story and the view.
|
|
66
|
+
*/
|
|
67
|
+
export const openedStory = async (page, storyPage) => {
|
|
68
|
+
await page.setViewportSize({ width: storyPage.width ?? WINDOW.width, height: WINDOW.height });
|
|
69
|
+
await page.goto(storyPage.frame);
|
|
70
|
+
try {
|
|
71
|
+
await page.waitForFunction((attribute) => ["ready", "error"].includes(document.documentElement.getAttribute(attribute) ?? ""), STATUS_ATTRIBUTE, { timeout: READY_MS });
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return "silent";
|
|
75
|
+
}
|
|
76
|
+
return (await page.locator("html").getAttribute(STATUS_ATTRIBUTE)) === "ready" ? "ready" : "error";
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Visits every story page of a request on one browser, each on a page in a context of its own (axe asks for one, and no
|
|
80
|
+
* story's storage reaches the next).
|
|
81
|
+
*
|
|
82
|
+
* @param request - the request.
|
|
83
|
+
* @param visit - what to do on each: its answer is collected.
|
|
84
|
+
* @returns the answers, in the request's order.
|
|
85
|
+
*/
|
|
86
|
+
export const eachStoryPage = async (request, visit) => {
|
|
87
|
+
const browser = await chromium.launch();
|
|
88
|
+
try {
|
|
89
|
+
const answers = [];
|
|
90
|
+
for (const storyPage of storyPagesOf(request)) {
|
|
91
|
+
const context = await browser.newContext();
|
|
92
|
+
try {
|
|
93
|
+
answers.push(await visit(await context.newPage(), storyPage));
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
await context.close();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return answers;
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
await browser.close();
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=storyPages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storyPages.js","sourceRoot":"","sources":["../../src/storyPages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type TouchWindowRequest } from "forgebook/real-touch";
|
|
2
|
+
/**
|
|
3
|
+
* Opens the catalogue in a touch window and waits until the person closes it.
|
|
4
|
+
*
|
|
5
|
+
* @param request - the catalogue's address.
|
|
6
|
+
*/
|
|
7
|
+
export declare const openTouchWindow: (request: TouchWindowRequest) => Promise<void>;
|
|
8
|
+
//# sourceMappingURL=touchWindow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"touchWindow.d.ts","sourceRoot":"","sources":["../../src/touchWindow.ts"],"names":[],"mappings":"AAcA,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAwBhF;;;;GAIG;AACH,eAAO,MAAM,eAAe,YAAmB,kBAAkB,KAAG,OAAO,CAAC,IAAI,CAqB/E,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The window `forgebook dev --touch` opens: the catalogue in a Chromium of Playwright's, with Chromium's own touch
|
|
3
|
+
* emulation, so the mouse makes real touch events (trusted, with the browser's own scrolling) where the catalogue's
|
|
4
|
+
* Touch switch can only simulate them.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Loaded from the project by the command only when it runs, as the check is, so the core needs no browser. The
|
|
8
|
+
* emulation is turned on through the browser's protocol (CDP) in every page of the window, popups included, and the
|
|
9
|
+
* pages are marked (`forgebook/real-touch`) so the catalogue's simulated touch stays off there. Still a computer: no
|
|
10
|
+
* virtual keyboard, no viewport shrinking under it, no iOS Safari.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import { chromium } from "@playwright/test";
|
|
15
|
+
import { REAL_TOUCH_FLAG } from "forgebook/real-touch";
|
|
16
|
+
/** How many fingers the emulation offers. */
|
|
17
|
+
const MAX_TOUCH_POINTS = 5;
|
|
18
|
+
/** The pages whose emulation is on: the first page is turned on before it loads, and the context then reports it. */
|
|
19
|
+
const emulated = new WeakSet();
|
|
20
|
+
/**
|
|
21
|
+
* Turns Chromium's touch emulation on in a page: the mouse's presses become touches, as in DevTools' device mode.
|
|
22
|
+
*
|
|
23
|
+
* @param page - the page.
|
|
24
|
+
*/
|
|
25
|
+
const emulateTouch = async (page) => {
|
|
26
|
+
if (emulated.has(page))
|
|
27
|
+
return;
|
|
28
|
+
emulated.add(page);
|
|
29
|
+
const session = await page.context().newCDPSession(page);
|
|
30
|
+
await session.send("Emulation.setTouchEmulationEnabled", {
|
|
31
|
+
enabled: true,
|
|
32
|
+
maxTouchPoints: MAX_TOUCH_POINTS
|
|
33
|
+
});
|
|
34
|
+
await session.send("Emulation.setEmitTouchEventsForMouse", { enabled: true, configuration: "mobile" });
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Opens the catalogue in a touch window and waits until the person closes it.
|
|
38
|
+
*
|
|
39
|
+
* @param request - the catalogue's address.
|
|
40
|
+
*/
|
|
41
|
+
export const openTouchWindow = async (request) => {
|
|
42
|
+
const browser = await chromium.launch({ headless: false });
|
|
43
|
+
// the window's own size, not a fixed viewport: the person resizes it as they like
|
|
44
|
+
const context = await browser.newContext({ viewport: null, hasTouch: true });
|
|
45
|
+
await context.addInitScript((flag) => {
|
|
46
|
+
Object.defineProperty(window, flag, { value: true });
|
|
47
|
+
}, REAL_TOUCH_FLAG);
|
|
48
|
+
context.on("page", (page) => {
|
|
49
|
+
void emulateTouch(page);
|
|
50
|
+
});
|
|
51
|
+
const page = await context.newPage();
|
|
52
|
+
await emulateTouch(page);
|
|
53
|
+
await page.goto(request.url);
|
|
54
|
+
await new Promise((done) => {
|
|
55
|
+
browser.on("disconnected", () => done());
|
|
56
|
+
// the last page closed closes the window
|
|
57
|
+
context.on("close", () => done());
|
|
58
|
+
page.on("close", () => {
|
|
59
|
+
if (context.pages().length === 0)
|
|
60
|
+
void browser.close();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=touchWindow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"touchWindow.js","sourceRoot":"","sources":["../../src/touchWindow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,QAAQ,EAAa,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,eAAe,EAA2B,MAAM,sBAAsB,CAAC;AAEhF,6CAA6C;AAC7C,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B,qHAAqH;AACrH,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;AAErC;;;;GAIG;AACH,MAAM,YAAY,GAAG,KAAK,EAAE,IAAU,EAAiB,EAAE;IACvD,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IAC/B,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACzD,MAAM,OAAO,CAAC,IAAI,CAAC,oCAAoC,EAAE;QACvD,OAAO,EAAE,IAAI;QACb,cAAc,EAAE,gBAAgB;KACjC,CAAC,CAAC;IACH,MAAM,OAAO,CAAC,IAAI,CAAC,sCAAsC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC;AACzG,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,OAA2B,EAAiB,EAAE;IAClF,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3D,kFAAkF;IAClF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7E,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC,IAAY,EAAQ,EAAE;QACjD,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC,EAAE,eAAe,CAAC,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAU,EAAQ,EAAE;QACtC,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IACrC,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,EAAE;QAC/B,OAAO,CAAC,EAAE,CAAC,cAAc,EAAE,GAAS,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/C,yCAAyC;QACzC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAS,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAS,EAAE;YAC1B,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,MAAM,KAAK,CAAC;gBAAE,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgebook/testing",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
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": {
|
|
@@ -51,18 +51,30 @@
|
|
|
51
51
|
"types": "./dist/src/overlays.d.ts",
|
|
52
52
|
"default": "./dist/src/overlays.js"
|
|
53
53
|
},
|
|
54
|
+
"./check": {
|
|
55
|
+
"types": "./dist/src/checkStories.d.ts",
|
|
56
|
+
"default": "./dist/src/checkStories.js"
|
|
57
|
+
},
|
|
58
|
+
"./shot": {
|
|
59
|
+
"types": "./dist/src/shotStories.d.ts",
|
|
60
|
+
"default": "./dist/src/shotStories.js"
|
|
61
|
+
},
|
|
62
|
+
"./touch": {
|
|
63
|
+
"types": "./dist/src/touchWindow.d.ts",
|
|
64
|
+
"default": "./dist/src/touchWindow.js"
|
|
65
|
+
},
|
|
54
66
|
"./fonts.css": "./dist/src/fonts/fonts.css"
|
|
55
67
|
},
|
|
56
68
|
"dependencies": {
|
|
57
69
|
"@axe-core/playwright": "4.14.0",
|
|
58
70
|
"@ensiria/cli-kit": "^0.1.1",
|
|
59
|
-
"@forgebook/story-format": "0.1.
|
|
71
|
+
"@forgebook/story-format": "0.1.3"
|
|
60
72
|
},
|
|
61
73
|
"peerDependencies": {
|
|
62
74
|
"@playwright/test": "^1.64.0",
|
|
63
75
|
"vite": "^8.0.0",
|
|
64
76
|
"vitest": "^5.0.0",
|
|
65
|
-
"forgebook": "^0.1.
|
|
77
|
+
"forgebook": "^0.1.5"
|
|
66
78
|
},
|
|
67
79
|
"devDependencies": {
|
|
68
80
|
"@playwright/test": "1.64.1",
|
|
@@ -72,8 +84,8 @@
|
|
|
72
84
|
"vite": "8.3.5",
|
|
73
85
|
"vitest": "5.0.5",
|
|
74
86
|
"@forgebook/tools": "0.0.0",
|
|
75
|
-
"forgebook": "0.
|
|
76
|
-
"
|
|
87
|
+
"@forgebook/typescript-config": "0.0.0",
|
|
88
|
+
"forgebook": "0.1.5"
|
|
77
89
|
},
|
|
78
90
|
"publishConfig": {
|
|
79
91
|
"access": "public"
|
package/dist/src/spills.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The elements of a story that spill out of their parent: what overlaps a neighbour or runs off the frame when the
|
|
3
|
-
* story is narrower than it was drawn for.
|
|
4
|
-
*
|
|
5
|
-
* @remarks
|
|
6
|
-
* Runs in the story's page (`page.evaluate`), so it takes no import. An element spills when its box reaches past its
|
|
7
|
-
* parent's box by more than a pixel, sideways, and the parent shows its overflow: a parent that clips or scrolls
|
|
8
|
-
* (`overflow` other than `visible`) and an element taken out of the flow (`absolute`, `fixed`) are left out, as is
|
|
9
|
-
* anything inside a frame-level layer (`data-forgebook-allow-spill`, for a story that shows a spill on purpose).
|
|
10
|
-
*
|
|
11
|
-
* @module
|
|
12
|
-
*/
|
|
13
|
-
/** One spill: the element, its parent, and by how many pixels it reaches past. */
|
|
14
|
-
export type Spill = {
|
|
15
|
-
/** The element, as a short CSS path (`div.story-settings`). */
|
|
16
|
-
readonly element: string;
|
|
17
|
-
/** Its parent, the same way. */
|
|
18
|
-
readonly parent: string;
|
|
19
|
-
/** How far it reaches past the parent, in CSS px. */
|
|
20
|
-
readonly by: number;
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* The spills inside a root, measured in the page.
|
|
24
|
-
*
|
|
25
|
-
* @param rootSelector - the story's root (`.forgebook-frame`).
|
|
26
|
-
*/
|
|
27
|
-
export declare const findSpills: (rootSelector: string) => Spill[];
|
|
28
|
-
//# sourceMappingURL=spills.d.ts.map
|
package/dist/src/spills.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spills.d.ts","sourceRoot":"","sources":["../../src/spills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,kFAAkF;AAClF,MAAM,MAAM,KAAK,GAAG;IAClB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gCAAgC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,iBAAkB,MAAM,KAAG,KAAK,EAgCtD,CAAC"}
|
package/dist/src/spills.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The elements of a story that spill out of their parent: what overlaps a neighbour or runs off the frame when the
|
|
3
|
-
* story is narrower than it was drawn for.
|
|
4
|
-
*
|
|
5
|
-
* @remarks
|
|
6
|
-
* Runs in the story's page (`page.evaluate`), so it takes no import. An element spills when its box reaches past its
|
|
7
|
-
* parent's box by more than a pixel, sideways, and the parent shows its overflow: a parent that clips or scrolls
|
|
8
|
-
* (`overflow` other than `visible`) and an element taken out of the flow (`absolute`, `fixed`) are left out, as is
|
|
9
|
-
* anything inside a frame-level layer (`data-forgebook-allow-spill`, for a story that shows a spill on purpose).
|
|
10
|
-
*
|
|
11
|
-
* @module
|
|
12
|
-
*/
|
|
13
|
-
/**
|
|
14
|
-
* The spills inside a root, measured in the page.
|
|
15
|
-
*
|
|
16
|
-
* @param rootSelector - the story's root (`.forgebook-frame`).
|
|
17
|
-
*/
|
|
18
|
-
export const findSpills = (rootSelector) => {
|
|
19
|
-
const pathOf = (element) => {
|
|
20
|
-
const classes = [...element.classList].slice(0, 2).join(".");
|
|
21
|
-
return classes === "" ? element.tagName.toLowerCase() : `${element.tagName.toLowerCase()}.${classes}`;
|
|
22
|
-
};
|
|
23
|
-
// an element out of the flow, a parent that clips or scrolls, and an allowed spill are not measured
|
|
24
|
-
const isMeasured = (element, parent) => {
|
|
25
|
-
if (element.closest("[data-forgebook-allow-spill]") !== null)
|
|
26
|
-
return false;
|
|
27
|
-
const style = getComputedStyle(element);
|
|
28
|
-
const parentStyle = getComputedStyle(parent);
|
|
29
|
-
return (style.position !== "absolute" &&
|
|
30
|
-
style.position !== "fixed" &&
|
|
31
|
-
style.display !== "contents" &&
|
|
32
|
-
parentStyle.display !== "contents" &&
|
|
33
|
-
parentStyle.overflowX === "visible");
|
|
34
|
-
};
|
|
35
|
-
const overreach = (element, parent) => {
|
|
36
|
-
const box = element.getBoundingClientRect();
|
|
37
|
-
const parentBox = parent.getBoundingClientRect();
|
|
38
|
-
if (box.width === 0 || box.height === 0)
|
|
39
|
-
return 0;
|
|
40
|
-
return Math.max(box.right - parentBox.right, parentBox.left - box.left);
|
|
41
|
-
};
|
|
42
|
-
const root = document.querySelector(rootSelector);
|
|
43
|
-
if (root === null)
|
|
44
|
-
return [];
|
|
45
|
-
return [...root.querySelectorAll("*")].flatMap((element) => {
|
|
46
|
-
const parent = element.parentElement;
|
|
47
|
-
if (parent === null || !isMeasured(element, parent))
|
|
48
|
-
return [];
|
|
49
|
-
const by = overreach(element, parent);
|
|
50
|
-
return by > 1 ? [{ element: pathOf(element), parent: pathOf(parent), by: Math.round(by) }] : [];
|
|
51
|
-
});
|
|
52
|
-
};
|
|
53
|
-
//# sourceMappingURL=spills.js.map
|
package/dist/src/spills.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spills.js","sourceRoot":"","sources":["../../src/spills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAYH;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,YAAoB,EAAW,EAAE;IAC1D,MAAM,MAAM,GAAG,CAAC,OAAgB,EAAU,EAAE;QAC1C,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,OAAO,EAAE,CAAC;IACxG,CAAC,CAAC;IACF,oGAAoG;IACpG,MAAM,UAAU,GAAG,CAAC,OAAgB,EAAE,MAAe,EAAW,EAAE;QAChE,IAAI,OAAO,CAAC,OAAO,CAAC,8BAA8B,CAAC,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QAC3E,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,WAAW,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC7C,OAAO,CACL,KAAK,CAAC,QAAQ,KAAK,UAAU;YAC7B,KAAK,CAAC,QAAQ,KAAK,OAAO;YAC1B,KAAK,CAAC,OAAO,KAAK,UAAU;YAC5B,WAAW,CAAC,OAAO,KAAK,UAAU;YAClC,WAAW,CAAC,SAAS,KAAK,SAAS,CACpC,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,SAAS,GAAG,CAAC,OAAgB,EAAE,MAAe,EAAU,EAAE;QAC9D,MAAM,GAAG,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;QAC5C,MAAM,SAAS,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;QACjD,IAAI,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1E,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAClD,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC7B,OAAO,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACzD,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;QACrC,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC;YAAE,OAAO,EAAE,CAAC;QAC/D,MAAM,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACtC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClG,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
|