-
Notifications
You must be signed in to change notification settings - Fork 3
/
stabilization.ts
114 lines (100 loc) · 2.65 KB
/
stabilization.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/**
* CSS to stabilize visual tests:
* - Hide carets
* - Hide scrollbars
* - Support [data-visual-test]
* - Support [data-visual-test-no-radius]
*/
export const GLOBAL_CSS: string = `
/* Hide carets */
* {
caret-color: transparent !important;
}
/* Hide scrollbars */
::-webkit-scrollbar {
display: none !important;
}
/* Make the element transparent */
[data-visual-test="transparent"] {
color: transparent !important;
font-family: monospace !important;
opacity: 0 !important;
}
/* Remove the element */
[data-visual-test="removed"] {
display: none !important;
}
/* Disable radius */
[data-visual-test-no-radius]:not([data-visual-test-no-radius="false"]) {
border-radius: 0 !important;
}
`;
/**
* Disable spellcheck to avoid displaying markers.
*/
export function disableSpellCheck(document: Document) {
const query =
"[contenteditable]:not([contenteditable=false]):not([spellcheck=false]), input:not([spellcheck=false]), textarea:not([spellcheck=false])";
const inputs = document.querySelectorAll(query);
inputs.forEach((input) => input.setAttribute("spellcheck", "false"));
}
/**
*
*/
export function injectGlobalStyles(document: Document) {
const style = document.createElement("style");
style.textContent = GLOBAL_CSS;
document.head.appendChild(style);
}
/**
* Prepare the document for a screenshot.
*/
export function prepareForScreenshot(document: Document) {
injectGlobalStyles(document);
disableSpellCheck(document);
}
/**
* Wait for the fonts to be loaded.
*/
export function waitForFontsToLoad(document: Document) {
return document.fonts.status === "loaded";
}
/**
* Wait for the images to be loaded.
*/
export function waitForImagesToLoad(document: Document) {
const images = Array.from(document.images);
// Force eager loading
images.forEach((img) => {
if (img.loading !== "eager") {
img.loading = "eager";
}
});
return images.every((img) => img.complete);
}
/**
* Wait for all [aria-busy="true"] elements to invisible.
*/
export function waitForNoBusy(document: Document) {
const checkIsVisible = (element: HTMLElement) =>
Boolean(
element.offsetWidth ||
element.offsetHeight ||
element.getClientRects().length,
);
const elements = Array.from(document.querySelectorAll('[aria-busy="true"]'));
return elements.every((element) => {
return !(element instanceof HTMLElement) || !checkIsVisible(element);
});
}
/**
* Wait for the document to be stable.
*/
export function waitForStability(document: Document) {
const results = [
waitForNoBusy(document),
waitForImagesToLoad(document),
waitForFontsToLoad(document),
];
return results.every(Boolean);
}