Skip to content

Commit

Permalink
feat: stabilize sticky & fixed elements in full page
Browse files Browse the repository at this point in the history
  • Loading branch information
gregberge committed Nov 16, 2023
1 parent 3d30b50 commit 5f01dd9
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 9 deletions.
9 changes: 7 additions & 2 deletions packages/browser/src/global.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { waitForStability, prepareForScreenshot } from "./stabilization";
import {
waitForStability,
prepareForScreenshot,
PrepareForScreenshotOptions,
} from "./stabilization";
import { getColorScheme, getMediaType } from "./media";

const ArgosGlobal = {
waitForStability: () => waitForStability(document),
prepareForScreenshot: () => prepareForScreenshot(document),
prepareForScreenshot: (options: PrepareForScreenshotOptions = {}) =>
prepareForScreenshot(document, options),
getColorScheme: () => getColorScheme(window),
getMediaType: () => getMediaType(window),
};
Expand Down
35 changes: 33 additions & 2 deletions packages/browser/src/stabilization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,51 @@ export function disableSpellCheck(document: Document) {
}

/**
*
* Inject global styles in the DOM.
*/
export function injectGlobalStyles(document: Document) {
const style = document.createElement("style");
style.textContent = GLOBAL_CSS;
document.head.appendChild(style);
}

const checkIsHTMLElement = (element: Element): element is HTMLElement => {
return "style" in element;
};

/**
* Stabilize sticky and fixed elements.
*/
export function stabilizeElementPositions(document: Document) {
const window = document.defaultView;
if (!window) return;
const elements = Array.from(document.querySelectorAll("*"));
elements.forEach((element) => {
if (!checkIsHTMLElement(element)) return;
const style = window.getComputedStyle(element);
const position = style.position;
if (position === "fixed") {
element.style.position = "absolute";
} else if (position === "sticky") {
element.style.position = "relative";
}
});
}

export type PrepareForScreenshotOptions = { fullPage?: boolean };

/**
* Prepare the document for a screenshot.
*/
export function prepareForScreenshot(document: Document) {
export function prepareForScreenshot(
document: Document,
{ fullPage }: PrepareForScreenshotOptions = {},
) {
injectGlobalStyles(document);
disableSpellCheck(document);
if (fullPage) {
stabilizeElementPositions(document);
}
}

/**
Expand Down
6 changes: 5 additions & 1 deletion packages/cypress/src/support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,12 @@ Cypress.Commands.add(

injectArgos();

const fullPage = !options.capture || options.capture === "fullPage";

cy.window({ log: false }).then((window) =>
((window as any).__ARGOS__ as ArgosGlobal).prepareForScreenshot(),
((window as any).__ARGOS__ as ArgosGlobal).prepareForScreenshot({
fullPage,
}),
);

function stabilizeAndScreenshot(name: string) {
Expand Down
9 changes: 7 additions & 2 deletions packages/playwright/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,13 @@ export async function argosScreenshot(

const originalViewportSize = getViewportSize(page);

const fullPage =
options.fullPage !== undefined ? options.fullPage : handle === page;

await page.evaluate(() =>
((window as any).__ARGOS__ as ArgosGlobal).prepareForScreenshot(),
((window as any).__ARGOS__ as ArgosGlobal).prepareForScreenshot({
fullPage,
}),
);

async function collectMetadata(
Expand Down Expand Up @@ -165,7 +170,7 @@ export async function argosScreenshot(
handle.screenshot({
path: screenshotPath ?? undefined,
type: "png",
fullPage: handle === page,
fullPage,
mask: [page.locator('[data-visual-test="blackout"]')],
animations: "disabled",
...options,
Expand Down
9 changes: 7 additions & 2 deletions packages/puppeteer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,14 @@ export async function argosScreenshot(
]);

await page.evaluate(() =>
((window as any).__ARGOS__ as ArgosGlobal).prepareForScreenshot(),
((window as any).__ARGOS__ as ArgosGlobal).prepareForScreenshot({
fullPage,
}),
);

const fullPage =
options.fullPage !== undefined ? options.fullPage : element === undefined;

async function collectMetadata(): Promise<ScreenshotMetadata> {
const [
colorScheme,
Expand Down Expand Up @@ -144,7 +149,7 @@ export async function argosScreenshot(
const screenshotOptions: ScreenshotOptions = {
path: screenshotPath,
type: "png",
fullPage: element === undefined,
fullPage,
...options,
};

Expand Down

0 comments on commit 5f01dd9

Please sign in to comment.