@apica-io/asm-playwright-runner 1.0.0-dev.1 → 1.0.0-dev.2

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.
@@ -92,6 +92,10 @@ function extractResources(zipPath_1) {
92
92
  .on('error', reject);
93
93
  });
94
94
  });
95
+ const errorContext = path_1.default.join(baseDir, "error-context.md");
96
+ if (fs_1.default.existsSync(errorContext)) {
97
+ fs_1.default.copyFileSync(errorContext, path_1.default.join(sourceDir, "error-context.md"));
98
+ }
95
99
  yield Promise.all([...imagePromises, ...sourcePromises]);
96
100
  });
97
101
  }
@@ -116,8 +120,8 @@ function zipResources(outputZipPath, screenshotsDir, sourceDir) {
116
120
  exports.zipResources = zipResources;
117
121
  function setHookActions(traceRawResult) {
118
122
  return __awaiter(this, void 0, void 0, function* () {
119
- var _a;
120
- const hookModel = { actions: [], stdio: [] };
123
+ var _a, _b;
124
+ const hookModel = { actions: [], stdio: [], errors: [] };
121
125
  const hookActions = {};
122
126
  for (const [index, row] of traceRawResult.entries()) {
123
127
  const entry = JSON.parse(row);
@@ -137,7 +141,7 @@ function setHookActions(traceRawResult) {
137
141
  });
138
142
  continue;
139
143
  }
140
- else if (entry.type === "stdout") {
144
+ else if (entry.type === "stdout" || entry.type === "stderr") {
141
145
  (_a = hookModel === null || hookModel === void 0 ? void 0 : hookModel.stdio) === null || _a === void 0 ? void 0 : _a.push(entry);
142
146
  }
143
147
  else if (entry.type === "before") {
@@ -161,10 +165,17 @@ function setHookActions(traceRawResult) {
161
165
  Object.assign(hookActions[entry.callId], {
162
166
  endTime: entry.endTime,
163
167
  annotations: entry.annotations,
168
+ error: entry.error,
164
169
  });
165
170
  }
171
+ else if (entry.type == "error") {
172
+ (_b = hookModel.errors) === null || _b === void 0 ? void 0 : _b.push(entry);
173
+ }
166
174
  if (index === (traceRawResult.length - 1) && entry.type === "after") {
167
175
  hookModel.endTime = entry.endTime;
176
+ if (hookModel.endTime != null && hookModel.startTime) {
177
+ hookModel.duration = Number((hookModel.endTime - hookModel.startTime).toFixed(3));
178
+ }
168
179
  }
169
180
  }
170
181
  return hookModel;
@@ -173,7 +184,7 @@ function setHookActions(traceRawResult) {
173
184
  exports.setHookActions = setHookActions;
174
185
  function setActions(traceRawResult, traceModel, tracePath, stackData) {
175
186
  return __awaiter(this, void 0, void 0, function* () {
176
- var _a, _b, _c, _d, _e;
187
+ var _a, _b, _c, _d, _e, _f;
177
188
  let beforeFlag = false;
178
189
  let action = null;
179
190
  let targetImages = [];
@@ -194,14 +205,17 @@ function setActions(traceRawResult, traceModel, tracePath, stackData) {
194
205
  else if (entry.type == "event" || entry.type == "console") {
195
206
  (_a = traceModel.events) === null || _a === void 0 ? void 0 : _a.push(entry);
196
207
  }
208
+ else if (entry.type === "stdout" || entry.type === "stderr") {
209
+ (_b = traceModel === null || traceModel === void 0 ? void 0 : traceModel.stdio) === null || _b === void 0 ? void 0 : _b.push(entry);
210
+ }
197
211
  else if (entry.type == "screencast-frame") {
198
- let page = (_b = traceModel.pages) === null || _b === void 0 ? void 0 : _b.find(p => p.pageId === entry.pageId);
212
+ let page = (_c = traceModel.pages) === null || _c === void 0 ? void 0 : _c.find(p => p.pageId === entry.pageId);
199
213
  if (!page) {
200
214
  page = {
201
215
  pageId: entry.pageId,
202
216
  screencastFrames: [],
203
217
  };
204
- (_c = traceModel.pages) === null || _c === void 0 ? void 0 : _c.push(page);
218
+ (_d = traceModel.pages) === null || _d === void 0 ? void 0 : _d.push(page);
205
219
  }
206
220
  targetImages.push(entry.sha1);
207
221
  page.screencastFrames.push(entry);
@@ -226,7 +240,7 @@ function setActions(traceRawResult, traceModel, tracePath, stackData) {
226
240
  }
227
241
  if (beforeFlag && action != null && action.callId == entry.callId) {
228
242
  if (entry.type == "log") {
229
- (_d = action.log) === null || _d === void 0 ? void 0 : _d.push({
243
+ (_e = action.log) === null || _e === void 0 ? void 0 : _e.push({
230
244
  time: entry.time,
231
245
  message: entry.message
232
246
  });
@@ -237,12 +251,15 @@ function setActions(traceRawResult, traceModel, tracePath, stackData) {
237
251
  action.result = entry.result;
238
252
  action.error = entry.error;
239
253
  action.afterSnapshot = entry.afterSnapshot;
240
- (_e = traceModel.actions) === null || _e === void 0 ? void 0 : _e.push(action);
254
+ (_f = traceModel.actions) === null || _f === void 0 ? void 0 : _f.push(action);
241
255
  }
242
256
  }
243
257
  }
244
258
  }
245
259
  traceModel.endTime = action === null || action === void 0 ? void 0 : action.endTime;
260
+ if (traceModel.endTime != null && traceModel.startTime) {
261
+ traceModel.duration = Number((traceModel.endTime - traceModel.startTime).toFixed(3));
262
+ }
246
263
  yield extractResources(tracePath, targetImages);
247
264
  });
248
265
  }
@@ -286,7 +303,8 @@ function prepareTraceModel(tracePath, logLevel) {
286
303
  events: [],
287
304
  resources: [],
288
305
  errors: [],
289
- pages: []
306
+ pages: [],
307
+ stdio: []
290
308
  };
291
309
  if (logLevel == runnerConfig_1.LogLevel.DEBUG) {
292
310
  fs_1.default.writeFileSync(path_1.default.join(path_1.default.dirname(tracePath), "trace-raw-data.json"), JSON.stringify(traceRawResult, null, 2), "utf-8");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apica-io/asm-playwright-runner",
3
- "version": "1.0.0-dev.1",
3
+ "version": "1.0.0-dev.2",
4
4
  "description": "CLI wrapper for Playwright collections or scripts with dynamic actions, config, and test result models.",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {
@@ -10,10 +10,13 @@
10
10
  "build": "tsc",
11
11
  "start": "ts-node src/cli/ index.ts",
12
12
  "dev": "ts-node-dev --respawn src/cli/index.ts",
13
+
13
14
  "test:playwright-script": "ts-node src/cli samples/playwright-script.spec.ts --timeout 10000 --browser chromium --headless -v -r result1 -l debug",
14
15
  "test:playwright/test-script": "ts-node src/cli samples/playwright-test-script.spec.ts --browser chromium --headless -r result2 -l debug",
15
16
  "test:playwright-multi-script": "ts-node src/cli samples/playwright-multi-script.spec.ts --browser chromium --headless -v -r result3 -l debug",
17
+
16
18
  "test:betsson-script": "ts-node src/cli samples/betsson.spec.ts --browser chromium -r result-betsson --headless false -l debug --extraHTTPHeaders {\\\"x-obg-bypass-fabric\\\":\\\"1\\\",\\\"x-obg-experiments\\\":\\\"b1ccAR1gW0f8\\\"}",
19
+
17
20
  "test:playwright-json": "ts-node src/cli samples/example.json --browser chromium --headless -v -r results3",
18
21
  "test:google": "ts-node src/cli samples/google.json --browser chromium --headless -v -r playwright-multi-script",
19
22
  "test:google-firefox": "ts-node src/cli samples/google.json --browser firefox --headless -v -r playwright-multi-script"
@@ -30,12 +33,10 @@
30
33
  "license": "ISC",
31
34
  "dependencies": {
32
35
  "commander": "^11.0.0",
33
- "playwright": "^1.60.0",
34
- "playwright-core": "^1.59.1",
35
36
  "log4js": "^6.3.0"
36
37
  },
37
38
  "devDependencies": {
38
- "@playwright/test": "^1.59.1",
39
+ "@playwright/test": "^1.60.0",
39
40
  "@types/leaflet": "^1.9.15",
40
41
  "@types/node": "^25.6.2",
41
42
  "ts-node": "^10.9.2",
@@ -48,7 +48,7 @@ test.describe('Playwright home page', () => {
48
48
  })
49
49
 
50
50
  test.describe('has Open Graph tags', () => {
51
- const tags = ['description', 'title', 'url']
51
+ const tags = ['description', '1title', '2url']
52
52
 
53
53
  // You can create tests from an array, by calling "test()" in a loop
54
54
  tags.forEach((tag) => {
@@ -1,9 +1,9 @@
1
- import {expect, Page} from "playwright/test";
1
+ import {expect, Page} from "playwright/test";
2
2
 
3
- export default async function example(page: Page) {
4
- await page.goto("https://playwright.dev/");
5
- await expect(page).toHaveTitle(/Playwright/);
3
+ export default async function example(page: Page) {
4
+ await page.goto("https://playwright.dev/");
5
+ await expect(page).toHaveTitle(/Playwright/);
6
6
 
7
- await page.getByRole("link", { name: "Get started" }).click();
8
- await expect(page.getByRole("heading", { name: "Installation" })).toBeVisible();
9
- }
7
+ await page.getByRole("link", { name: "Get started11" }).click();
8
+ await expect(page.getByRole("heading", { name: "Installation" })).toBeVisible();
9
+ }
@@ -1,17 +1,19 @@
1
1
  import { test, expect } from '@playwright/test';
2
2
 
3
+ /*
3
4
  test('has title', async ({ page }) => {
4
5
  await page.goto('https://playwright.dev/');
5
6
 
6
7
  // Expect a title "to contain" a substring.
7
8
  await expect(page).toHaveTitle(/Playwright/);
8
9
  });
10
+ */
9
11
 
10
12
  test('get started link', async ({ page }) => {
11
13
  await page.goto('https://playwright.dev/');
12
14
 
13
15
  // Click the get started link.
14
- await page.getByRole('link', { name: 'Get started' }).click();
16
+ await page.getByRole('link', { name: 'Get started11' }).click();
15
17
 
16
18
  // Expects page to have a heading with the name of Installation.
17
19
  await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
package/src/lib/parser.ts CHANGED
@@ -107,13 +107,22 @@ async function extractResources(
107
107
  });
108
108
  });
109
109
 
110
+ const errorContext = path.join(baseDir, "error-context.md");
111
+
112
+ if (fs.existsSync(errorContext)) {
113
+ fs.copyFileSync(
114
+ errorContext,
115
+ path.join(sourceDir, "error-context.md"));
116
+ }
117
+
118
+
110
119
  await Promise.all([...imagePromises, ...sourcePromises]);
111
120
  }
112
121
 
113
122
  export async function zipResources(outputZipPath: string, screenshotsDir: string, sourceDir: string) {
114
123
  return new Promise<void>((resolve, reject) => {
115
124
  const output = fs.createWriteStream(outputZipPath);
116
- const archive = archiver("zip", { zlib: { level: 9 } });
125
+ const archive = archiver("zip", {zlib: {level: 9}});
117
126
 
118
127
  output.on("close", resolve);
119
128
  archive.on("error", reject);
@@ -133,7 +142,7 @@ export async function zipResources(outputZipPath: string, screenshotsDir: string
133
142
  }
134
143
 
135
144
  export async function setHookActions(traceRawResult: string[]): Promise<TraceModel> {
136
- const hookModel: TraceModel = {actions: [], stdio: []};
145
+ const hookModel: TraceModel = {actions: [], stdio: [], errors: []};
137
146
  const hookActions: Record<string, HookAction> = {};
138
147
 
139
148
  for (const [index, row] of traceRawResult.entries()) {
@@ -154,7 +163,7 @@ export async function setHookActions(traceRawResult: string[]): Promise<TraceMod
154
163
  testTimeout: entry.testTimeout,
155
164
  });
156
165
  continue;
157
- } else if (entry.type === "stdout") {
166
+ } else if (entry.type === "stdout" || entry.type === "stderr") {
158
167
  hookModel?.stdio?.push(entry)
159
168
  } else if (entry.type === "before") {
160
169
  const action: HookAction = {
@@ -176,11 +185,17 @@ export async function setHookActions(traceRawResult: string[]): Promise<TraceMod
176
185
  Object.assign(hookActions[entry.callId], {
177
186
  endTime: entry.endTime,
178
187
  annotations: entry.annotations,
188
+ error: entry.error,
179
189
  });
190
+ } else if (entry.type == "error") {
191
+ hookModel.errors?.push(entry);
180
192
  }
181
193
 
182
194
  if (index === (traceRawResult.length - 1) && entry.type === "after") {
183
195
  hookModel.endTime = entry.endTime;
196
+ if (hookModel.endTime != null && hookModel.startTime) {
197
+ hookModel.duration = Number((hookModel.endTime - hookModel.startTime).toFixed(3));
198
+ }
184
199
  }
185
200
  }
186
201
 
@@ -208,6 +223,8 @@ export async function setActions(traceRawResult: string[], traceModel: TraceMode
208
223
  traceModel.contextId = entry.contextId;
209
224
  } else if (entry.type == "event" || entry.type == "console") {
210
225
  traceModel.events?.push(entry);
226
+ } else if (entry.type === "stdout" || entry.type === "stderr") {
227
+ traceModel?.stdio?.push(entry)
211
228
  } else if (entry.type == "screencast-frame") {
212
229
  let page = traceModel.pages?.find(
213
230
  p => p.pageId === entry.pageId
@@ -265,6 +282,9 @@ export async function setActions(traceRawResult: string[], traceModel: TraceMode
265
282
  }
266
283
 
267
284
  traceModel.endTime = action?.endTime
285
+ if (traceModel.endTime != null && traceModel.startTime) {
286
+ traceModel.duration = Number((traceModel.endTime - traceModel.startTime).toFixed(3));
287
+ }
268
288
  await extractResources(tracePath, targetImages)
269
289
  }
270
290
 
@@ -309,7 +329,8 @@ export async function prepareTraceModel(tracePath: string, logLevel: LogLevel |
309
329
  events: [],
310
330
  resources: [],
311
331
  errors: [],
312
- pages: []
332
+ pages: [],
333
+ stdio: []
313
334
  };
314
335
 
315
336
  if (logLevel == LogLevel.DEBUG) {
@@ -3,6 +3,7 @@ export interface TraceModel {
3
3
  browserName?: string;
4
4
  contextId?: string;
5
5
  endTime?: number;
6
+ duration?: number;
6
7
  events?: Event[];
7
8
  hasSource?: boolean;
8
9
  options?: BrowserContextOptions;
@@ -20,7 +21,7 @@ export interface TraceModel {
20
21
  // this is for hook test model
21
22
  testTimeout?: number
22
23
 
23
- errors?: [];
24
+ errors?: Record<string, any>[];
24
25
  }
25
26
 
26
27
  export interface Resource {