@empiricalrun/playwright-utils 0.18.11 → 0.18.12

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @empiricalrun/playwright-utils
2
2
 
3
+ ## 0.18.12
4
+
5
+ ### Patch Changes
6
+
7
+ - 97f2b70: feat: send test case run event on onTestEnd
8
+
3
9
  ## 0.18.11
4
10
 
5
11
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/reporter/custom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EAMV,KAAK,EACL,QAAQ,IAAI,cAAc,EAC1B,SAAS,EACT,UAAU,IAAI,gBAAgB,EAE/B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAML,UAAU,EAMX,MAAM,2BAA2B,CAAC;AAiBnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAiC/C,QAAA,MAAM,iBAAiB,UAAoC,CAAC;AAC5D,KAAK,oBAAoB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAM/D,KAAK,mBAAmB,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AA6BF,cAAM,YAAa,YAAW,UAAU;IACtC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,mBAAmB,CAAU;IACrC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,oBAAoB,CAAiC;IAC7D,OAAO,CAAC,kBAAkB,CAAyC;IACnE,OAAO,CAAC,kBAAkB,CAEpB;IACN,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,OAAO,CAAC,YAAY;YA4BN,uBAAuB;IAQrC,OAAO,CAAC,YAAY,CAEN;IACd,OAAO,CAAC,eAAe,CAAmB;gBAE9B,OAAO,EAAE,mBAAmB;IAIxC,aAAa;IAIb,QAAQ;IAER,QAAQ;IAER,WAAW;IAEX,SAAS;IAET,WAAW,CAAC,IAAI,EAAE,cAAc;IAIhC,OAAO,IAAI,IAAI;IAIf,SAAS,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB;IAUxD,OAAO,CAAC,qBAAqB;IAoD7B,WAAW,CAAC,MAAM,EAAE,UAAU;IAI9B,OAAO,CAAC,KAAK,EAAE,KAAK;IAYpB,eAAe,IAAI;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,IAAI,EAAE,oBAAoB,CAAC;QAC3B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QACzB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;KAC1B;IAsBD,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IASxD,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAIzB,KAAK,CAAC,MAAM,EAAE,UAAU;IA+IxB,MAAM;CA8Bb;AAwED,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,IAAI,GAAE,MAAoB,EAC1B,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,iBAqBhB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAsBhE;AAqiBD,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/reporter/custom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EAMV,KAAK,EACL,QAAQ,IAAI,cAAc,EAC1B,SAAS,EACT,UAAU,IAAI,gBAAgB,EAE/B,MAAM,2BAA2B,CAAC;AAInC,OAAO,EAML,UAAU,EAMX,MAAM,2BAA2B,CAAC;AAiBnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAqC/C,QAAA,MAAM,iBAAiB,UAAoC,CAAC;AAC5D,KAAK,oBAAoB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAM/D,KAAK,mBAAmB,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AA6BF,cAAM,YAAa,YAAW,UAAU;IACtC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,mBAAmB,CAAU;IACrC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,oBAAoB,CAAiC;IAC7D,OAAO,CAAC,kBAAkB,CAAyC;IACnE,OAAO,CAAC,kBAAkB,CAEpB;IACN,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,OAAO,CAAC,YAAY;YA4BN,uBAAuB;IAQrC,OAAO,CAAC,YAAY,CAEN;IACd,OAAO,CAAC,eAAe,CAAmB;gBAE9B,OAAO,EAAE,mBAAmB;IAIxC,aAAa;IAIb,QAAQ;IAER,QAAQ;IAER,WAAW;IAEX,SAAS;IAET,WAAW,CAAC,IAAI,EAAE,cAAc;IAIhC,OAAO,IAAI,IAAI;IAIf,SAAS,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB;YAuD1C,qBAAqB;IAuDnC,WAAW,CAAC,MAAM,EAAE,UAAU;IAI9B,OAAO,CAAC,KAAK,EAAE,KAAK;IAYpB,eAAe,IAAI;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,IAAI,EAAE,oBAAoB,CAAC;QAC3B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QACzB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;KAC1B;IAsBD,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IASxD,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAIzB,KAAK,CAAC,MAAM,EAAE,UAAU;IA+IxB,MAAM;CA8Bb;AAwED,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,IAAI,GAAE,MAAoB,EAC1B,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,iBAqBhB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAsBhE;AAsiBD,eAAe,YAAY,CAAC"}
@@ -23,6 +23,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
23
23
  exports.startHtmlReportServer = exports.showHTMLReport = void 0;
24
24
  const code_frame_1 = require("@babel/code-frame");
25
25
  const r2_uploader_1 = require("@empiricalrun/r2-uploader");
26
+ const crypto_1 = require("crypto");
26
27
  const fs_1 = __importDefault(require("fs"));
27
28
  const path_1 = __importDefault(require("path"));
28
29
  const utils_1 = require("playwright-core/lib/utils");
@@ -127,15 +128,50 @@ class HtmlReporter {
127
128
  }
128
129
  onTestEnd(test, result) {
129
130
  try {
130
- result.attachments.forEach(async (attachment) => {
131
+ const attachmentPromises = result.attachments.map((attachment) => {
131
132
  return this.processTestAttachment(attachment);
132
133
  });
134
+ Promise.all(attachmentPromises)
135
+ .then((uploadedAttachments) => {
136
+ if (!uploadedAttachments) {
137
+ return;
138
+ }
139
+ logger_1.logger.info(`All attachments processed, test data sent for test: ${test.title}`);
140
+ let params = {
141
+ assetsURL: {
142
+ trace: "",
143
+ videos: [],
144
+ },
145
+ test,
146
+ result,
147
+ runId: process.env.TEST_RUN_GITHUB_ACTION_ID || "",
148
+ };
149
+ uploadedAttachments.forEach((attachment) => {
150
+ if (attachment) {
151
+ Object.entries(attachment).forEach(([key, value]) => {
152
+ if (key.includes("video")) {
153
+ params.assetsURL.videos.push({
154
+ name: `test-${test.id}-slug-${(0, crypto_1.randomUUID)()}`,
155
+ url: value,
156
+ });
157
+ }
158
+ if (key.includes("trace")) {
159
+ params.assetsURL.trace = value;
160
+ }
161
+ });
162
+ }
163
+ });
164
+ return (0, util_1.sendTestCaseUpdateToDashboard)(params);
165
+ })
166
+ .catch((error) => {
167
+ logger_1.logger.error(`Error processing attachments for test: ${test.title}:`, error);
168
+ });
133
169
  }
134
170
  catch (e) {
135
- logger_1.logger.error("Error while processing attachments for test", e);
171
+ logger_1.logger.error(`Error while processing attachments for test ${test.title}:`, e);
136
172
  }
137
173
  }
138
- processTestAttachment(attachment) {
174
+ async processTestAttachment(attachment) {
139
175
  if (!attachment.path)
140
176
  return;
141
177
  if (this.haveSeenAttachments.has(attachment.path))
@@ -148,16 +184,19 @@ class HtmlReporter {
148
184
  return;
149
185
  }
150
186
  try {
151
- const uploadTask = async () => (0, r2_uploader_1.uploadDirectory)({
152
- fileList: [attachment.path],
153
- sourceDir: this._outputFolder + "/data/" + folderName,
154
- destinationDir: process.env.PROJECT_NAME +
155
- "/" +
156
- process.env.TEST_RUN_GITHUB_ACTION_ID +
157
- "/data/" +
158
- folderName,
159
- uploadBucket: "test-report",
160
- });
187
+ const uploadTask = async () => {
188
+ const uploadedFiles = await (0, r2_uploader_1.uploadDirectory)({
189
+ fileList: [attachment.path],
190
+ sourceDir: this._outputFolder + "/data/" + folderName,
191
+ destinationDir: process.env.PROJECT_NAME +
192
+ "/" +
193
+ process.env.TEST_RUN_GITHUB_ACTION_ID +
194
+ "/data/" +
195
+ folderName,
196
+ uploadBucket: "test-report",
197
+ });
198
+ return uploadedFiles;
199
+ };
161
200
  if (this.uploadExecutionQueue.length <= this.uploadMaxQueueSize) {
162
201
  const promise = uploadTask()
163
202
  .catch((e) => {
@@ -171,6 +210,7 @@ class HtmlReporter {
171
210
  this.processQueue(); // Keep processing queue
172
211
  });
173
212
  this.uploadExecutionQueue.push(promise);
213
+ return promise;
174
214
  }
175
215
  else {
176
216
  logger_1.logger.debug("Queuing upload task ", attachment.path);
@@ -579,7 +619,8 @@ class HtmlBuilder {
579
619
  fs_1.default.appendFileSync(indexFile, '";</script>');
580
620
  let singleTestId;
581
621
  if (htmlReport.stats.total === 1) {
582
- const testFile = data.values().next().value?.testFile;
622
+ const testFile = data.values().next()
623
+ ?.value?.testFile;
583
624
  singleTestId = testFile?.tests[0]?.testId;
584
625
  }
585
626
  return { ok, singleTestId };
@@ -0,0 +1,15 @@
1
+ import { TestCase, TestResult } from "@playwright/test/reporter";
2
+ export type VideoURL = {
3
+ name: string;
4
+ url: string;
5
+ };
6
+ export type TestCaseRunEndEvent = {
7
+ assetsURL: {
8
+ trace: string;
9
+ videos: VideoURL[];
10
+ };
11
+ test: TestCase;
12
+ result: TestResult;
13
+ runId: string;
14
+ };
15
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/reporter/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE;QACT,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,QAAQ,EAAE,CAAC;KACpB,CAAC;IACF,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -16,6 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
  /// <reference types="node" />
19
+ import { TestCaseRunEndEvent } from "./types";
19
20
  export declare function getPackageJsonPath(folderPath: string): string;
20
21
  export declare function resolveReporterOutputPath(defaultValue: string, configDir: string, configValue: string | undefined): string;
21
22
  export declare function normalizeAndSaveAttachment(outputPath: string, name: string, options?: {
@@ -28,4 +29,6 @@ export declare function normalizeAndSaveAttachment(outputPath: string, name: str
28
29
  body?: Buffer | undefined;
29
30
  contentType: string;
30
31
  }>;
32
+ export declare function sendTestCaseUpdateToDashboard(params: TestCaseRunEndEvent): Promise<void>;
33
+ export declare function safelySerialiseJSON(obj: any, keyFilter?: (key: string) => boolean): any;
31
34
  //# sourceMappingURL=util.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/reporter/util.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;;AAiBH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAmB7D;AAED,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAAG,SAAS,UAMhC;AAED,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5E,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAyCD"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/reporter/util.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;;AAiBH,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAK9C,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAmB7D;AAED,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAAG,SAAS,UAMhC;AAED,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5E,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAyCD;AAED,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAqDf;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,GAAG,EACR,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,GACnC,GAAG,CAIL"}
@@ -20,12 +20,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
20
20
  return (mod && mod.__esModule) ? mod : { "default": mod };
21
21
  };
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.normalizeAndSaveAttachment = exports.resolveReporterOutputPath = exports.getPackageJsonPath = void 0;
23
+ exports.safelySerialiseJSON = exports.sendTestCaseUpdateToDashboard = exports.normalizeAndSaveAttachment = exports.resolveReporterOutputPath = exports.getPackageJsonPath = void 0;
24
+ const async_retry_1 = __importDefault(require("async-retry"));
24
25
  const fs_1 = __importDefault(require("fs"));
25
26
  const path_1 = __importDefault(require("path"));
26
27
  const utils_1 = require("playwright-core/lib/utils");
27
28
  const utilsBundle_1 = require("playwright-core/lib/utilsBundle");
29
+ const logger_1 = require("../logger");
28
30
  const folderToPackageJsonPath = new Map();
31
+ const API_TOKEN = "weQPMWKT";
29
32
  function getPackageJsonPath(folderPath) {
30
33
  const cached = folderToPackageJsonPath.get(folderPath);
31
34
  if (cached !== undefined)
@@ -87,3 +90,51 @@ async function normalizeAndSaveAttachment(outputPath, name, options = {}) {
87
90
  }
88
91
  }
89
92
  exports.normalizeAndSaveAttachment = normalizeAndSaveAttachment;
93
+ async function sendTestCaseUpdateToDashboard(params) {
94
+ const DOMAIN = process.env.DASHBOARD_DOMAIN || "https://dash.empirical.run";
95
+ try {
96
+ const keyFilter = (key) => key === "parent";
97
+ const payload = {
98
+ ...params,
99
+ test: safelySerialiseJSON(params.test, keyFilter),
100
+ result: safelySerialiseJSON(params.result, keyFilter),
101
+ };
102
+ const requestBody = {
103
+ name: "test_case_run_end",
104
+ data: {
105
+ ...payload,
106
+ },
107
+ };
108
+ if (!DOMAIN) {
109
+ console.warn("No dashboard domain found. Skipping send message to dashboard.");
110
+ return;
111
+ }
112
+ await (0, async_retry_1.default)(async () => {
113
+ const response = await fetch(`${DOMAIN}/api/test-runs/events`, {
114
+ method: "PUT",
115
+ headers: {
116
+ "Content-Type": "application/json",
117
+ Authorization: API_TOKEN,
118
+ },
119
+ body: JSON.stringify(requestBody),
120
+ });
121
+ if (!response.ok) {
122
+ throw new Error(`Failed to publish test case diagnois: ${response.status}`);
123
+ }
124
+ }, {
125
+ retries: 3,
126
+ minTimeout: 1000,
127
+ maxTimeout: 60000,
128
+ factor: 3,
129
+ });
130
+ logger_1.logger.info("Successfully sent test case update to dashboard");
131
+ }
132
+ catch (e) {
133
+ console.error(e.message);
134
+ }
135
+ }
136
+ exports.sendTestCaseUpdateToDashboard = sendTestCaseUpdateToDashboard;
137
+ function safelySerialiseJSON(obj, keyFilter) {
138
+ return JSON.parse(JSON.stringify(obj, (key, value) => (keyFilter?.(key) ? undefined : value)));
139
+ }
140
+ exports.safelySerialiseJSON = safelySerialiseJSON;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/playwright-utils",
3
- "version": "0.18.11",
3
+ "version": "0.18.12",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -23,6 +23,7 @@
23
23
  "author": "Empirical Team <hey@empirical.run>",
24
24
  "devDependencies": {
25
25
  "@playwright/test": "1.47.1",
26
+ "@types/async-retry": "^1.4.8",
26
27
  "@types/babel__code-frame": "^7.0.6",
27
28
  "@types/console-log-level": "^1.4.5",
28
29
  "@types/md5": "^2.3.5",
@@ -33,6 +34,7 @@
33
34
  "@aws-sdk/client-s3": "^3.614.0",
34
35
  "@aws-sdk/s3-request-presigner": "^3.614.0",
35
36
  "@babel/code-frame": "^7.24.7",
37
+ "async-retry": "^1.3.3",
36
38
  "console-log-level": "^1.4.1",
37
39
  "mailosaur": "^8.6.1",
38
40
  "md5": "^2.3.0",
@@ -41,9 +43,9 @@
41
43
  "playwright-extra": "^4.3.6",
42
44
  "puppeteer-extra-plugin-recaptcha": "^3.6.8",
43
45
  "rimraf": "^6.0.1",
44
- "@empiricalrun/r2-uploader": "^0.3.7",
46
+ "@empiricalrun/llm": "^0.9.28",
45
47
  "@empiricalrun/test-gen": "^0.38.39",
46
- "@empiricalrun/llm": "^0.9.28"
48
+ "@empiricalrun/r2-uploader": "^0.3.7"
47
49
  },
48
50
  "scripts": {
49
51
  "dev": "tsc --build --watch",