@qualflare/playwright 0.3.0 → 0.4.1

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.
@@ -22,6 +22,7 @@ var MAX_ATTEMPT_SNIPPET_RUNES = 4096;
22
22
  var MAX_ATTEMPT_OUTPUT_RUNES = 16384;
23
23
  var MAX_ATTEMPT_OUTPUT_LINES = 200;
24
24
  var MAX_VIDEO_UPLOAD_BYTES = 50 * 1024 * 1024;
25
+ var MAX_TRACE_UPLOAD_BYTES = 50 * 1024 * 1024;
25
26
  var MAX_STEPS_PER_TEST_ATTEMPT = 300;
26
27
 
27
28
  // src/config/ci-detect.ts
@@ -249,6 +250,7 @@ function resolveConfig(options, deps = {}) {
249
250
  maxAttachmentBytes: options.maxAttachmentBytes ?? envInt("QUALFLARE_MAX_ATTACHMENT_BYTES") ?? 15e5,
250
251
  maxTotalAttachmentBytes: options.maxTotalAttachmentBytes ?? envInt("QUALFLARE_MAX_TOTAL_ATTACHMENT_BYTES") ?? 75e4,
251
252
  maxVideoBytes: options.maxVideoBytes ?? envInt("QUALFLARE_MAX_VIDEO_BYTES") ?? MAX_VIDEO_UPLOAD_BYTES,
253
+ maxTraceBytes: options.maxTraceBytes ?? envInt("QUALFLARE_MAX_TRACE_BYTES") ?? MAX_TRACE_UPLOAD_BYTES,
252
254
  debug: options.debug ?? envBool("QUALFLARE_DEBUG", "QF_DEBUG") ?? false,
253
255
  enabled,
254
256
  outputDir,
@@ -285,35 +287,51 @@ var VIDEO_MIME_TYPES_BY_EXTENSION = {
285
287
  ".webm": "video/webm",
286
288
  ".mov": "video/quicktime"
287
289
  };
288
- function copyVideoAttachment(filePath, outputDir, maxVideoBytes) {
289
- const ext = path.extname(filePath).toLowerCase();
290
- const mimeType = VIDEO_MIME_TYPES_BY_EXTENSION[ext];
291
- if (!mimeType) {
292
- logger.warn(`skipping video attachment "${filePath}": unsupported video format.`);
293
- return void 0;
294
- }
290
+ var TRACE_MIME_TYPE = "application/zip";
291
+ var TRACE_EXTENSION = ".zip";
292
+ function copyArtifact(filePath, outputDir, maxBytes, ext, capName, label) {
295
293
  let fileSize;
296
294
  try {
297
295
  fileSize = fs.statSync(filePath).size;
298
296
  } catch (err) {
299
- logger.warn(`skipping video attachment "${filePath}": could not stat file: ${err.message}`);
297
+ logger.warn(`skipping ${label} attachment "${filePath}": could not stat file: ${err.message}`);
300
298
  return void 0;
301
299
  }
302
- if (fileSize > maxVideoBytes) {
300
+ if (fileSize > maxBytes) {
303
301
  logger.warn(
304
- `skipping video attachment "${filePath}": ${fileSize} bytes exceeds the configured maxVideoBytes cap of ${maxVideoBytes} bytes.`
302
+ `skipping ${label} attachment "${filePath}": ${fileSize} bytes exceeds the configured ${capName} cap of ${maxBytes} bytes.`
305
303
  );
306
304
  return void 0;
307
305
  }
308
- const localVideoPath = `${randomUUID2()}${ext}`;
306
+ const localPath = `${randomUUID2()}${ext}`;
309
307
  try {
310
308
  fs.mkdirSync(outputDir, { recursive: true });
311
- fs.copyFileSync(filePath, path.join(outputDir, localVideoPath));
309
+ fs.copyFileSync(filePath, path.join(outputDir, localPath));
312
310
  } catch (err) {
313
- logger.warn(`skipping video attachment "${filePath}": could not copy file: ${err.message}`);
311
+ logger.warn(`skipping ${label} attachment "${filePath}": could not copy file: ${err.message}`);
312
+ return void 0;
313
+ }
314
+ return { localPath, fileSize };
315
+ }
316
+ function copyVideoAttachment(filePath, outputDir, maxVideoBytes) {
317
+ const ext = path.extname(filePath).toLowerCase();
318
+ const mimeType = VIDEO_MIME_TYPES_BY_EXTENSION[ext];
319
+ if (!mimeType) {
320
+ logger.warn(`skipping video attachment "${filePath}": unsupported video format.`);
314
321
  return void 0;
315
322
  }
316
- return { localVideoPath, fileSize, mimeType };
323
+ const copied = copyArtifact(filePath, outputDir, maxVideoBytes, ext, "maxVideoBytes", "video");
324
+ if (!copied) {
325
+ return void 0;
326
+ }
327
+ return { localVideoPath: copied.localPath, fileSize: copied.fileSize, mimeType };
328
+ }
329
+ function copyTraceAttachment(filePath, outputDir, maxTraceBytes) {
330
+ const copied = copyArtifact(filePath, outputDir, maxTraceBytes, TRACE_EXTENSION, "maxTraceBytes", "trace");
331
+ if (!copied) {
332
+ return void 0;
333
+ }
334
+ return { localTracePath: copied.localPath, fileSize: copied.fileSize, mimeType: TRACE_MIME_TYPE };
317
335
  }
318
336
 
319
337
  // src/reporter/attachment-reader.ts
@@ -343,6 +361,7 @@ var AttachmentBudget = class {
343
361
  };
344
362
  var NAME_VIDEO = "video";
345
363
  var NAME_TRACE = "trace";
364
+ var TRACE_CONTENT_TYPE = "application/zip";
346
365
  function isVideo(a) {
347
366
  return a.name === NAME_VIDEO || (a.contentType?.startsWith("video/") ?? false);
348
367
  }
@@ -363,7 +382,20 @@ function resolveAttachments(result, config, budget) {
363
382
  }
364
383
  break;
365
384
  }
366
- if (a.name === NAME_TRACE || a.contentType === "application/zip") {
385
+ if (a.name === NAME_TRACE || a.contentType === TRACE_CONTENT_TYPE) {
386
+ if (!a.path) {
387
+ logger.warn(`skipping in-memory trace attachment "${a.name}": only file-backed traces are supported.`);
388
+ continue;
389
+ }
390
+ const copied = copyTraceAttachment(a.path, config.outputDir, config.maxTraceBytes);
391
+ if (copied) {
392
+ out.push({
393
+ name: a.name,
394
+ mimeType: copied.mimeType,
395
+ localTracePath: copied.localTracePath,
396
+ fileSize: copied.fileSize
397
+ });
398
+ }
367
399
  continue;
368
400
  }
369
401
  if (isVideo(a)) {
@@ -793,7 +825,7 @@ function buildCase(test, config, attachmentsByResult, budget) {
793
825
  import * as os from "os";
794
826
 
795
827
  // src/config/version.ts
796
- var PACKAGE_VERSION = "0.3.0";
828
+ var PACKAGE_VERSION = "0.4.1";
797
829
 
798
830
  // src/reporter/collect-builder.ts
799
831
  function resolveOs(config) {
@@ -984,7 +1016,8 @@ var QualflareReporter = class {
984
1016
  return path3.isAbsolute(outputDir) ? outputDir : path3.resolve(this.options.configDir ?? this.rootDir, outputDir);
985
1017
  }
986
1018
  /** Drops everything an earlier, now-superseded attempt produced: deletes the
987
- * video copied into outputDir and refunds its bytes to the run budget. */
1019
+ * video or trace copied into outputDir and refunds its bytes to the run
1020
+ * budget. */
988
1021
  discardSupersededAttempt(testId, retry, outputDir) {
989
1022
  const previous = this.latestAttemptByTest.get(testId);
990
1023
  if (previous === void 0 || previous >= retry) {
@@ -992,9 +1025,10 @@ var QualflareReporter = class {
992
1025
  }
993
1026
  const key = `${testId}:${previous}`;
994
1027
  for (const attachment of this.attachmentsByResult.get(key) ?? []) {
995
- if (attachment.localVideoPath) {
1028
+ const orphan = attachment.localVideoPath ?? attachment.localTracePath;
1029
+ if (orphan) {
996
1030
  try {
997
- fs3.rmSync(path3.join(this.resolveOutputDir(outputDir), attachment.localVideoPath), { force: true });
1031
+ fs3.rmSync(path3.join(this.resolveOutputDir(outputDir), orphan), { force: true });
998
1032
  } catch {
999
1033
  }
1000
1034
  }