@apica-io/asm-playwright-runner 1.0.0-dev.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.
- package/asm-playwright-runner.iml +8 -0
- package/dist/actions.js +47 -0
- package/dist/cli/index.js +97 -0
- package/dist/lib/helper.js +109 -0
- package/dist/lib/parser.js +309 -0
- package/dist/loader.js +5 -0
- package/dist/model/result.js +1 -0
- package/dist/model/runnerConfig.js +27 -0
- package/dist/model/traceModel.js +2 -0
- package/dist/runner.js +280 -0
- package/package.json +47 -0
- package/samples/betsson.spec.ts +86 -0
- package/samples/example.json +10 -0
- package/samples/google.json +6 -0
- package/samples/playwright-multi-script.spec.ts +60 -0
- package/samples/playwright-script.spec.ts +9 -0
- package/samples/playwright-test-script.spec.ts +18 -0
- package/samples/r.json +16 -0
- package/src/actions.ts +42 -0
- package/src/cli/index.ts +74 -0
- package/src/lib/helper.ts +81 -0
- package/src/lib/parser.ts +341 -0
- package/src/model/runnerConfig.ts +41 -0
- package/src/model/traceModel.ts +150 -0
- package/src/runner.ts +272 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import unzipper from 'unzipper';
|
|
2
|
+
import archiver from "archiver";
|
|
3
|
+
import {Action, HookAction, StackFrame, TraceModel} from "../model/traceModel";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import {LogLevel, ResultDir} from "../model/runnerConfig";
|
|
7
|
+
|
|
8
|
+
export async function getJsonFileData(tracePath: string, fileName: string): Promise<Record<string, any>> {
|
|
9
|
+
const directory = await unzipper.Open.file(tracePath);
|
|
10
|
+
|
|
11
|
+
const file = directory.files.find(
|
|
12
|
+
f => f.path.endsWith(fileName)
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
if (!file) {
|
|
16
|
+
return {}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const content = await file.buffer();
|
|
20
|
+
return JSON.parse(content.toString("utf-8"));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function getFileData(tracePath: string, fileName: string): Promise<string[]> {
|
|
24
|
+
const directory = await unzipper.Open.file(tracePath);
|
|
25
|
+
|
|
26
|
+
const traceFile = directory.files.find(f => f.path.endsWith(fileName));
|
|
27
|
+
if (!traceFile) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const content = await traceFile.buffer();
|
|
32
|
+
return content.toString('utf-8').split('\n').filter(Boolean);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function extractResources(
|
|
36
|
+
zipPath: string,
|
|
37
|
+
targetImages: string[] = []
|
|
38
|
+
) {
|
|
39
|
+
const baseDir = path.dirname(zipPath);
|
|
40
|
+
const runName = path.basename(baseDir);
|
|
41
|
+
const resultDir = path.dirname(baseDir);
|
|
42
|
+
|
|
43
|
+
const parentDir = resultDir === "." ? runName : resultDir;
|
|
44
|
+
const appendRunName = resultDir === "." ? [] : [runName];
|
|
45
|
+
|
|
46
|
+
const screenshotsDir = path.join(
|
|
47
|
+
parentDir, ResultDir.SCREENSHOT, ...appendRunName
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const sourceDir = path.join(
|
|
51
|
+
parentDir, ResultDir.SOURCE, ...appendRunName
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
// Create folders if not exists
|
|
55
|
+
[screenshotsDir, sourceDir].forEach(dir => {
|
|
56
|
+
if (!fs.existsSync(dir)) {
|
|
57
|
+
fs.mkdirSync(dir, {recursive: true});
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const directory = await unzipper.Open.file(zipPath);
|
|
62
|
+
|
|
63
|
+
// Copy target images
|
|
64
|
+
const imagePromises = targetImages.map(targetImage => {
|
|
65
|
+
const fileEntry = directory.files.find(
|
|
66
|
+
(file: { path: string; }) => file.path === `resources/${targetImage}`
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
if (!fileEntry) {
|
|
70
|
+
return Promise.resolve();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const outputPath = path.join(
|
|
74
|
+
screenshotsDir, targetImage
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
fileEntry
|
|
79
|
+
.stream()
|
|
80
|
+
.pipe(fs.createWriteStream(outputPath))
|
|
81
|
+
.on('finish', () => {
|
|
82
|
+
resolve(true);
|
|
83
|
+
})
|
|
84
|
+
.on('error', reject);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Copy all src@*.txt files
|
|
89
|
+
const sourcePromises = directory.files
|
|
90
|
+
.filter(
|
|
91
|
+
file =>
|
|
92
|
+
file.path.startsWith('resources/') &&
|
|
93
|
+
/^src@.*\.txt$/.test(path.basename(file.path))
|
|
94
|
+
)
|
|
95
|
+
.map(fileEntry => {
|
|
96
|
+
const fileName = path.basename(fileEntry.path);
|
|
97
|
+
const outputPath = path.join(sourceDir, fileName);
|
|
98
|
+
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
fileEntry
|
|
101
|
+
.stream()
|
|
102
|
+
.pipe(fs.createWriteStream(outputPath))
|
|
103
|
+
.on('finish', () => {
|
|
104
|
+
resolve(true);
|
|
105
|
+
})
|
|
106
|
+
.on('error', reject);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
await Promise.all([...imagePromises, ...sourcePromises]);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export async function zipResources(outputZipPath: string, screenshotsDir: string, sourceDir: string) {
|
|
114
|
+
return new Promise<void>((resolve, reject) => {
|
|
115
|
+
const output = fs.createWriteStream(outputZipPath);
|
|
116
|
+
const archive = archiver("zip", { zlib: { level: 9 } });
|
|
117
|
+
|
|
118
|
+
output.on("close", resolve);
|
|
119
|
+
archive.on("error", reject);
|
|
120
|
+
|
|
121
|
+
archive.pipe(output);
|
|
122
|
+
|
|
123
|
+
if (fs.existsSync(screenshotsDir)) {
|
|
124
|
+
archive.directory(screenshotsDir, ResultDir.SCREENSHOT);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (fs.existsSync(sourceDir)) {
|
|
128
|
+
archive.directory(sourceDir, ResultDir.SOURCE);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
archive.finalize();
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export async function setHookActions(traceRawResult: string[]): Promise<TraceModel> {
|
|
136
|
+
const hookModel: TraceModel = {actions: [], stdio: []};
|
|
137
|
+
const hookActions: Record<string, HookAction> = {};
|
|
138
|
+
|
|
139
|
+
for (const [index, row] of traceRawResult.entries()) {
|
|
140
|
+
const entry = JSON.parse(row);
|
|
141
|
+
|
|
142
|
+
if (entry.type === "context-options") {
|
|
143
|
+
Object.assign(hookModel, {
|
|
144
|
+
origin: entry.origin,
|
|
145
|
+
browserName: entry.browserName,
|
|
146
|
+
playwrightVersion: entry.playwrightVersion,
|
|
147
|
+
options: entry.options,
|
|
148
|
+
platform: entry.platform,
|
|
149
|
+
wallTime: entry.wallTime,
|
|
150
|
+
startTime: entry.monotonicTime,
|
|
151
|
+
sdkLanguage: entry.sdkLanguage,
|
|
152
|
+
testIdAttributeName: entry.testIdAttributeName,
|
|
153
|
+
contextId: entry.contextId,
|
|
154
|
+
testTimeout: entry.testTimeout,
|
|
155
|
+
});
|
|
156
|
+
continue;
|
|
157
|
+
} else if (entry.type === "stdout") {
|
|
158
|
+
hookModel?.stdio?.push(entry)
|
|
159
|
+
} else if (entry.type === "before") {
|
|
160
|
+
const action: HookAction = {
|
|
161
|
+
type: "action",
|
|
162
|
+
callId: entry.callId,
|
|
163
|
+
stepId: entry.stepId,
|
|
164
|
+
parentId: entry.parentId,
|
|
165
|
+
startTime: entry.startTime,
|
|
166
|
+
class: entry.class,
|
|
167
|
+
method: entry.method,
|
|
168
|
+
title: entry.title,
|
|
169
|
+
params: entry.params,
|
|
170
|
+
stack: entry.stack,
|
|
171
|
+
log: [],
|
|
172
|
+
};
|
|
173
|
+
hookActions[entry.callId] = action;
|
|
174
|
+
hookModel.actions!.push(action);
|
|
175
|
+
} else if (entry.type === "after" && hookActions[entry.callId]) {
|
|
176
|
+
Object.assign(hookActions[entry.callId], {
|
|
177
|
+
endTime: entry.endTime,
|
|
178
|
+
annotations: entry.annotations,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (index === (traceRawResult.length - 1) && entry.type === "after") {
|
|
183
|
+
hookModel.endTime = entry.endTime;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return hookModel;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
export async function setActions(traceRawResult: string[], traceModel: TraceModel, tracePath: string, stackData: Record<string, any>) {
|
|
192
|
+
let beforeFlag = false
|
|
193
|
+
let action: Action | null = null;
|
|
194
|
+
let targetImages: string[] = [];
|
|
195
|
+
|
|
196
|
+
for (const row of traceRawResult) {
|
|
197
|
+
const entry = JSON.parse(row);
|
|
198
|
+
if (entry.type === 'context-options') {
|
|
199
|
+
traceModel.origin = entry.origin;
|
|
200
|
+
traceModel.browserName = entry.browserName;
|
|
201
|
+
traceModel.playwrightVersion = entry.playwrightVersion;
|
|
202
|
+
traceModel.options = entry.options;
|
|
203
|
+
traceModel.platform = entry.platform;
|
|
204
|
+
traceModel.wallTime = entry.wallTime;
|
|
205
|
+
traceModel.startTime = entry.monotonicTime;
|
|
206
|
+
traceModel.sdkLanguage = entry.sdkLanguage;
|
|
207
|
+
traceModel.testIdAttributeName = entry.testIdAttributeName;
|
|
208
|
+
traceModel.contextId = entry.contextId;
|
|
209
|
+
} else if (entry.type == "event" || entry.type == "console") {
|
|
210
|
+
traceModel.events?.push(entry);
|
|
211
|
+
} else if (entry.type == "screencast-frame") {
|
|
212
|
+
let page = traceModel.pages?.find(
|
|
213
|
+
p => p.pageId === entry.pageId
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
if (!page) {
|
|
217
|
+
page = {
|
|
218
|
+
pageId: entry.pageId,
|
|
219
|
+
screencastFrames: [],
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
traceModel.pages?.push(page);
|
|
223
|
+
}
|
|
224
|
+
targetImages.push(entry.sha1);
|
|
225
|
+
page.screencastFrames.push(entry);
|
|
226
|
+
} else {
|
|
227
|
+
if (entry.type == "before") {
|
|
228
|
+
action = {
|
|
229
|
+
callId: entry.callId,
|
|
230
|
+
class: entry.class,
|
|
231
|
+
method: entry.method,
|
|
232
|
+
startTime: entry.startTime,
|
|
233
|
+
type: "action",
|
|
234
|
+
params: entry.params,
|
|
235
|
+
pageId: entry.pageId,
|
|
236
|
+
log: [],
|
|
237
|
+
stack: stackData[entry.callId]
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (entry.class == "Frame") {
|
|
241
|
+
action.beforeSnapshot = entry.beforeSnapshot
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
beforeFlag = true
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (beforeFlag && action != null && action.callId == entry.callId) {
|
|
248
|
+
if (entry.type == "log") {
|
|
249
|
+
action.log?.push({
|
|
250
|
+
time: entry.time,
|
|
251
|
+
message: entry.message
|
|
252
|
+
})
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (entry.type == "after") {
|
|
256
|
+
beforeFlag = false
|
|
257
|
+
action.endTime = entry.endTime;
|
|
258
|
+
action.result = entry.result;
|
|
259
|
+
action.error = entry.error;
|
|
260
|
+
action.afterSnapshot = entry.afterSnapshot
|
|
261
|
+
traceModel.actions?.push(action);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
traceModel.endTime = action?.endTime
|
|
268
|
+
await extractResources(tracePath, targetImages)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export async function setResources(resourceRawResult: string[], traceModel: TraceModel) {
|
|
272
|
+
for (const row of resourceRawResult) {
|
|
273
|
+
const entry = JSON.parse(row);
|
|
274
|
+
traceModel.resources?.push(entry.snapshot);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
interface PreparedStackData {
|
|
279
|
+
[key: string]: StackFrame[];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export async function prepareStackData(stacksRawResult: Record<string, any>): Promise<PreparedStackData> {
|
|
283
|
+
const preparedData: PreparedStackData = {};
|
|
284
|
+
const files: string[] = stacksRawResult.files || [];
|
|
285
|
+
const stacks = stacksRawResult.stacks || [];
|
|
286
|
+
|
|
287
|
+
for (const stack of stacks) {
|
|
288
|
+
const [callId, frames] = stack;
|
|
289
|
+
preparedData[`call@${callId}`] = frames.map(
|
|
290
|
+
([fileIndex, line, column, fn]: [number, number, number, string]) => ({
|
|
291
|
+
file: files[fileIndex] || `source-file-${fileIndex}`,
|
|
292
|
+
fileIndex: `source-file-${fileIndex}`,
|
|
293
|
+
line,
|
|
294
|
+
column,
|
|
295
|
+
functionName: fn || ""
|
|
296
|
+
})
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return preparedData;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export async function prepareTraceModel(tracePath: string, logLevel: LogLevel | undefined): Promise<TraceModel[]> {
|
|
304
|
+
const traceRawResult = await getFileData(tracePath, "trace.trace");
|
|
305
|
+
const resourceRawResult = await getFileData(tracePath, "trace.network");
|
|
306
|
+
const stacksRawResult = await getJsonFileData(tracePath, "trace.stacks")
|
|
307
|
+
const traceModel: TraceModel = {
|
|
308
|
+
actions: [],
|
|
309
|
+
events: [],
|
|
310
|
+
resources: [],
|
|
311
|
+
errors: [],
|
|
312
|
+
pages: []
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
if (logLevel == LogLevel.DEBUG) {
|
|
316
|
+
fs.writeFileSync(
|
|
317
|
+
path.join(path.dirname(tracePath), "trace-raw-data.json"),
|
|
318
|
+
JSON.stringify(traceRawResult, null, 2), "utf-8"
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const stackData = await prepareStackData(stacksRawResult);
|
|
323
|
+
await setActions(traceRawResult, traceModel, tracePath, stackData);
|
|
324
|
+
await setResources(resourceRawResult, traceModel);
|
|
325
|
+
|
|
326
|
+
const testHookResult = await getFileData(tracePath, "test.trace");
|
|
327
|
+
if (testHookResult && testHookResult.length > 0) {
|
|
328
|
+
if (logLevel == LogLevel.DEBUG) {
|
|
329
|
+
//raw data to validate data from trace
|
|
330
|
+
fs.writeFileSync(
|
|
331
|
+
path.join(path.dirname(tracePath), "test-trace-raw-data.json"),
|
|
332
|
+
JSON.stringify(testHookResult, null, 2), "utf-8"
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const hookModel = await setHookActions(testHookResult)
|
|
337
|
+
return [hookModel, traceModel]
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return [traceModel];
|
|
341
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface RunnerConfig {
|
|
2
|
+
browser: BrowserType;
|
|
3
|
+
chromiumPath?: string;
|
|
4
|
+
headless: boolean;
|
|
5
|
+
verbose: boolean;
|
|
6
|
+
resultDir: string;
|
|
7
|
+
logLevel: LogLevel;
|
|
8
|
+
trace?: string;
|
|
9
|
+
returnResult: boolean
|
|
10
|
+
sslClientCert?: string;
|
|
11
|
+
sslClientKey?: string;
|
|
12
|
+
sslClientPassphrase?: string;
|
|
13
|
+
isValidScript?: boolean;
|
|
14
|
+
scriptType?: ScriptType;
|
|
15
|
+
extraHTTPHeaders?: string;
|
|
16
|
+
timeout?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export enum BrowserType {
|
|
20
|
+
CHROMIUM = "chromium",
|
|
21
|
+
FIREFOX = "firefox",
|
|
22
|
+
WEBKIT = "webkit"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export enum LogLevel {
|
|
26
|
+
INFO = "info",
|
|
27
|
+
DEBUG = "debug",
|
|
28
|
+
ERROR = "error"
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export enum ScriptType {
|
|
32
|
+
JSON = "json",
|
|
33
|
+
PLAYWRIGHT = "playwright",
|
|
34
|
+
PLAYWRIGHT_TEST = "playwright/test"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export enum ResultDir {
|
|
38
|
+
BASE_DIR = "result",
|
|
39
|
+
SCREENSHOT = "screenshots",
|
|
40
|
+
SOURCE = "source"
|
|
41
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
export interface TraceModel {
|
|
2
|
+
actions?: Action[];
|
|
3
|
+
browserName?: string;
|
|
4
|
+
contextId?: string;
|
|
5
|
+
endTime?: number;
|
|
6
|
+
events?: Event[];
|
|
7
|
+
hasSource?: boolean;
|
|
8
|
+
options?: BrowserContextOptions;
|
|
9
|
+
origin?: string;
|
|
10
|
+
pages?: Page[];
|
|
11
|
+
platform?: string;
|
|
12
|
+
playwrightVersion?: string;
|
|
13
|
+
resources?: Resource[];
|
|
14
|
+
sdkLanguage?: string;
|
|
15
|
+
startTime?: number;
|
|
16
|
+
testIdAttributeName?: string;
|
|
17
|
+
wallTime?: number;
|
|
18
|
+
stdio?: Record<string, any>[];
|
|
19
|
+
|
|
20
|
+
// this is for hook test model
|
|
21
|
+
testTimeout?: number
|
|
22
|
+
|
|
23
|
+
errors?: [];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface Resource {
|
|
27
|
+
cache: Record<string, any>;
|
|
28
|
+
pageref: string;
|
|
29
|
+
request: Request;
|
|
30
|
+
response: Response;
|
|
31
|
+
serverIPAddress: string;
|
|
32
|
+
startedDateTime: string;
|
|
33
|
+
time: number;
|
|
34
|
+
timings: Timing;
|
|
35
|
+
_frameref: string;
|
|
36
|
+
_monotonicTime: number;
|
|
37
|
+
_securityDetails: Record<string, any>;
|
|
38
|
+
_serverPort: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface Timing {
|
|
42
|
+
connect: number;
|
|
43
|
+
dns: number;
|
|
44
|
+
receive: number;
|
|
45
|
+
send: number;
|
|
46
|
+
ssl: number;
|
|
47
|
+
wait: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface Response {
|
|
51
|
+
bodySize: number;
|
|
52
|
+
content: Record<string, any>;
|
|
53
|
+
cookies: string[];
|
|
54
|
+
headers: Record<string, any>;
|
|
55
|
+
headersSize: number;
|
|
56
|
+
httpVersion: string;
|
|
57
|
+
redirectURL: string;
|
|
58
|
+
status: number;
|
|
59
|
+
statusText: string;
|
|
60
|
+
_transferSize: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface Request {
|
|
64
|
+
bodySize: number;
|
|
65
|
+
cookies: string[];
|
|
66
|
+
headers: Record<string, any>;
|
|
67
|
+
headersSize: number;
|
|
68
|
+
httpVersion: string;
|
|
69
|
+
method: string;
|
|
70
|
+
queryString: string[];
|
|
71
|
+
url: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface Page {
|
|
75
|
+
pageId: string;
|
|
76
|
+
screencastFrames: ScreencastFrame[]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface ScreencastFrame {
|
|
80
|
+
frameSwapWallTime: number;
|
|
81
|
+
height: number;
|
|
82
|
+
pageId: string;
|
|
83
|
+
sha1: string;
|
|
84
|
+
timestamp: number;
|
|
85
|
+
type: string;
|
|
86
|
+
width: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface Event {
|
|
90
|
+
class: string;
|
|
91
|
+
method: string;
|
|
92
|
+
params: Record<string, any>;
|
|
93
|
+
time: number;
|
|
94
|
+
type: 'event';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export type TraceEventType =
|
|
98
|
+
| 'context-options'
|
|
99
|
+
| 'before'
|
|
100
|
+
| 'after'
|
|
101
|
+
| 'event';
|
|
102
|
+
|
|
103
|
+
export interface BrowserContextOptions {
|
|
104
|
+
noDefaultViewport?: boolean;
|
|
105
|
+
ignoreHTTPSErrors?: boolean;
|
|
106
|
+
selectorEngines?: any[];
|
|
107
|
+
acceptDownloads?: string;
|
|
108
|
+
viewport?: Viewport;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface HookAction extends Action{
|
|
112
|
+
stepId?: string;
|
|
113
|
+
annotations?: [];
|
|
114
|
+
title?: string;
|
|
115
|
+
parentId?: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface Action {
|
|
119
|
+
type: 'action';
|
|
120
|
+
callId: string;
|
|
121
|
+
startTime: number;
|
|
122
|
+
endTime?: number;
|
|
123
|
+
class: string;
|
|
124
|
+
method: string;
|
|
125
|
+
params?: Record<string, any>;
|
|
126
|
+
pageId?: string;
|
|
127
|
+
beforeSnapshot?: string;
|
|
128
|
+
afterSnapshot?: string;
|
|
129
|
+
log?: ActionLog[];
|
|
130
|
+
result?: Record<string, any>;
|
|
131
|
+
stack?: StackFrame[];
|
|
132
|
+
error?: Record<string, any>;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface ActionLog {
|
|
136
|
+
time: number;
|
|
137
|
+
message: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface StackFrame {
|
|
141
|
+
file: string;
|
|
142
|
+
line: number;
|
|
143
|
+
column: number;
|
|
144
|
+
function: string;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface Viewport {
|
|
148
|
+
width: number;
|
|
149
|
+
height: number;
|
|
150
|
+
}
|