@lullabot/playwright-testing 0.1.0 → 1.0.1

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 (68) hide show
  1. package/bin/github-a11y-summary +2 -2
  2. package/bin/github-failure-summary +4 -4
  3. package/lib/accessibility-baseline-file.d.ts +6 -6
  4. package/lib/accessibility-baseline-file.js +29 -23
  5. package/lib/accessibility-baseline.js +5 -3
  6. package/lib/accessible-screenshot.d.ts +4 -4
  7. package/lib/accessible-screenshot.js +88 -76
  8. package/lib/focus.js +4 -1
  9. package/lib/frames.js +4 -4
  10. package/lib/github/a11y-summary.js +74 -79
  11. package/lib/github/attachments.d.ts +1 -1
  12. package/lib/github/attachments.js +36 -34
  13. package/lib/github/failure-summary.d.ts +4 -4
  14. package/lib/github/failure-summary.js +139 -107
  15. package/lib/github/index.d.ts +6 -6
  16. package/lib/github/report-paths.js +17 -9
  17. package/lib/hover.js +17 -17
  18. package/lib/images.js +15 -12
  19. package/lib/index.d.ts +13 -13
  20. package/lib/interaction-states.d.ts +2 -2
  21. package/lib/interaction-states.js +7 -7
  22. package/lib/mock/index.d.ts +1 -1
  23. package/lib/mock/youtube.d.ts +1 -1
  24. package/lib/mock/youtube.js +1 -1
  25. package/lib/pseudo-state.d.ts +2 -2
  26. package/lib/pseudo-state.js +15 -7
  27. package/lib/videos.js +21 -10
  28. package/lib/visualdiff.d.ts +4 -4
  29. package/lib/visualdiff.js +35 -27
  30. package/package.json +3 -3
  31. package/src/accessibility-baseline-file.test.ts +190 -154
  32. package/src/accessibility-baseline-file.ts +107 -83
  33. package/src/accessibility-baseline.test.ts +633 -433
  34. package/src/accessibility-baseline.ts +41 -21
  35. package/src/accessible-screenshot.test.ts +551 -423
  36. package/src/accessible-screenshot.ts +334 -245
  37. package/src/focus.test.ts +23 -23
  38. package/src/focus.ts +7 -2
  39. package/src/fonts.test.ts +13 -13
  40. package/src/fonts.ts +1 -1
  41. package/src/frames.test.ts +10 -8
  42. package/src/frames.ts +5 -5
  43. package/src/github/a11y-summary.test.ts +436 -332
  44. package/src/github/a11y-summary.ts +189 -179
  45. package/src/github/attachments.test.ts +228 -167
  46. package/src/github/attachments.ts +144 -121
  47. package/src/github/failure-summary.test.ts +659 -445
  48. package/src/github/failure-summary.ts +376 -274
  49. package/src/github/index.test.ts +14 -14
  50. package/src/github/index.ts +6 -6
  51. package/src/github/report-paths.test.ts +211 -156
  52. package/src/github/report-paths.ts +75 -61
  53. package/src/hover.test.ts +50 -46
  54. package/src/hover.ts +18 -18
  55. package/src/images.test.ts +251 -206
  56. package/src/images.ts +52 -43
  57. package/src/index.ts +13 -13
  58. package/src/interaction-states.test.ts +72 -42
  59. package/src/interaction-states.ts +43 -29
  60. package/src/mock/index.ts +1 -1
  61. package/src/mock/youtube.test.ts +26 -26
  62. package/src/mock/youtube.ts +4 -6
  63. package/src/pseudo-state.test.ts +58 -51
  64. package/src/pseudo-state.ts +32 -27
  65. package/src/videos.test.ts +559 -399
  66. package/src/videos.ts +68 -44
  67. package/src/visualdiff.test.ts +416 -315
  68. package/src/visualdiff.ts +140 -99
@@ -1,83 +1,90 @@
1
- import {describe, expect, it, vi} from 'vitest'
2
- import {forcePseudoState} from './pseudo-state'
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { forcePseudoState } from "./pseudo-state";
3
3
 
4
4
  function fakePage(nodeId = 2) {
5
5
  const session = {
6
6
  send: vi.fn(async (method: string) => {
7
- if (method === 'DOM.getDocument') {
8
- return {root: {nodeId: 1}}
7
+ if (method === "DOM.getDocument") {
8
+ return { root: { nodeId: 1 } };
9
9
  }
10
- if (method === 'DOM.querySelector') {
11
- return {nodeId}
10
+ if (method === "DOM.querySelector") {
11
+ return { nodeId };
12
12
  }
13
- return {}
13
+ return {};
14
14
  }),
15
15
  detach: vi.fn().mockResolvedValue(undefined),
16
- }
16
+ };
17
17
  const context = {
18
18
  newCDPSession: vi.fn().mockResolvedValue(session),
19
- }
19
+ };
20
20
  const page = {
21
21
  context: vi.fn(() => context),
22
- }
22
+ };
23
23
 
24
- return {context, page, session}
24
+ return { context, page, session };
25
25
  }
26
26
 
27
- describe('forcePseudoState', () => {
28
- it('forces pseudo-classes on the first selector match and clears them', async () => {
29
- const {context, page, session} = fakePage()
27
+ describe("forcePseudoState", () => {
28
+ it("forces pseudo-classes on the first selector match and clears them", async () => {
29
+ const { context, page, session } = fakePage();
30
30
 
31
- const cleanup = await forcePseudoState(page as any, '.menu-trigger', ['hover', 'focus-visible'])
31
+ const cleanup = await forcePseudoState(page as any, ".menu-trigger", [
32
+ "hover",
33
+ "focus-visible",
34
+ ]);
32
35
 
33
- expect(context.newCDPSession).toHaveBeenCalledWith(page)
34
- expect(session.send).toHaveBeenNthCalledWith(1, 'DOM.enable')
35
- expect(session.send).toHaveBeenNthCalledWith(2, 'CSS.enable')
36
- expect(session.send).toHaveBeenNthCalledWith(3, 'DOM.getDocument')
37
- expect(session.send).toHaveBeenNthCalledWith(4, 'DOM.querySelector', {
36
+ expect(context.newCDPSession).toHaveBeenCalledWith(page);
37
+ expect(session.send).toHaveBeenNthCalledWith(1, "DOM.enable");
38
+ expect(session.send).toHaveBeenNthCalledWith(2, "CSS.enable");
39
+ expect(session.send).toHaveBeenNthCalledWith(3, "DOM.getDocument");
40
+ expect(session.send).toHaveBeenNthCalledWith(4, "DOM.querySelector", {
38
41
  nodeId: 1,
39
- selector: '.menu-trigger',
40
- })
41
- expect(session.send).toHaveBeenNthCalledWith(5, 'CSS.forcePseudoState', {
42
+ selector: ".menu-trigger",
43
+ });
44
+ expect(session.send).toHaveBeenNthCalledWith(5, "CSS.forcePseudoState", {
42
45
  nodeId: 2,
43
- forcedPseudoClasses: ['hover', 'focus-visible'],
44
- })
46
+ forcedPseudoClasses: ["hover", "focus-visible"],
47
+ });
45
48
 
46
- await cleanup()
47
- await cleanup()
49
+ await cleanup();
50
+ await cleanup();
48
51
 
49
- expect(session.send).toHaveBeenNthCalledWith(6, 'CSS.forcePseudoState', {
52
+ expect(session.send).toHaveBeenNthCalledWith(6, "CSS.forcePseudoState", {
50
53
  nodeId: 2,
51
54
  forcedPseudoClasses: [],
52
- })
53
- expect(session.detach).toHaveBeenCalledOnce()
54
- })
55
+ });
56
+ expect(session.detach).toHaveBeenCalledOnce();
57
+ });
55
58
 
56
- it('fails clearly and detaches when the selector does not match', async () => {
57
- const {page, session} = fakePage(0)
59
+ it("fails clearly and detaches when the selector does not match", async () => {
60
+ const { page, session } = fakePage(0);
58
61
 
59
- await expect(forcePseudoState(page as any, '.missing', ['hover']))
60
- .rejects.toThrow('could not find an element matching ".missing"')
61
- expect(session.detach).toHaveBeenCalledOnce()
62
- })
62
+ await expect(
63
+ forcePseudoState(page as any, ".missing", ["hover"]),
64
+ ).rejects.toThrow('could not find an element matching ".missing"');
65
+ expect(session.detach).toHaveBeenCalledOnce();
66
+ });
63
67
 
64
- it('reports that CDP requires Chromium', async () => {
68
+ it("reports that CDP requires Chromium", async () => {
65
69
  const page = {
66
70
  context: () => ({
67
- newCDPSession: vi.fn().mockRejectedValue(new Error('CDP only supported in Chromium')),
71
+ newCDPSession: vi
72
+ .fn()
73
+ .mockRejectedValue(new Error("CDP only supported in Chromium")),
68
74
  }),
69
- }
75
+ };
70
76
 
71
- await expect(forcePseudoState(page as any, 'button', ['focus']))
72
- .rejects.toThrow('requires a Chromium browser project')
73
- })
77
+ await expect(
78
+ forcePseudoState(page as any, "button", ["focus"]),
79
+ ).rejects.toThrow("requires a Chromium browser project");
80
+ });
74
81
 
75
- it('detaches even when clearing the state fails', async () => {
76
- const {page, session} = fakePage()
77
- const cleanup = await forcePseudoState(page as any, 'button', ['focus'])
78
- session.send.mockRejectedValueOnce(new Error('node disappeared'))
82
+ it("detaches even when clearing the state fails", async () => {
83
+ const { page, session } = fakePage();
84
+ const cleanup = await forcePseudoState(page as any, "button", ["focus"]);
85
+ session.send.mockRejectedValueOnce(new Error("node disappeared"));
79
86
 
80
- await expect(cleanup()).rejects.toThrow('node disappeared')
81
- expect(session.detach).toHaveBeenCalledOnce()
82
- })
83
- })
87
+ await expect(cleanup()).rejects.toThrow("node disappeared");
88
+ expect(session.detach).toHaveBeenCalledOnce();
89
+ });
90
+ });
@@ -1,18 +1,13 @@
1
- import {Page} from '@playwright/test'
1
+ import { Page } from "@playwright/test";
2
2
 
3
3
  /** Pseudo-classes supported by Chromium's CSS.forcePseudoState command. */
4
4
  export type ForcedPseudoClass =
5
- | 'active'
6
- | 'focus'
7
- | 'focus-visible'
8
- | 'focus-within'
9
- | 'hover'
10
- | 'target'
5
+ "active" | "focus" | "focus-visible" | "focus-within" | "hover" | "target";
11
6
 
12
7
  /** A CSS selector and the pseudo-classes to force on its first match. */
13
8
  export interface ForcedPseudoState {
14
- selector: string
15
- pseudoClasses: ForcedPseudoClass[]
9
+ selector: string;
10
+ pseudoClasses: ForcedPseudoClass[];
16
11
  }
17
12
 
18
13
  /**
@@ -28,42 +23,52 @@ export async function forcePseudoState(
28
23
  selector: string,
29
24
  pseudoClasses: ForcedPseudoClass[],
30
25
  ): Promise<() => Promise<void>> {
31
- let session
26
+ let session;
32
27
  try {
33
- session = await page.context().newCDPSession(page)
28
+ session = await page.context().newCDPSession(page);
34
29
  } catch (error) {
35
- throw new Error('forcePseudoState() requires a Chromium browser project.', {cause: error})
30
+ throw new Error("forcePseudoState() requires a Chromium browser project.", {
31
+ cause: error,
32
+ });
36
33
  }
37
34
 
38
35
  try {
39
- await session.send('DOM.enable')
40
- await session.send('CSS.enable')
41
- const {root} = await session.send('DOM.getDocument')
42
- const {nodeId} = await session.send('DOM.querySelector', {
36
+ await session.send("DOM.enable");
37
+ await session.send("CSS.enable");
38
+ const { root } = await session.send("DOM.getDocument");
39
+ const { nodeId } = await session.send("DOM.querySelector", {
43
40
  nodeId: root.nodeId,
44
41
  selector,
45
- })
42
+ });
46
43
 
47
44
  if (!nodeId) {
48
- throw new Error(`forcePseudoState() could not find an element matching "${selector}".`)
45
+ throw new Error(
46
+ `forcePseudoState() could not find an element matching "${selector}".`,
47
+ );
49
48
  }
50
49
 
51
- await session.send('CSS.forcePseudoState', {nodeId, forcedPseudoClasses: pseudoClasses})
50
+ await session.send("CSS.forcePseudoState", {
51
+ nodeId,
52
+ forcedPseudoClasses: pseudoClasses,
53
+ });
52
54
 
53
- let cleared = false
55
+ let cleared = false;
54
56
  return async () => {
55
57
  if (cleared) {
56
- return
58
+ return;
57
59
  }
58
- cleared = true
60
+ cleared = true;
59
61
  try {
60
- await session.send('CSS.forcePseudoState', {nodeId, forcedPseudoClasses: []})
62
+ await session.send("CSS.forcePseudoState", {
63
+ nodeId,
64
+ forcedPseudoClasses: [],
65
+ });
61
66
  } finally {
62
- await session.detach()
67
+ await session.detach();
63
68
  }
64
- }
69
+ };
65
70
  } catch (error) {
66
- await session.detach()
67
- throw error
71
+ await session.detach();
72
+ throw error;
68
73
  }
69
74
  }