@manufac/general-tests 0.5.1 → 0.9.0
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/README.md +88 -0
- package/dist/config/projects.d.ts +3 -1
- package/dist/config/projects.js +4 -2
- package/dist/fixtures/index.d.ts +2 -1
- package/dist/fixtures/index.js +1 -0
- package/dist/schema/index.d.ts +13 -0
- package/dist/schema/index.js +7 -0
- package/dist/specs/cta-destinations.spec.js +65 -0
- package/dist/specs/page-visual-regression.spec.js +68 -0
- package/dist/specs/{visual-regression.spec.js → storybook-visual-regression.spec.js} +7 -0
- package/dist/specs/utils.d.ts +4 -158
- package/dist/specs/utils.js +27 -856
- package/package.json +1 -1
- package/dist/specs/desktop-only/browser-zoom.spec.js +0 -26
- package/dist/specs/mobile-only/ios-safari-toolbar.spec.js +0 -62
- package/dist/specs/mobile-only/ios-safe-areas.spec.js +0 -36
- package/dist/specs/mobile-only/navigation.spec.d.ts +0 -1
- package/dist/specs/mobile-only/navigation.spec.js +0 -40
- package/dist/specs/mobile-only/orientation.spec.d.ts +0 -1
- package/dist/specs/mobile-only/orientation.spec.js +0 -46
- package/dist/specs/mobile-only/readability.spec.d.ts +0 -1
- package/dist/specs/mobile-only/readability.spec.js +0 -14
- package/dist/specs/mobile-only/soft-keyboard.spec.d.ts +0 -1
- package/dist/specs/mobile-only/soft-keyboard.spec.js +0 -43
- package/dist/specs/mobile-only/touch-targets.spec.d.ts +0 -1
- package/dist/specs/mobile-only/touch-targets.spec.js +0 -12
- package/dist/specs/shared/cta.spec.d.ts +0 -1
- package/dist/specs/shared/cta.spec.js +0 -199
- package/dist/specs/shared/forms/autofill.spec.d.ts +0 -1
- package/dist/specs/shared/forms/autofill.spec.js +0 -28
- package/dist/specs/shared/forms/double-submit.spec.d.ts +0 -1
- package/dist/specs/shared/forms/double-submit.spec.js +0 -25
- package/dist/specs/shared/forms/input-edge.spec.d.ts +0 -1
- package/dist/specs/shared/forms/input-edge.spec.js +0 -60
- package/dist/specs/shared/forms/invalid-input.spec.d.ts +0 -1
- package/dist/specs/shared/forms/invalid-input.spec.js +0 -41
- package/dist/specs/shared/forms/native-inputs.spec.d.ts +0 -1
- package/dist/specs/shared/forms/native-inputs.spec.js +0 -37
- package/dist/specs/shared/forms/required-field.spec.d.ts +0 -1
- package/dist/specs/shared/forms/required-field.spec.js +0 -39
- package/dist/specs/shared/forms/thankyou-confirm.spec.d.ts +0 -1
- package/dist/specs/shared/forms/thankyou-confirm.spec.js +0 -34
- package/dist/specs/shared/hero-fold.spec.d.ts +0 -1
- package/dist/specs/shared/hero-fold.spec.js +0 -40
- package/dist/specs/shared/image-quality.spec.d.ts +0 -1
- package/dist/specs/shared/image-quality.spec.js +0 -13
- package/dist/specs/shared/media-embeds/carousel-slider.spec.d.ts +0 -1
- package/dist/specs/shared/media-embeds/carousel-slider.spec.js +0 -31
- package/dist/specs/shared/media-embeds/cookie-consent.spec.d.ts +0 -1
- package/dist/specs/shared/media-embeds/cookie-consent.spec.js +0 -27
- package/dist/specs/shared/media-embeds/third-party-embeds.spec.d.ts +0 -1
- package/dist/specs/shared/media-embeds/third-party-embeds.spec.js +0 -27
- package/dist/specs/shared/media-embeds/video-playback.spec.d.ts +0 -1
- package/dist/specs/shared/media-embeds/video-playback.spec.js +0 -54
- package/dist/specs/shared/sticky-elements.spec.d.ts +0 -1
- package/dist/specs/shared/sticky-elements.spec.js +0 -13
- package/dist/specs/sticky-utils.d.ts +0 -8
- package/dist/specs/sticky-utils.js +0 -175
- package/dist/specs/visual-regression.spec.d.ts +0 -1
- /package/dist/specs/{desktop-only/browser-zoom.spec.d.ts → cta-destinations.spec.d.ts} +0 -0
- /package/dist/specs/{mobile-only/ios-safari-toolbar.spec.d.ts → page-visual-regression.spec.d.ts} +0 -0
- /package/dist/specs/{mobile-only/ios-safe-areas.spec.d.ts → storybook-visual-regression.spec.d.ts} +0 -0
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.checkStickyElements = checkStickyElements;
|
|
4
|
-
const utils_1 = require("./utils");
|
|
5
|
-
// Each page.evaluate call runs in a fresh browser-side context, so a DOM element found in one
|
|
6
|
-
// can't be referenced from the next — this attribute gives each sticky a stable ID to re-select
|
|
7
|
-
// by across the many separate evaluate calls this check makes while scrolling.
|
|
8
|
-
const StickyMarkerAttribute = "data-rs06-sticky-id";
|
|
9
|
-
// Content worth checking that a sticky element doesn't cover: body text and form fields.
|
|
10
|
-
const ContentSelector = "p, li, td, th, label, input, textarea, select, button, a, h1, h2, h3, h4, h5, h6";
|
|
11
|
-
// Marks by computed position alone, not current visibility — a sticky/fixed element that's
|
|
12
|
-
// hidden at page load (e.g. a CTA bar that only appears after scrolling past the hero) must
|
|
13
|
-
// still be tracked once it shows up later, not excluded from the whole test up front.
|
|
14
|
-
async function markStickyElements(page) {
|
|
15
|
-
return page.evaluate((markerAttribute) => {
|
|
16
|
-
const candidates = Array.from(document.querySelectorAll("body *")).filter((element) => {
|
|
17
|
-
const style = window.getComputedStyle(element);
|
|
18
|
-
return style.position === "fixed" || style.position === "sticky";
|
|
19
|
-
});
|
|
20
|
-
candidates.forEach((element, index) => {
|
|
21
|
-
element.setAttribute(markerAttribute, String(index));
|
|
22
|
-
});
|
|
23
|
-
return candidates.length;
|
|
24
|
-
}, StickyMarkerAttribute);
|
|
25
|
-
}
|
|
26
|
-
async function sampleStickyPositions(page) {
|
|
27
|
-
return page.evaluate(({ markerAttribute, contentSelector }) => {
|
|
28
|
-
function isRendered(element) {
|
|
29
|
-
const style = window.getComputedStyle(element);
|
|
30
|
-
const rect = element.getBoundingClientRect();
|
|
31
|
-
return (style.display !== "none" &&
|
|
32
|
-
style.visibility !== "hidden" &&
|
|
33
|
-
Number.parseFloat(style.opacity) !== 0 &&
|
|
34
|
-
rect.width > 0 &&
|
|
35
|
-
rect.height > 0);
|
|
36
|
-
}
|
|
37
|
-
// Only currently-visible stickies contribute a sample this step — a sticky bar that's
|
|
38
|
-
// hidden right now (not yet triggered, or already dismissed) simply isn't sampled here.
|
|
39
|
-
const stickies = Array.from(document.querySelectorAll(`[${markerAttribute}]`)).filter(isRendered);
|
|
40
|
-
const contentElements = Array.from(document.querySelectorAll(contentSelector)).filter(isRendered);
|
|
41
|
-
return stickies.map((element) => {
|
|
42
|
-
const stickyID = Number(element.getAttribute(markerAttribute));
|
|
43
|
-
const rect = element.getBoundingClientRect();
|
|
44
|
-
const desc = `<${element.tagName.toLowerCase()} class="${element.className}">`;
|
|
45
|
-
const covered = contentElements
|
|
46
|
-
.filter((content) => {
|
|
47
|
-
const isNested = element.contains(content);
|
|
48
|
-
const contentRect = content.getBoundingClientRect();
|
|
49
|
-
const overlapWidth = Math.min(rect.right, contentRect.right) - Math.max(rect.left, contentRect.left);
|
|
50
|
-
const overlapHeight = Math.min(rect.bottom, contentRect.bottom) - Math.max(rect.top, contentRect.top);
|
|
51
|
-
return !isNested && overlapWidth > 0 && overlapHeight > 0;
|
|
52
|
-
})
|
|
53
|
-
.map((content) => {
|
|
54
|
-
return `${desc} covers <${content.tagName.toLowerCase()} class="${content.className}">`;
|
|
55
|
-
});
|
|
56
|
-
return { stickyID, top: rect.top, covered };
|
|
57
|
-
});
|
|
58
|
-
}, { markerAttribute: StickyMarkerAttribute, contentSelector: ContentSelector });
|
|
59
|
-
}
|
|
60
|
-
async function waitForScrollToSettle(page) {
|
|
61
|
-
let previousScrollY = await page.evaluate(() => {
|
|
62
|
-
return window.scrollY;
|
|
63
|
-
});
|
|
64
|
-
let isSettled = false;
|
|
65
|
-
let attempt = 0;
|
|
66
|
-
while (!isSettled && attempt < 20) {
|
|
67
|
-
await page.waitForTimeout(100);
|
|
68
|
-
const currentScrollY = await page.evaluate(() => {
|
|
69
|
-
return window.scrollY;
|
|
70
|
-
});
|
|
71
|
-
isSettled = Math.abs(currentScrollY - previousScrollY) < 1;
|
|
72
|
-
previousScrollY = currentScrollY;
|
|
73
|
-
attempt += 1;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
async function collectStickySamples(page, steps) {
|
|
77
|
-
const samplesByElement = new Map();
|
|
78
|
-
const coversContent = [];
|
|
79
|
-
const maxScrollY = await page.evaluate(() => {
|
|
80
|
-
return document.documentElement.scrollHeight - document.documentElement.clientHeight;
|
|
81
|
-
});
|
|
82
|
-
const down = Array.from({ length: steps + 1 }, (_, stepIndex) => {
|
|
83
|
-
return Math.min(Math.floor((maxScrollY / steps) * stepIndex), maxScrollY);
|
|
84
|
-
});
|
|
85
|
-
const up = Array.from({ length: steps + 1 }, (_, stepIndex) => {
|
|
86
|
-
return Math.min(Math.floor((maxScrollY / steps) * (steps - stepIndex)), maxScrollY);
|
|
87
|
-
});
|
|
88
|
-
for (const targetScrollY of [...down, ...up]) {
|
|
89
|
-
await page.evaluate((y) => {
|
|
90
|
-
window.scrollTo(0, y);
|
|
91
|
-
}, targetScrollY);
|
|
92
|
-
await waitForScrollToSettle(page);
|
|
93
|
-
const actualScrollY = await page.evaluate(() => {
|
|
94
|
-
return window.scrollY;
|
|
95
|
-
});
|
|
96
|
-
const sample = await sampleStickyPositions(page);
|
|
97
|
-
for (const entry of sample) {
|
|
98
|
-
const samples = samplesByElement.get(entry.stickyID) ?? [];
|
|
99
|
-
samples.push({ scrollY: actualScrollY, top: entry.top });
|
|
100
|
-
samplesByElement.set(entry.stickyID, samples);
|
|
101
|
-
coversContent.push(...entry.covered);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return { samplesByElement, coversContent };
|
|
105
|
-
}
|
|
106
|
-
// A well-behaved sticky/fixed element's top can only change between two samples in one of two
|
|
107
|
-
// ways: it's currently pinned, so top stays put (delta ~0); or it's still in normal flow (not yet
|
|
108
|
-
// engaged), so top moves in exact lockstep with scroll (delta ~ -scrollDelta). Anything else is an
|
|
109
|
-
// unexplained jump — the actual flicker/jank this check is meant to catch.
|
|
110
|
-
//
|
|
111
|
-
// Limitation (RS-06 / #162): This is a false-positive risk for JS-driven sticky toggles where the
|
|
112
|
-
// CSS `position` value changes (e.g. from static to fixed). A discrete state change causes a large
|
|
113
|
-
// top jump which computeFlicker currently flags as a flicker. A full fix requires tracking `position`
|
|
114
|
-
// and ignoring jumps when the position value changes. Tracked as a P2 limitation for a future pass.
|
|
115
|
-
function computeFlicker(samplesByElement) {
|
|
116
|
-
const flicker = [];
|
|
117
|
-
for (const [stickyID, samples] of samplesByElement) {
|
|
118
|
-
for (let sampleIndex = 1; sampleIndex < samples.length; sampleIndex++) {
|
|
119
|
-
const topDelta = samples[sampleIndex].top - samples[sampleIndex - 1].top;
|
|
120
|
-
const scrollDelta = samples[sampleIndex].scrollY - samples[sampleIndex - 1].scrollY;
|
|
121
|
-
const isPinned = Math.abs(topDelta) <= utils_1.ResponsiveConfig.PinFlickerTolerancePX;
|
|
122
|
-
const isFollowingScroll = Math.abs(topDelta + scrollDelta) <= utils_1.ResponsiveConfig.PinFlickerTolerancePX;
|
|
123
|
-
if (!isPinned && !isFollowingScroll) {
|
|
124
|
-
flicker.push(`sticky element #${String(stickyID)} jumped ${Math.abs(topDelta).toFixed(0)}px between consecutive scroll samples`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return flicker;
|
|
129
|
-
}
|
|
130
|
-
async function findFooterOverlaps(page) {
|
|
131
|
-
await page.evaluate(() => {
|
|
132
|
-
window.scrollTo(0, document.documentElement.scrollHeight);
|
|
133
|
-
});
|
|
134
|
-
await page.waitForTimeout(100);
|
|
135
|
-
const conflicts = [];
|
|
136
|
-
const footer = await page.$("footer, [role='contentinfo']");
|
|
137
|
-
if (footer !== null) {
|
|
138
|
-
const footerRect = await footer.boundingBox();
|
|
139
|
-
const stickies = await page.$$(`[${StickyMarkerAttribute}]`);
|
|
140
|
-
for (const sticky of stickies) {
|
|
141
|
-
const rect = await sticky.boundingBox();
|
|
142
|
-
if (footerRect !== null && rect !== null) {
|
|
143
|
-
const overlapWidth = Math.min(rect.x + rect.width, footerRect.x + footerRect.width) - Math.max(rect.x, footerRect.x);
|
|
144
|
-
const overlapHeight = Math.min(rect.y + rect.height, footerRect.y + footerRect.height) - Math.max(rect.y, footerRect.y);
|
|
145
|
-
if (overlapWidth > 0 && overlapHeight > 0) {
|
|
146
|
-
const description = await sticky.evaluate((element) => {
|
|
147
|
-
return `<${element.tagName.toLowerCase()} class="${element.className}">`;
|
|
148
|
-
});
|
|
149
|
-
conflicts.push(description);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return conflicts;
|
|
155
|
-
}
|
|
156
|
-
async function checkStickyElements(page) {
|
|
157
|
-
const stickyElementCount = await markStickyElements(page);
|
|
158
|
-
let result;
|
|
159
|
-
if (stickyElementCount === 0) {
|
|
160
|
-
result = { stickyElementCount: 0, flicker: [], coversContent: [], overlapsFooter: [] };
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
const steps = 20;
|
|
164
|
-
const { samplesByElement, coversContent } = await collectStickySamples(page, steps);
|
|
165
|
-
const flicker = computeFlicker(samplesByElement);
|
|
166
|
-
const overlapsFooter = await findFooterOverlaps(page);
|
|
167
|
-
result = {
|
|
168
|
-
stickyElementCount,
|
|
169
|
-
flicker,
|
|
170
|
-
coversContent: [...new Set(coversContent)],
|
|
171
|
-
overlapsFooter,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
return result;
|
|
175
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
File without changes
|
/package/dist/specs/{mobile-only/ios-safari-toolbar.spec.d.ts → page-visual-regression.spec.d.ts}
RENAMED
|
File without changes
|
/package/dist/specs/{mobile-only/ios-safe-areas.spec.d.ts → storybook-visual-regression.spec.d.ts}
RENAMED
|
File without changes
|