core/coordinators/snapshot.coordinator.ts

core/coordinators/snapshot.coordinator.ts is a file in Project Scripts. 61 lines of code and 13 definitions.

import { NO_DEVTOOLS, clickedLine } from "#configuration/strings/snapshot.strings";
import { devtoolsEndpoint, openSession } from "@banes-lab/build-scripts/core/adapters/browser.adapter.ts";
import { dirname, resolve } from "node:path";
import { freshProfile, launchBrowser, settleBrowser } from "@banes-lab/build-scripts/core/factories/browser.factory.ts";
import type { Session } from "@banes-lab/build-scripts/types/browser.types.ts";
import type { SnapshotOptions } from "#types/snapshot.types";
import process from "node:process";
import { wait } from "@banes-lab/build-scripts/core/timers/base.timer.ts";
import { writeArtifacts } from "#core/persistence/snapshot.persistence";

const HERE = ".";

const settleAndClick = async function settleAndClick(session: Session, options: SnapshotOptions): Promise<void> {
    if (options.clickAt === null) {
        await wait(options.settleMs);
        return;
    }
    await wait(Math.min(options.clickAfterMs, options.settleMs));
    const [x = 0, y = 0] = options.clickAt;
    const spot = { button: "left", clickCount: 1, x, y };
    await session.send("Input.dispatchMouseEvent", { ...spot, type: "mousePressed" });
    await session.send("Input.dispatchMouseEvent", { ...spot, type: "mouseReleased" });
    process.stdout.write(clickedLine(x, y));
    await wait(Math.max(0, options.settleMs - options.clickAfterMs));
};

const captureThrough = async function captureThrough(session: Session, options: SnapshotOptions): Promise<string> {
    await session.send("Page.enable");
    await session.send("Runtime.enable");
    await session.send("Emulation.setDeviceMetricsOverride", {
        deviceScaleFactor: 1,
        height: options.height,
        mobile: false,
        width: options.width,
    });
    await session.send("Page.navigate", { url: options.url });
    await settleAndClick(session, options);
    if (options.out === null) {
        return "";
    }
    const { data } = await session.send("Page.captureScreenshot", { format: "png" });
    return typeof data === "string" ? data : "";
};

export const capturePage = async function capturePage(binary: string, options: SnapshotOptions): Promise<boolean> {
    const profile = freshProfile(resolve(dirname(options.out ?? options.log ?? HERE)));
    const child = launchBrowser(binary, {
        height: options.height,
        profileDir: profile,
        software: options.software,
        width: options.width,
    });
    return settleBrowser(child, async () => {
        const endpoint = await devtoolsEndpoint(profile, options.timeoutMs);
        if (endpoint === null) {
            process.stderr.write(NO_DEVTOOLS);
            return false;
        }
        const session = await openSession(endpoint, true);
        const data = await captureThrough(session, options);
        const records = session.records();
        session.close();
        return writeArtifacts(options, data, records);
    });
};