Skip to content

Commit

Permalink
Merge pull request #120 from argos-ci/various-fixes-playwright
Browse files Browse the repository at this point in the history
various fixes playwright
  • Loading branch information
gregberge committed Mar 15, 2024
2 parents 2db40cb + b99d314 commit bd8185c
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 66 deletions.
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
},
"devDependencies": {
"@types/convict": "^6.1.4",
"@types/debug": "^4.1.9",
"@types/debug": "^4.1.12",
"@types/tmp": "^0.2.3",
"msw": "^1.3.0"
},
Expand Down
9 changes: 8 additions & 1 deletion packages/core/src/discovery.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { resolve } from "node:path";
import glob from "fast-glob";
import { debug } from "./debug";

export const discoverScreenshots = async (
patterns: string[],
patterns: string | string[],
{ root = process.cwd(), ignore }: { root?: string; ignore?: string[] } = {},
): Promise<{ name: string; path: string }[]> => {
debug(
`Discovering screenshots with patterns: ${
Array.isArray(patterns) ? patterns.join(", ") : patterns
} in ${root}`,
);
const matches = await glob(patterns, { onlyFiles: true, ignore, cwd: root });
return matches.map((match) => {
debug(`Found screenshot: ${match}`);
const path = resolve(root, match);
return {
name: match,
Expand Down
2 changes: 1 addition & 1 deletion packages/playwright/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ test.describe("#argosScreenshot", () => {
expect(loaderContainer.trim()).toBe("");
});

test("waits for image loading", async () => {
test("waits for image loading @visual", async () => {
const loaderContainer = await page.$eval("#image", (div) => div.innerHTML);
expect(loaderContainer.trim()).toBe("");
});
Expand Down
6 changes: 4 additions & 2 deletions packages/playwright/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@
"@argos-ci/browser": "workspace:*",
"@argos-ci/core": "workspace:*",
"@argos-ci/util": "workspace:*",
"chalk": "^5.3.0"
"chalk": "^5.3.0",
"debug": "^4.3.4"
},
"devDependencies": {
"@argos-ci/cli": "workspace:*",
"@argos-ci/playwright": "workspace:.",
"@playwright/test": "^1.38.1",
"@playwright/test": "^1.42.1",
"@types/debug": "^4.1.12",
"@types/node": "^16.0.0"
},
"scripts": {
Expand Down
5 changes: 5 additions & 0 deletions packages/playwright/src/debug.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import createDebug from "debug";

const KEY = "@argos-ci/playwright";

export const debug = createDebug(KEY);
41 changes: 22 additions & 19 deletions packages/playwright/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ export async function argosScreenshot(

const teardown = await setup(page, options);

async function collectMetadata(
const collectMetadata = async (
testInfo: TestInfo | null,
): Promise<ScreenshotMetadata> {
): Promise<ScreenshotMetadata> => {
const [colorScheme, mediaType, libMetadata, testMetadata] =
await Promise.all([
page.evaluate(() =>
Expand Down Expand Up @@ -185,50 +185,53 @@ export async function argosScreenshot(
};

return metadata;
}
};

async function stabilizeAndScreenshot(name: string) {
const stabilizeAndScreenshot = async (name: string) => {
await page.waitForFunction(() =>
((window as any).__ARGOS__ as ArgosGlobal).waitForStability(),
);

const metadata = await collectMetadata(testInfo);
const screenshotPath = useArgosReporter
? testInfo!.outputPath("argos", `${name}.png`)
: resolve(screenshotFolder, `${name}.png`);

if (screenshotPath) {
const dir = dirname(screenshotPath);
if (dir !== screenshotFolder) {
await mkdir(dirname(screenshotPath), { recursive: true });
}
const nameInProject = testInfo?.project.name
? `${testInfo.project.name}/${name}`
: name;

const screenshotPath =
useArgosReporter && testInfo
? testInfo.outputPath("argos", `${nameInProject}.png`)
: resolve(screenshotFolder, `${nameInProject}.png`);

const dir = dirname(screenshotPath);
if (dir !== screenshotFolder) {
await mkdir(dirname(screenshotPath), { recursive: true });
}

await Promise.all([
handle.screenshot({
path: screenshotPath ?? undefined,
path: screenshotPath,
type: "png",
fullPage,
mask: [page.locator('[data-visual-test="blackout"]')],
animations: "disabled",
...playwrightOptions,
}),
screenshotPath ? writeMetadata(screenshotPath, metadata) : null,
writeMetadata(screenshotPath, metadata),
]);

if (useArgosReporter) {
if (useArgosReporter && testInfo) {
await Promise.all([
testInfo!.attach(getAttachmentName(name, "metadata"), {
testInfo.attach(getAttachmentName(nameInProject, "metadata"), {
path: getMetadataPath(screenshotPath),
contentType: "application/json",
}),
testInfo!.attach(getAttachmentName(name, "screenshot"), {
testInfo.attach(getAttachmentName(nameInProject, "screenshot"), {
path: screenshotPath,
contentType: "image/png",
}),
]);
}
}
};

// If no viewports are specified, take a single screenshot
if (viewports) {
Expand Down
58 changes: 45 additions & 13 deletions packages/playwright/src/reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ import {
getAttachmentFilename,
} from "./attachment";
import { getMetadataFromTestCase } from "./metadata";
import { debug } from "./debug";

async function createTempDirectory() {
async function createUploadDirectory() {
debug("Creating temporary directory for screenshots");
const osTmpDirectory = tmpdir();
const path = join(osTmpDirectory, "argos." + randomBytes(16).toString("hex"));
await mkdir(path, { recursive: true });
debug(`Temporary directory created: ${path}`);
return path;
}

Expand Down Expand Up @@ -54,30 +57,37 @@ async function getParallelFromConfig(
}

class ArgosReporter implements Reporter {
uploadDir!: string;
createUploadDirPromise: null | Promise<string>;
config: ArgosReporterOptions;
playwrightConfig!: FullConfig;
uploadToArgos: boolean;

constructor(config: ArgosReporterOptions) {
this.config = config;
this.uploadToArgos = config.uploadToArgos ?? true;
this.createUploadDirPromise = null;
}

async writeFile(path: string, body: Buffer | string) {
const uploadDir = await this.getUploadDir();
const dir = dirname(path);
if (dir !== this.uploadDir) {
if (dir !== uploadDir) {
await mkdir(dir, { recursive: true });
}
debug(`Writing file to ${path}`);
await writeFile(path, body);
debug(`File written to ${path}`);
}

async copyFile(from: string, to: string) {
const uploadDir = await this.getUploadDir();
const dir = dirname(to);
if (dir !== this.uploadDir) {
if (dir !== uploadDir) {
await mkdir(dir, { recursive: true });
}
debug(`Copying file from ${from} to ${to}`);
await copyFile(from, to);
debug(`File copied from ${from} to ${to}`);
}

getAutomaticScreenshotName(test: TestCase, result: TestResult) {
Expand All @@ -90,22 +100,28 @@ class ArgosReporter implements Reporter {
return name;
}

async onBegin(config: FullConfig, _suite: Suite) {
getUploadDir() {
if (!this.createUploadDirPromise) {
this.createUploadDirPromise = createUploadDirectory();
}
return this.createUploadDirPromise;
}

onBegin(config: FullConfig, _suite: Suite) {
debug("ArgosReporter:onBegin");
this.playwrightConfig = config;
this.uploadDir = await createTempDirectory();
}

async onTestEnd(test: TestCase, result: TestResult) {
const uploadDir = await this.getUploadDir();
debug("ArgosReporter:onTestEnd");
await Promise.all(
result.attachments.map(async (attachment) => {
if (
checkIsArgosScreenshot(attachment) ||
checkIsArgosScreenshotMetadata(attachment)
) {
const path = join(
this.uploadDir,
getAttachmentFilename(attachment.name),
);
const path = join(uploadDir, getAttachmentFilename(attachment.name));
await this.copyFile(attachment.path, path);
return;
}
Expand All @@ -115,7 +131,7 @@ class ArgosReporter implements Reporter {
const trace = result.attachments.find(checkIsTrace) ?? null;
const metadata = await getMetadataFromTestCase(test, result);
const name = this.getAutomaticScreenshotName(test, result);
const path = join(this.uploadDir, `${name}.png`);
const path = join(uploadDir, `${name}.png`);
await Promise.all([
this.writeFile(path + ".argos.json", JSON.stringify(metadata)),
this.copyFile(attachment.path, path),
Expand All @@ -128,17 +144,33 @@ class ArgosReporter implements Reporter {
}

async onEnd(_result: FullResult) {
if (!this.uploadToArgos) return;
debug("ArgosReporter:onEnd");
const uploadDir = await this.getUploadDir();
if (!this.uploadToArgos) {
debug("Not uploading to Argos because uploadToArgos is false.");
debug(`Upload directory: ${uploadDir}`);
return;
}

debug("Getting parallel from config");
const parallel = await getParallelFromConfig(this.playwrightConfig);
if (parallel) {
debug(
`Using parallel config — total: ${parallel.total}, nonce: "${parallel.nonce}"`,
);
} else {
debug("Non-parallel mode");
}

try {
debug("Uploading to Argos");
const res = await upload({
files: ["**/*.png"],
root: this.uploadDir,
root: uploadDir,
parallel: parallel ?? undefined,
...this.config,
});

console.log(chalk.green(`✅ Argos build created: ${res.build.url}`));
} catch (error) {
console.error(error);
Expand Down
2 changes: 1 addition & 1 deletion packages/webdriverio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"@wdio/mocha-framework": "^8.27.0",
"@wdio/spec-reporter": "^8.27.0",
"@wdio/types": "^8.27.0",
"chromedriver": "^120.0.1",
"chromedriver": "^122.0.6",
"ts-node": "^10.9.2",
"wdio-chromedriver-service": "^8.1.1",
"webdriverio": "^8.27.0"
Expand Down
Loading

0 comments on commit bd8185c

Please sign in to comment.