@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.
- package/bin/github-a11y-summary +2 -2
- package/bin/github-failure-summary +4 -4
- package/lib/accessibility-baseline-file.d.ts +6 -6
- package/lib/accessibility-baseline-file.js +29 -23
- package/lib/accessibility-baseline.js +5 -3
- package/lib/accessible-screenshot.d.ts +4 -4
- package/lib/accessible-screenshot.js +88 -76
- package/lib/focus.js +4 -1
- package/lib/frames.js +4 -4
- package/lib/github/a11y-summary.js +74 -79
- package/lib/github/attachments.d.ts +1 -1
- package/lib/github/attachments.js +36 -34
- package/lib/github/failure-summary.d.ts +4 -4
- package/lib/github/failure-summary.js +139 -107
- package/lib/github/index.d.ts +6 -6
- package/lib/github/report-paths.js +17 -9
- package/lib/hover.js +17 -17
- package/lib/images.js +15 -12
- package/lib/index.d.ts +13 -13
- package/lib/interaction-states.d.ts +2 -2
- package/lib/interaction-states.js +7 -7
- package/lib/mock/index.d.ts +1 -1
- package/lib/mock/youtube.d.ts +1 -1
- package/lib/mock/youtube.js +1 -1
- package/lib/pseudo-state.d.ts +2 -2
- package/lib/pseudo-state.js +15 -7
- package/lib/videos.js +21 -10
- package/lib/visualdiff.d.ts +4 -4
- package/lib/visualdiff.js +35 -27
- package/package.json +3 -3
- package/src/accessibility-baseline-file.test.ts +190 -154
- package/src/accessibility-baseline-file.ts +107 -83
- package/src/accessibility-baseline.test.ts +633 -433
- package/src/accessibility-baseline.ts +41 -21
- package/src/accessible-screenshot.test.ts +551 -423
- package/src/accessible-screenshot.ts +334 -245
- package/src/focus.test.ts +23 -23
- package/src/focus.ts +7 -2
- package/src/fonts.test.ts +13 -13
- package/src/fonts.ts +1 -1
- package/src/frames.test.ts +10 -8
- package/src/frames.ts +5 -5
- package/src/github/a11y-summary.test.ts +436 -332
- package/src/github/a11y-summary.ts +189 -179
- package/src/github/attachments.test.ts +228 -167
- package/src/github/attachments.ts +144 -121
- package/src/github/failure-summary.test.ts +659 -445
- package/src/github/failure-summary.ts +376 -274
- package/src/github/index.test.ts +14 -14
- package/src/github/index.ts +6 -6
- package/src/github/report-paths.test.ts +211 -156
- package/src/github/report-paths.ts +75 -61
- package/src/hover.test.ts +50 -46
- package/src/hover.ts +18 -18
- package/src/images.test.ts +251 -206
- package/src/images.ts +52 -43
- package/src/index.ts +13 -13
- package/src/interaction-states.test.ts +72 -42
- package/src/interaction-states.ts +43 -29
- package/src/mock/index.ts +1 -1
- package/src/mock/youtube.test.ts +26 -26
- package/src/mock/youtube.ts +4 -6
- package/src/pseudo-state.test.ts +58 -51
- package/src/pseudo-state.ts +32 -27
- package/src/videos.test.ts +559 -399
- package/src/videos.ts +68 -44
- package/src/visualdiff.test.ts +416 -315
- package/src/visualdiff.ts +140 -99
package/src/focus.test.ts
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import {afterEach, describe, expect, it, vi} from
|
|
2
|
-
import {blurActiveElement} from
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { blurActiveElement } from "./focus";
|
|
3
3
|
|
|
4
|
-
describe(
|
|
5
|
-
afterEach(() => vi.unstubAllGlobals())
|
|
4
|
+
describe("blurActiveElement", () => {
|
|
5
|
+
afterEach(() => vi.unstubAllGlobals());
|
|
6
6
|
|
|
7
|
-
it(
|
|
8
|
-
const activeElement = {blur: vi.fn()}
|
|
9
|
-
const document = {activeElement, body: {}, documentElement: {}}
|
|
7
|
+
it("blurs a genuinely focused element", async () => {
|
|
8
|
+
const activeElement = { blur: vi.fn() };
|
|
9
|
+
const document = { activeElement, body: {}, documentElement: {} };
|
|
10
10
|
const page = {
|
|
11
11
|
evaluate: vi.fn((callback: () => boolean) => {
|
|
12
|
-
vi.stubGlobal(
|
|
13
|
-
return callback()
|
|
12
|
+
vi.stubGlobal("document", document);
|
|
13
|
+
return callback();
|
|
14
14
|
}),
|
|
15
|
-
}
|
|
15
|
+
};
|
|
16
16
|
|
|
17
|
-
await expect(blurActiveElement(page as never)).resolves.toBe(true)
|
|
18
|
-
expect(activeElement.blur).toHaveBeenCalledOnce()
|
|
19
|
-
})
|
|
17
|
+
await expect(blurActiveElement(page as never)).resolves.toBe(true);
|
|
18
|
+
expect(activeElement.blur).toHaveBeenCalledOnce();
|
|
19
|
+
});
|
|
20
20
|
|
|
21
|
-
it(
|
|
22
|
-
const body = {blur: vi.fn()}
|
|
23
|
-
const document = {activeElement: body, body, documentElement: {}}
|
|
21
|
+
it("does not blur the document body fallback", async () => {
|
|
22
|
+
const body = { blur: vi.fn() };
|
|
23
|
+
const document = { activeElement: body, body, documentElement: {} };
|
|
24
24
|
const page = {
|
|
25
25
|
evaluate: vi.fn((callback: () => boolean) => {
|
|
26
|
-
vi.stubGlobal(
|
|
27
|
-
return callback()
|
|
26
|
+
vi.stubGlobal("document", document);
|
|
27
|
+
return callback();
|
|
28
28
|
}),
|
|
29
|
-
}
|
|
29
|
+
};
|
|
30
30
|
|
|
31
|
-
await expect(blurActiveElement(page as never)).resolves.toBe(false)
|
|
32
|
-
expect(body.blur).not.toHaveBeenCalled()
|
|
33
|
-
})
|
|
34
|
-
})
|
|
31
|
+
await expect(blurActiveElement(page as never)).resolves.toBe(false);
|
|
32
|
+
expect(body.blur).not.toHaveBeenCalled();
|
|
33
|
+
});
|
|
34
|
+
});
|
package/src/focus.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Page} from "@playwright/test";
|
|
1
|
+
import { Page } from "@playwright/test";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Remove keyboard focus from the active element.
|
|
@@ -18,7 +18,12 @@ export async function blurActiveElement(page: Page): Promise<boolean> {
|
|
|
18
18
|
// `document.activeElement` falls back to `<body>`/`<html>` when nothing is
|
|
19
19
|
// focused. Blurring that paints no focus ring but can still fire `focusout`
|
|
20
20
|
// handlers, so skip it and only blur a genuinely focused control.
|
|
21
|
-
if (
|
|
21
|
+
if (
|
|
22
|
+
!el ||
|
|
23
|
+
el === document.body ||
|
|
24
|
+
el === document.documentElement ||
|
|
25
|
+
typeof el.blur !== "function"
|
|
26
|
+
) {
|
|
22
27
|
return false;
|
|
23
28
|
}
|
|
24
29
|
el.blur();
|
package/src/fonts.test.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {describe, expect, it, vi} from
|
|
2
|
-
import {waitForFonts} from
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { waitForFonts } from "./fonts";
|
|
3
3
|
|
|
4
|
-
describe(
|
|
5
|
-
it(
|
|
4
|
+
describe("waitForFonts", () => {
|
|
5
|
+
it("waits for the browser font set to become ready", async () => {
|
|
6
6
|
const evaluate = vi.fn(async (callback: () => Promise<void>) => {
|
|
7
|
-
const ready = Promise.resolve()
|
|
8
|
-
vi.stubGlobal(
|
|
9
|
-
await callback()
|
|
10
|
-
})
|
|
7
|
+
const ready = Promise.resolve();
|
|
8
|
+
vi.stubGlobal("document", { fonts: { ready } });
|
|
9
|
+
await callback();
|
|
10
|
+
});
|
|
11
11
|
|
|
12
|
-
await waitForFonts({evaluate} as never)
|
|
12
|
+
await waitForFonts({ evaluate } as never);
|
|
13
13
|
|
|
14
|
-
expect(evaluate).toHaveBeenCalledOnce()
|
|
15
|
-
vi.unstubAllGlobals()
|
|
16
|
-
})
|
|
17
|
-
})
|
|
14
|
+
expect(evaluate).toHaveBeenCalledOnce();
|
|
15
|
+
vi.unstubAllGlobals();
|
|
16
|
+
});
|
|
17
|
+
});
|
package/src/fonts.ts
CHANGED
package/src/frames.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
2
|
|
|
3
|
-
import { waitForFrames } from
|
|
3
|
+
import { waitForFrames } from "./frames";
|
|
4
4
|
|
|
5
5
|
function makeLocator({
|
|
6
6
|
connected = true,
|
|
@@ -39,8 +39,8 @@ function makePage(locators: ReturnType<typeof makeLocator>[]) {
|
|
|
39
39
|
} as never;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
describe(
|
|
43
|
-
it(
|
|
42
|
+
describe("waitForFrames", () => {
|
|
43
|
+
it("waits for each visible frame URL and load state", async () => {
|
|
44
44
|
const first = makeLocator();
|
|
45
45
|
const second = makeLocator();
|
|
46
46
|
|
|
@@ -49,14 +49,16 @@ describe('waitForFrames', () => {
|
|
|
49
49
|
for (const locator of [first, second]) {
|
|
50
50
|
expect(locator.scrollIntoViewIfNeeded).toHaveBeenCalledTimes(2);
|
|
51
51
|
expect(locator.element.contentFrame).toHaveBeenCalledOnce();
|
|
52
|
-
expect(locator.element.contentFrame.mock.results[0].value).toBeInstanceOf(
|
|
52
|
+
expect(locator.element.contentFrame.mock.results[0].value).toBeInstanceOf(
|
|
53
|
+
Promise,
|
|
54
|
+
);
|
|
53
55
|
const frame = await locator.element.contentFrame.mock.results[0].value;
|
|
54
56
|
expect(frame?.waitForURL).toHaveBeenCalledOnce();
|
|
55
|
-
expect(frame?.waitForLoadState).toHaveBeenCalledWith(
|
|
57
|
+
expect(frame?.waitForLoadState).toHaveBeenCalledWith("load");
|
|
56
58
|
}
|
|
57
59
|
});
|
|
58
60
|
|
|
59
|
-
it(
|
|
61
|
+
it("ignores frames that are detached or hidden", async () => {
|
|
60
62
|
const detached = makeLocator({ connected: false });
|
|
61
63
|
const hidden = makeLocator({ visible: false });
|
|
62
64
|
|
|
@@ -67,7 +69,7 @@ describe('waitForFrames', () => {
|
|
|
67
69
|
expect(hidden.elementHandle).not.toHaveBeenCalled();
|
|
68
70
|
});
|
|
69
71
|
|
|
70
|
-
it(
|
|
72
|
+
it("tolerates an iframe that detaches before its content frame is resolved", async () => {
|
|
71
73
|
const locator = makeLocator({ frame: null });
|
|
72
74
|
|
|
73
75
|
await expect(waitForFrames(makePage([locator]))).resolves.toBeUndefined();
|
package/src/frames.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Page} from "@playwright/test";
|
|
1
|
+
import { Page } from "@playwright/test";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Wait for all frames to load.
|
|
@@ -6,20 +6,20 @@ import {Page} from "@playwright/test";
|
|
|
6
6
|
* @param page
|
|
7
7
|
*/
|
|
8
8
|
export async function waitForFrames(page: Page): Promise<void> {
|
|
9
|
-
const locators = await page.locator(
|
|
9
|
+
const locators = await page.locator("iframe");
|
|
10
10
|
// Trigger lazy-loading iframes. Since this should be fast, and we don't want to
|
|
11
11
|
// have to deal with concurrency bugs, we do this in serial.
|
|
12
12
|
for (const locator of await locators.all()) {
|
|
13
13
|
// Ensure iframes are connected to the DOM before trying to scroll to them.
|
|
14
14
|
// https://github.com/microsoft/playwright/issues/23758
|
|
15
|
-
if (await locator.evaluate(iframe => iframe.isConnected)) {
|
|
15
|
+
if (await locator.evaluate((iframe) => iframe.isConnected)) {
|
|
16
16
|
if (await locator.isVisible()) {
|
|
17
17
|
await locator.scrollIntoViewIfNeeded();
|
|
18
18
|
await locator.scrollIntoViewIfNeeded();
|
|
19
19
|
const element = await locator.elementHandle();
|
|
20
20
|
const frame = await element?.contentFrame();
|
|
21
|
-
await frame?.waitForURL(new RegExp(
|
|
22
|
-
await frame?.waitForLoadState(
|
|
21
|
+
await frame?.waitForURL(new RegExp(".*/.*", "i"));
|
|
22
|
+
await frame?.waitForLoadState("load");
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
}
|