Skip to content

Commit

Permalink
refactor(screenshots): Remove Puppeteer related code
Browse files Browse the repository at this point in the history
  • Loading branch information
xrutayisire committed Oct 30, 2023
1 parent 274d6ad commit c49be57
Show file tree
Hide file tree
Showing 32 changed files with 20 additions and 1,455 deletions.
File renamed without changes.
70 changes: 0 additions & 70 deletions cypress/e2e/slices/02-simulator-screenshots.cy.js

This file was deleted.

83 changes: 0 additions & 83 deletions cypress/pages/simulator/simulatorPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,6 @@ class SimulatorPage {
return cy.contains("Save mock content");
}

get takeScreenshotButton() {
return cy.contains("Take a screenshot");
}

get screenshotToast() {
return cy.contains("Tap to view screenshot");
}

get simulatorIframe() {
return cy.get("#__iframe-renderer");
}

get widthInput() {
return cy.get('input[name="W-screensize-input"]');
}

get heightInput() {
return cy.get('input[name="H-screensize-input"]');
}

getScreenSizeDropdown(currentValue) {
return cy.get("button").contains(currentValue);
}

/**
* Setup the slice simulator in the example project, and stub the window open
* event to open in the same page.
Expand All @@ -45,65 +21,6 @@ class SimulatorPage {
return this;
}

/**
* Use the screen size dropdown menu to change the simulator screen size.
*
* @param {string} startValue The expected start value of the dropdown button.
* @param {string} newValue The new value to set the screen size to.
*/
resizeScreenWithDropdown(startValue, newValue) {
this.getScreenSizeDropdown(startValue).click();
cy.contains(newValue).click();

return this;
}

/**
* Use the screen size input fields to change the simulator screen size.
*
* @param {number} newWidth The new value to the the width to.
* @param {number} newHeight The new value to the the height to.
*/
resizeScreenWithInput(newWidth, newHeight) {
this.widthInput.clear().type(`{rightArrow}${newWidth}`);
this.heightInput.clear().type(`{rightArrow}${newHeight}`);

return this;
}

/**
* Check that the dimensions of the simulator are equal to the provided ones.
*
* @param {number} expectedWidth The value which the width should equal.
* @param {number} expectedHeight The value which the height should equal.
*/
validateSimulatorSize(expectedWidth, expectedHeight) {
this.simulatorIframe
.should("have.css", "maxWidth")
.and("eq", `${expectedWidth}px`);
this.simulatorIframe
.should("have.css", "minWidth")
.and("eq", `${expectedWidth}px`);
this.simulatorIframe
.should("have.css", "maxHeight")
.and("eq", `${expectedHeight}px`);
this.simulatorIframe
.should("have.css", "minHeight")
.and("eq", `${expectedHeight}px`);

return this;
}

takeAScreenshotAndOpenModal() {
this.takeScreenshotButton.click();

cy.contains("Screenshot taken", { timeout: 30000 }).should("be.visible");

this.screenshotToast.click();

return this;
}

/**
* Change the slice variations using the variations dropdown in the simulator.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const omitProcedures = defineOmits<SliceMachineManager>()([
"sliceTemplateLibrary._sliceMachineManager",
"getSliceMachinePluginRunner",
"getPrismicAuthManager",
"screenshots.browserContext",
]);

export type SliceMachineManagerMiddleware = RPCMiddleware<
Expand Down
163 changes: 0 additions & 163 deletions packages/manager/src/managers/screenshots/ScreenshotsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { fileTypeFromBuffer } from "file-type";
import pLimit from "p-limit";
import fetch, { FormData, Blob, Response } from "../../lib/fetch";

import { checkIsURLAccessible } from "../../lib/checkIsURLAccessible";
import { createContentDigest } from "../../lib/createContentDigest";
import { decode } from "../../lib/decode";

Expand All @@ -13,21 +12,6 @@ import { API_ENDPOINTS } from "../../constants/API_ENDPOINTS";

import { BaseManager } from "../BaseManager";

const SLICE_SIMULATOR_WAIT_FOR_SELECTOR = "#__iframe-ready";
const SLICE_SIMULATOR_WAIT_FOR_SELECTOR_TIMEOUT = 10_000; // ms
const SLICE_SIMULATOR_SCREENSHOT_SELECTOR = "#__iframe-renderer";

// TODO(DT-1534): Use Puppeteer types if we want reactive Puppeteer screenshots
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Viewport = any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type BrowserContext = any;

const DEFAULT_SCREENSHOT_VIEWPORT: Viewport = {
width: 1200,
height: 800,
};

function assertS3ACLInitialized(
s3ACL: S3ACL | undefined,
): asserts s3ACL is NonNullable<typeof s3ACL> {
Expand All @@ -38,48 +22,8 @@ function assertS3ACLInitialized(
}
}

function assertBrowserContextInitialized(
browserContext: BrowserContext | undefined,
): asserts browserContext is NonNullable<typeof browserContext> {
if (browserContext == undefined) {
throw new Error(
"A browser context has not been initialized. Run `SliceMachineManager.screenshots.prototype.initBrowserContext()` before re-calling this method.",
);
}
}

const uploadScreenshotLimit = pLimit(10);

/**
* Encodes a part of a Slice Simulator URL to ensure it can be added to a URL
* safely.
*
* The encoding logic must match Slice Machine UI's URL encoding practices.
* Today, that requires the following:
*
* - Replace "/" with "--" (e.g. a Slice Library ID of "./slices" should turn into
* ".--slices")
*
* @param urlPart - A part of the URL.
*
* @returns `urlPart` encoded for use in a URL.
*/
const encodeSliceSimulatorURLPart = (urlPart: string): string => {
return urlPart.replace(/\//g, "--");
};

type ScreenshotsManagerCaptureSliceSimulatorScreenshotArgs = {
sliceMachineUIOrigin: string;
libraryID: string;
sliceID: string;
variationID: string;
viewport?: Viewport;
};

type ScreenshotsManagerCaptureSliceSimulatorScreenshotReturnType = {
data: Buffer;
};

type ScreenshotsManagerUploadScreenshotArgs = {
data: Buffer;
keyPrefix?: string;
Expand All @@ -94,35 +38,8 @@ type ScreenshotsManagerDeleteScreenshotFolderArgs = {
};

export class ScreenshotsManager extends BaseManager {
private _browserContext: BrowserContext | undefined;
private _s3ACL: S3ACL | undefined;

async initBrowserContext(): Promise<void> {
// TODO(DT-1534): Uncomment to enable Puppeteer screenshots or delete if we decide to remove Puppeteer
//
// if (this._browserContext) {
// return;
// }
//
// let puppeteer: typeof import("puppeteer");
// try {
// // Lazy-load Puppeteer only once it is needed.
// puppeteer = await import("puppeteer");
// } catch {
// throw new InternalError(
// "Screenshots require Puppeteer but Puppeteer was not found. Check that the `puppeteer` package is installed before trying again.",
// );
// }
// try {
// const browser = await puppeteer.launch({ headless: "new" });
// this._browserContext = await browser.createIncognitoBrowserContext();
// } catch (error) {
// throw new InternalError(
// "Error launching browser. If you're using an Apple Silicon Mac, check if Rosetta is installed.",
// );
// }
}

async initS3ACL(): Promise<void> {
// TODO: we need to find a way to create a new AWS ACL only when necessary (e.g., when it has expired).
// if (this._s3ACL) {
Expand Down Expand Up @@ -177,86 +94,6 @@ export class ScreenshotsManager extends BaseManager {
};
}

// TODO: Abstract to a generic `captureScreenshot()` method that is
// used within a Slice-specific method in SliceManager.
async captureSliceSimulatorScreenshot(
args: ScreenshotsManagerCaptureSliceSimulatorScreenshotArgs,
): Promise<ScreenshotsManagerCaptureSliceSimulatorScreenshotReturnType> {
assertBrowserContextInitialized(this._browserContext);

const sliceMachineConfig = await this.project.getSliceMachineConfig();

if (!sliceMachineConfig.localSliceSimulatorURL) {
// TODO: Provide a more helpful error message.
throw new Error(
"A local Slice Simulator URL must be configured in your Slice Machine configuration file.",
);
}

const { model } = await this.slices.readSlice({
libraryID: args.libraryID,
sliceID: args.sliceID,
});
if (!model) {
throw new Error(
`Did not find a Slice in library "${args.libraryID}" with ID "${args.sliceID}".`,
);
}

const viewport = args.viewport || DEFAULT_SCREENSHOT_VIEWPORT;

// TODO: Change `model.name` to `args.sliceID`?
// Making that change would require changing the screenshot
// page path in Slice Machine UI.
const url = new URL(
`./${encodeSliceSimulatorURLPart(args.libraryID)}/${model.name}/${
args.variationID
}/screenshot`,
args.sliceMachineUIOrigin,
);
url.searchParams.set("screenWidth", viewport.width.toString());
url.searchParams.set("screenHeight", viewport.height.toString());

const isURLAccessible = await checkIsURLAccessible(url.toString());

if (!isURLAccessible) {
throw new Error(
`Slice Simulator screenshot URL is not accessible: ${url}`,
);
}

const page = await this._browserContext.newPage();
page.setViewport(viewport);

await page.goto(url.toString(), { waitUntil: ["load", "networkidle0"] });
await page.waitForSelector(SLICE_SIMULATOR_WAIT_FOR_SELECTOR, {
timeout: SLICE_SIMULATOR_WAIT_FOR_SELECTOR_TIMEOUT,
});

const element = await page.$(SLICE_SIMULATOR_SCREENSHOT_SELECTOR);
if (!element) {
const baseURL = new URL(url.pathname, url.origin);

throw new Error(
`Slice Simulator did not find ${SLICE_SIMULATOR_WAIT_FOR_SELECTOR} on the page. Verify the URL is correct: ${baseURL}`,
);
}

const data = (await element.screenshot({
encoding: "binary",
clip: {
width: viewport.width,
height: viewport.height,
x: 0,
y: 0,
},
})) as Buffer;

return {
data,
};
}

async uploadScreenshot(
args: ScreenshotsManagerUploadScreenshotArgs,
): Promise<ScreenshotsManagerUploadScreenshotReturnType> {
Expand Down
4 changes: 2 additions & 2 deletions packages/manager/src/managers/telemetry/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ type LegacySliceConvertedSegmentEvent = SegmentEvent<
type ScreenshotTakenSegmentEvent = SegmentEvent<
typeof SegmentEventType.screenshotTaken,
{
type: "custom" | "automatic";
method: "fromSimulator" | "upload" | "dragAndDrop";
type: "custom";
method: "upload" | "dragAndDrop";
}
>;

Expand Down
Loading

0 comments on commit c49be57

Please sign in to comment.