@argos-ci/playwright 6.5.0 → 6.6.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/dist/reporter.js DELETED
@@ -1,388 +0,0 @@
1
- // src/reporter.ts
2
- import chalk from "chalk";
3
- import { readConfig, upload } from "@argos-ci/core";
4
- import { copyFile, readdir, writeFile } from "fs/promises";
5
- import { dirname as dirname2, join } from "path";
6
-
7
- // src/util.ts
8
- import { createRequire as createRequire2 } from "module";
9
-
10
- // src/metadata.ts
11
- import {
12
- getGitRepositoryPath,
13
- readVersionFromPackage
14
- } from "@argos-ci/util";
15
- import { relative } from "path";
16
- import { createRequire } from "module";
17
- import { AsyncLocalStorage } from "async_hooks";
18
- var require2 = createRequire(import.meta.url);
19
- function tryResolve(pkg) {
20
- try {
21
- return require2.resolve(pkg);
22
- } catch {
23
- return null;
24
- }
25
- }
26
- var metadataConfigStorage = new AsyncLocalStorage();
27
- var DEFAULT_PLAYWRIGHT_LIBRARIES = [
28
- "@playwright/test",
29
- "playwright",
30
- "playwright-core"
31
- ];
32
- async function getAutomationLibraryMetadata() {
33
- const metadataConfig = metadataConfigStorage.getStore();
34
- const libraries = metadataConfig?.playwrightLibraries ?? DEFAULT_PLAYWRIGHT_LIBRARIES;
35
- for (const name of libraries) {
36
- const pkgPath = tryResolve(`${name}/package.json`);
37
- if (pkgPath) {
38
- const version = await readVersionFromPackage(pkgPath);
39
- return { version, name };
40
- }
41
- }
42
- throw new Error(
43
- `Unable to find any of the following packages: ${libraries.join(", ")}`
44
- );
45
- }
46
- async function getArgosPlaywrightVersion() {
47
- const pkgPath = require2.resolve("@argos-ci/playwright/package.json");
48
- return readVersionFromPackage(pkgPath);
49
- }
50
- async function getSdkMetadata() {
51
- const metadataConfig = metadataConfigStorage.getStore();
52
- if (metadataConfig) {
53
- return metadataConfig.sdk;
54
- }
55
- const argosPlaywrightVersion = await getArgosPlaywrightVersion();
56
- return {
57
- name: "@argos-ci/playwright",
58
- version: argosPlaywrightVersion
59
- };
60
- }
61
- async function getLibraryMetadata() {
62
- const [automationLibrary, sdk] = await Promise.all([
63
- getAutomationLibraryMetadata(),
64
- getSdkMetadata()
65
- ]);
66
- return {
67
- automationLibrary,
68
- sdk
69
- };
70
- }
71
- async function getTestMetadataFromTestCase(testCase, testResult) {
72
- const repositoryPath = await getGitRepositoryPath();
73
- const testMetadata = {
74
- title: testCase.title,
75
- titlePath: testCase.titlePath(),
76
- tags: testCase.tags.length > 0 ? testCase.tags : void 0,
77
- retry: testResult.retry,
78
- retries: testCase.retries,
79
- repeat: testCase.repeatEachIndex,
80
- location: {
81
- file: repositoryPath ? relative(repositoryPath, testCase.location.file) : testCase.location.file,
82
- line: testCase.location.line,
83
- column: testCase.location.column
84
- },
85
- annotations: testCase.annotations
86
- };
87
- return testMetadata;
88
- }
89
- async function getMetadataFromTestCase(testCase, testResult) {
90
- const [libMetadata, testMetadata] = await Promise.all([
91
- getLibraryMetadata(),
92
- getTestMetadataFromTestCase(testCase, testResult)
93
- ]);
94
- const metadata = {
95
- test: testMetadata,
96
- ...libMetadata
97
- };
98
- return metadata;
99
- }
100
-
101
- // src/util.ts
102
- import {
103
- getGlobalScript
104
- } from "@argos-ci/browser";
105
- import { dirname, resolve } from "path";
106
- import { mkdir } from "fs/promises";
107
- var require3 = createRequire2(import.meta.url);
108
- var PNG_EXTENSION = `.png`;
109
- var ARIA_EXTENSION = `.aria.yml`;
110
- var METADATA_EXTENSION = `.argos.json`;
111
- var MAX_NAME_LENGTH = 255 - PNG_EXTENSION.length - METADATA_EXTENSION.length;
112
- function truncate(text, length) {
113
- if (text.length <= length) {
114
- return text;
115
- }
116
- return text.slice(0, length - 1) + "\u2026";
117
- }
118
- function getAutomaticScreenshotName(test, result) {
119
- const name = test.titlePath().join(" ");
120
- let suffix = "";
121
- suffix += result.retry > 0 ? ` #${result.retry + 1}` : "";
122
- suffix += result.status === "failed" || result.status === "timedOut" ? " (failed)" : "";
123
- const maxNameLength = MAX_NAME_LENGTH - suffix.length;
124
- if (name.length > maxNameLength) {
125
- return `${truncate(`${test.id} - ${test.title}`, maxNameLength)}${suffix}`;
126
- }
127
- return `${name}${suffix}`;
128
- }
129
-
130
- // src/attachment.ts
131
- function parseAttachmentName(name) {
132
- const match = name.match(/^argos\/(screenshot|aria)(\/metadata)?___(.*)$/);
133
- if (!match) {
134
- return null;
135
- }
136
- const [, mainType, metadataPart, originalName] = match;
137
- if (!originalName) {
138
- throw new Error(`Invalid attachment name: ${name}`);
139
- }
140
- const type = metadataPart ? `${mainType}/metadata` : mainType;
141
- return { type, originalName };
142
- }
143
- function getAttachmentFilename(attachment) {
144
- const parsed = parseAttachmentName(attachment.name);
145
- if (!parsed) {
146
- throw new Error(`Invalid attachment name: ${attachment.name}`);
147
- }
148
- const { type, originalName } = parsed;
149
- const extension = {
150
- screenshot: PNG_EXTENSION,
151
- aria: ARIA_EXTENSION,
152
- "screenshot/metadata": `${PNG_EXTENSION}${METADATA_EXTENSION}`,
153
- "aria/metadata": `${ARIA_EXTENSION}${METADATA_EXTENSION}`
154
- }[type];
155
- return `${originalName}${extension}`;
156
- }
157
- function checkIsTrace(attachment) {
158
- return attachment.name === "trace" && attachment.contentType === "application/zip" && Boolean(attachment.path);
159
- }
160
- function checkIsArgosSnapshot(attachment) {
161
- const parsed = parseAttachmentName(attachment.name);
162
- if (!parsed) {
163
- return false;
164
- }
165
- return parsed.type === "aria" || parsed.type === "screenshot";
166
- }
167
- function checkIsArgosMetadata(attachment) {
168
- const parsed = parseAttachmentName(attachment.name);
169
- if (!parsed) {
170
- return false;
171
- }
172
- return parsed.type === "aria/metadata" || parsed.type === "screenshot/metadata";
173
- }
174
- function checkIsAutomaticScreenshot(attachment) {
175
- return attachment.name === "screenshot" && attachment.contentType === "image/png" && Boolean(attachment.path);
176
- }
177
-
178
- // src/debug.ts
179
- import createDebug from "debug";
180
- var KEY = "@argos-ci/playwright";
181
- var debug = createDebug(KEY);
182
-
183
- // src/reporter.ts
184
- import { createDirectory, createTemporaryDirectory } from "@argos-ci/util";
185
- function checkIsDynamicBuildName(buildName) {
186
- return Boolean(typeof buildName === "object" && buildName);
187
- }
188
- function createArgosReporterOptions(options) {
189
- return options;
190
- }
191
- async function getParallelFromConfig(config) {
192
- if (!config.shard) {
193
- return null;
194
- }
195
- if (config.shard.total === 1) {
196
- return null;
197
- }
198
- const argosConfig = await readConfig();
199
- if (!argosConfig.parallelNonce) {
200
- throw new Error(
201
- "Playwright shard mode detected. Please specify ARGOS_PARALLEL_NONCE env variable. Read /parallel-testing"
202
- );
203
- }
204
- return {
205
- total: argosConfig.parallelTotal ?? config.shard.total,
206
- nonce: argosConfig.parallelNonce,
207
- index: argosConfig.parallelIndex ?? config.shard.current
208
- };
209
- }
210
- var ArgosReporter = class {
211
- rootUploadDirectoryPromise;
212
- uploadDirectoryPromises;
213
- config;
214
- playwrightConfig;
215
- uploadToArgos;
216
- constructor(config) {
217
- this.config = config;
218
- this.uploadToArgos = config.uploadToArgos ?? true;
219
- this.rootUploadDirectoryPromise = null;
220
- this.uploadDirectoryPromises = /* @__PURE__ */ new Map();
221
- }
222
- /**
223
- * Write a file to the temporary directory.
224
- */
225
- async writeFile(path, body) {
226
- await createDirectory(dirname2(path));
227
- debug(`Writing file to ${path}`);
228
- await writeFile(path, body);
229
- debug(`File written to ${path}`);
230
- }
231
- /**
232
- * Copy a file to the temporary directory.
233
- */
234
- async copyFile(from, to) {
235
- await createDirectory(dirname2(to));
236
- debug(`Copying file from ${from} to ${to}`);
237
- await copyFile(from, to);
238
- debug(`File copied from ${from} to ${to}`);
239
- }
240
- /**
241
- * Copy the trace file if found in the result.
242
- */
243
- async copyTraceIfFound(result, path) {
244
- const trace = result.attachments.find(checkIsTrace) ?? null;
245
- if (trace) {
246
- await this.copyFile(trace.path, path + ".pw-trace.zip");
247
- }
248
- }
249
- /**
250
- * Get the root upload directory (cached).
251
- */
252
- getRootUploadDirectory() {
253
- if (!this.rootUploadDirectoryPromise) {
254
- this.rootUploadDirectoryPromise = createTemporaryDirectory();
255
- }
256
- return this.rootUploadDirectoryPromise;
257
- }
258
- onBegin(config) {
259
- debug("ArgosReporter:onBegin");
260
- this.playwrightConfig = config;
261
- }
262
- async onTestEnd(test, result) {
263
- const buildName = checkIsDynamicBuildName(this.config.buildName) ? this.config.buildName.get(test) : this.config.buildName;
264
- if (buildName === "") {
265
- throw new Error('Argos "buildName" cannot be an empty string.');
266
- }
267
- const rootUploadDir = await this.getRootUploadDirectory();
268
- const uploadDir = buildName ? join(rootUploadDir, buildName) : rootUploadDir;
269
- debug("ArgosReporter:onTestEnd");
270
- await Promise.all(
271
- result.attachments.map(async (attachment) => {
272
- if (checkIsArgosSnapshot(attachment) || checkIsArgosMetadata(attachment)) {
273
- const path = join(uploadDir, getAttachmentFilename(attachment));
274
- await Promise.all([
275
- this.copyFile(attachment.path, path),
276
- this.copyTraceIfFound(result, path)
277
- ]);
278
- return;
279
- }
280
- if (checkIsAutomaticScreenshot(attachment)) {
281
- const metadata = await getMetadataFromTestCase(test, result);
282
- const name = getAutomaticScreenshotName(test, result);
283
- const path = join(uploadDir, `${name}${PNG_EXTENSION}`);
284
- await Promise.all([
285
- this.writeFile(path + METADATA_EXTENSION, JSON.stringify(metadata)),
286
- this.copyFile(attachment.path, path),
287
- this.copyTraceIfFound(result, path)
288
- ]);
289
- return;
290
- }
291
- })
292
- );
293
- }
294
- async onEnd(result) {
295
- debug("ArgosReporter:onEnd");
296
- const rootUploadDir = await this.getRootUploadDirectory();
297
- if (!this.uploadToArgos) {
298
- debug("Not uploading to Argos because uploadToArgos is false.");
299
- debug(`Upload directory: ${rootUploadDir}`);
300
- return;
301
- }
302
- debug("Getting parallel from config");
303
- const parallel = await getParallelFromConfig(this.playwrightConfig);
304
- if (parallel) {
305
- debug(
306
- `Using parallel config \u2014 total: ${parallel.total}, nonce: "${parallel.nonce}"`
307
- );
308
- } else {
309
- debug("Non-parallel mode");
310
- }
311
- const buildNameConfig = this.config.buildName;
312
- const uploadOptions = {
313
- files: ["**/*.png", "**/*.aria.yml"],
314
- parallel: parallel ?? void 0,
315
- ...this.config,
316
- buildName: void 0,
317
- // We will set it later
318
- metadata: {
319
- testReport: {
320
- status: result.status,
321
- stats: {
322
- startTime: result.startTime.toISOString(),
323
- duration: result.duration
324
- }
325
- }
326
- }
327
- };
328
- try {
329
- if (checkIsDynamicBuildName(buildNameConfig)) {
330
- debug(
331
- `Dynamic build names, uploading to Argos for each build name: ${buildNameConfig.values.join()}`
332
- );
333
- const directories = await readdir(rootUploadDir);
334
- if (directories.some((dir) => !buildNameConfig.values.includes(dir))) {
335
- throw new Error(
336
- `The \`buildName.values\` (${buildNameConfig.values.join(", ")}) are inconsistent with the \`buildName.get\` returns values (${directories.join(", ")}). Please fix the configuration.`
337
- );
338
- }
339
- const iteratesOnBuildNames = parallel ? buildNameConfig.values : directories;
340
- for (const buildName of iteratesOnBuildNames) {
341
- const uploadDir = join(rootUploadDir, buildName);
342
- await createDirectory(uploadDir);
343
- debug(`Uploading to Argos for build: ${buildName}`);
344
- const res = await upload({
345
- ...uploadOptions,
346
- root: uploadDir,
347
- buildName
348
- });
349
- console.log(
350
- chalk.green(
351
- `\u2705 Argos "${buildName}" build created: ${res.build.url}`
352
- )
353
- );
354
- }
355
- } else {
356
- debug("Uploading to Argos");
357
- const uploadDir = buildNameConfig ? join(rootUploadDir, buildNameConfig) : rootUploadDir;
358
- const res = await upload({
359
- ...uploadOptions,
360
- root: uploadDir,
361
- buildName: buildNameConfig ?? void 0
362
- });
363
- console.log(chalk.green(`\u2705 Argos build created: ${res.build.url}`));
364
- }
365
- } catch (error) {
366
- console.error(chalk.red(`\u274C Error while creating the Argos build`));
367
- console.error(error);
368
- if (!this.config.ignoreUploadFailures) {
369
- return { status: "failed" };
370
- } else {
371
- console.warn(
372
- chalk.yellow(
373
- "\u26A0\uFE0F Upload failure ignored due to ignoreUploadFailures option"
374
- )
375
- );
376
- }
377
- }
378
- return;
379
- }
380
- printsToStdio() {
381
- return false;
382
- }
383
- };
384
- var reporter_default = ArgosReporter;
385
- export {
386
- createArgosReporterOptions,
387
- reporter_default as default
388
- };