@haibun/web-playwright 1.59.0 → 1.60.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.
- package/build/cycles.d.ts +4 -0
- package/build/cycles.d.ts.map +1 -0
- package/build/cycles.js +82 -0
- package/build/cycles.js.map +1 -0
- package/build/interactionSteps.d.ts +221 -0
- package/build/interactionSteps.d.ts.map +1 -0
- package/build/interactionSteps.js +515 -0
- package/build/interactionSteps.js.map +1 -0
- package/build/monitor/LogEntry.d.ts +4 -0
- package/build/monitor/LogEntry.d.ts.map +1 -0
- package/build/monitor/LogEntry.js +4 -0
- package/build/monitor/LogEntry.js.map +1 -0
- package/build/monitor/MonitorHandler.d.ts +9 -0
- package/build/monitor/MonitorHandler.d.ts.map +1 -1
- package/build/monitor/MonitorHandler.js +61 -47
- package/build/monitor/MonitorHandler.js.map +1 -1
- package/build/monitor/artifactDisplayBase.d.ts +2 -0
- package/build/monitor/artifactDisplayBase.d.ts.map +1 -0
- package/build/monitor/artifactDisplayBase.js +2 -0
- package/build/monitor/artifactDisplayBase.js.map +1 -0
- package/build/monitor/artifactDisplays/HtmlArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/HtmlArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/HtmlArtifactDisplay.js +31 -0
- package/build/monitor/artifactDisplays/HtmlArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/ImageArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/ImageArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/ImageArtifactDisplay.js +17 -0
- package/build/monitor/artifactDisplays/ImageArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/JsonArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/JsonArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/JsonArtifactDisplay.js +18 -0
- package/build/monitor/artifactDisplays/JsonArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/JsonArtifactHTTPTrace.d.ts +13 -0
- package/build/monitor/artifactDisplays/JsonArtifactHTTPTrace.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/JsonArtifactHTTPTrace.js +44 -0
- package/build/monitor/artifactDisplays/JsonArtifactHTTPTrace.js.map +1 -0
- package/build/monitor/artifactDisplays/MermaidDiagram.d.ts +22 -0
- package/build/monitor/artifactDisplays/MermaidDiagram.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/MermaidDiagram.js +199 -0
- package/build/monitor/artifactDisplays/MermaidDiagram.js.map +1 -0
- package/build/monitor/artifactDisplays/ResolvedFeaturesArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/ResolvedFeaturesArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/ResolvedFeaturesArtifactDisplay.js +38 -0
- package/build/monitor/artifactDisplays/ResolvedFeaturesArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/SequenceDiagramGenerator.d.ts +32 -0
- package/build/monitor/artifactDisplays/SequenceDiagramGenerator.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/SequenceDiagramGenerator.js +258 -0
- package/build/monitor/artifactDisplays/SequenceDiagramGenerator.js.map +1 -0
- package/build/monitor/artifactDisplays/SpeechArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/SpeechArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/SpeechArtifactDisplay.js +19 -0
- package/build/monitor/artifactDisplays/SpeechArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/VideoArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/VideoArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/VideoArtifactDisplay.js +21 -0
- package/build/monitor/artifactDisplays/VideoArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/VideoStartArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/VideoStartArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/VideoStartArtifactDisplay.js +16 -0
- package/build/monitor/artifactDisplays/VideoStartArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/artifactDisplayBase.d.ts +20 -0
- package/build/monitor/artifactDisplays/artifactDisplayBase.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/artifactDisplayBase.js +40 -0
- package/build/monitor/artifactDisplays/artifactDisplayBase.js.map +1 -0
- package/build/monitor/artifactDisplays/htmlArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/htmlArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/htmlArtifactDisplay.js +31 -0
- package/build/monitor/artifactDisplays/htmlArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/imageArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/imageArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/imageArtifactDisplay.js +17 -0
- package/build/monitor/artifactDisplays/imageArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/jsonArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/jsonArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/jsonArtifactDisplay.js +18 -0
- package/build/monitor/artifactDisplays/jsonArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/jsonArtifactHTTPTrace.d.ts +14 -0
- package/build/monitor/artifactDisplays/jsonArtifactHTTPTrace.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/jsonArtifactHTTPTrace.js +72 -0
- package/build/monitor/artifactDisplays/jsonArtifactHTTPTrace.js.map +1 -0
- package/build/monitor/artifactDisplays/mermaidDiagram.d.ts +22 -0
- package/build/monitor/artifactDisplays/mermaidDiagram.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/mermaidDiagram.js +199 -0
- package/build/monitor/artifactDisplays/mermaidDiagram.js.map +1 -0
- package/build/monitor/artifactDisplays/resolvedFeaturesArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/resolvedFeaturesArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/resolvedFeaturesArtifactDisplay.js +36 -0
- package/build/monitor/artifactDisplays/resolvedFeaturesArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/sequenceDiagramGenerator.d.ts +32 -0
- package/build/monitor/artifactDisplays/sequenceDiagramGenerator.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/sequenceDiagramGenerator.js +299 -0
- package/build/monitor/artifactDisplays/sequenceDiagramGenerator.js.map +1 -0
- package/build/monitor/artifactDisplays/speechArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/speechArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/speechArtifactDisplay.js +38 -0
- package/build/monitor/artifactDisplays/speechArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/videoArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/videoArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/videoArtifactDisplay.js +22 -0
- package/build/monitor/artifactDisplays/videoArtifactDisplay.js.map +1 -0
- package/build/monitor/artifactDisplays/videoStartArtifactDisplay.d.ts +9 -0
- package/build/monitor/artifactDisplays/videoStartArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/artifactDisplays/videoStartArtifactDisplay.js +30 -0
- package/build/monitor/artifactDisplays/videoStartArtifactDisplay.js.map +1 -0
- package/build/monitor/controls.d.ts +0 -1
- package/build/monitor/controls.d.ts.map +1 -1
- package/build/monitor/controls.js +6 -71
- package/build/monitor/controls.js.map +1 -1
- package/build/monitor/graph/feature-bases.d.ts +5 -0
- package/build/monitor/graph/feature-bases.d.ts.map +1 -0
- package/build/monitor/graph/feature-bases.js +36 -0
- package/build/monitor/graph/feature-bases.js.map +1 -0
- package/build/monitor/graph/generateMermaidGraph.d.ts +4 -0
- package/build/monitor/graph/generateMermaidGraph.d.ts.map +1 -0
- package/build/monitor/graph/generateMermaidGraph.js +144 -0
- package/build/monitor/graph/generateMermaidGraph.js.map +1 -0
- package/build/monitor/graph/graphUtils.d.ts +3 -0
- package/build/monitor/graph/graphUtils.d.ts.map +1 -0
- package/build/monitor/graph/graphUtils.js +16 -0
- package/build/monitor/graph/graphUtils.js.map +1 -0
- package/build/monitor/graph/mermaidGraphLinks.d.ts +3 -0
- package/build/monitor/graph/mermaidGraphLinks.d.ts.map +1 -0
- package/build/monitor/graph/mermaidGraphLinks.js +31 -0
- package/build/monitor/graph/mermaidGraphLinks.js.map +1 -0
- package/build/monitor/htmlArtifactDisplay.d.ts +2 -0
- package/build/monitor/htmlArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/htmlArtifactDisplay.js +2 -0
- package/build/monitor/htmlArtifactDisplay.js.map +1 -0
- package/build/monitor/imageArtifactDisplay.d.ts +2 -0
- package/build/monitor/imageArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/imageArtifactDisplay.js +2 -0
- package/build/monitor/imageArtifactDisplay.js.map +1 -0
- package/build/monitor/jsonArtifactDisplay.d.ts +2 -0
- package/build/monitor/jsonArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/jsonArtifactDisplay.js +2 -0
- package/build/monitor/jsonArtifactDisplay.js.map +1 -0
- package/build/monitor/jsonArtifactHTTPTrace.d.ts +2 -0
- package/build/monitor/jsonArtifactHTTPTrace.d.ts.map +1 -0
- package/build/monitor/jsonArtifactHTTPTrace.js +2 -0
- package/build/monitor/jsonArtifactHTTPTrace.js.map +1 -0
- package/build/monitor/messages.d.ts +9 -21
- package/build/monitor/messages.d.ts.map +1 -1
- package/build/monitor/messages.js +83 -216
- package/build/monitor/messages.js.map +1 -1
- package/build/monitor/monitor.d.ts +9 -4
- package/build/monitor/monitor.d.ts.map +1 -1
- package/build/monitor/monitor.js +8 -18
- package/build/monitor/monitor.js.map +1 -1
- package/build/monitor/resolvedFeaturesArtifactDisplay.d.ts +2 -0
- package/build/monitor/resolvedFeaturesArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/resolvedFeaturesArtifactDisplay.js +2 -0
- package/build/monitor/resolvedFeaturesArtifactDisplay.js.map +1 -0
- package/build/monitor/sequenceDiagramGenerator.d.ts +32 -0
- package/build/monitor/sequenceDiagramGenerator.d.ts.map +1 -0
- package/build/monitor/sequenceDiagramGenerator.js +299 -0
- package/build/monitor/sequenceDiagramGenerator.js.map +1 -0
- package/build/monitor/speechArtifactDisplay.d.ts +2 -0
- package/build/monitor/speechArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/speechArtifactDisplay.js +2 -0
- package/build/monitor/speechArtifactDisplay.js.map +1 -0
- package/build/monitor/test-utils.d.ts +9 -0
- package/build/monitor/test-utils.d.ts.map +1 -0
- package/build/monitor/test-utils.js +70 -0
- package/build/monitor/test-utils.js.map +1 -0
- package/build/monitor/videoArtifactDisplay.d.ts +2 -0
- package/build/monitor/videoArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/videoArtifactDisplay.js +2 -0
- package/build/monitor/videoArtifactDisplay.js.map +1 -0
- package/build/monitor/videoStartArtifactDisplay.d.ts +2 -0
- package/build/monitor/videoStartArtifactDisplay.d.ts.map +1 -0
- package/build/monitor/videoStartArtifactDisplay.js +2 -0
- package/build/monitor/videoStartArtifactDisplay.js.map +1 -0
- package/build/web-playwright.d.ts +78 -77
- package/build/web-playwright.d.ts.map +1 -1
- package/build/web-playwright.js +12 -571
- package/build/web-playwright.js.map +1 -1
- package/package.json +9 -5
- package/build/monitor/monitorHandler.d.ts +0 -16
- package/build/monitor/monitorHandler.d.ts.map +0 -1
- package/build/monitor/monitorHandler.js +0 -108
- package/build/monitor/monitorHandler.js.map +0 -1
- package/build/monitor/vite.config.d.ts +0 -4
- package/build/monitor/vite.config.d.ts.map +0 -1
- package/build/monitor/vite.config.js +0 -91
- package/build/monitor/vite.config.js.map +0 -1
- package/web/monitor.html +0 -3059
package/build/web-playwright.js
CHANGED
|
@@ -3,78 +3,27 @@ import { pathToFileURL } from 'url';
|
|
|
3
3
|
import { OK } from '@haibun/core/build/lib/defs.js';
|
|
4
4
|
import { WEB_PAGE, WEB_CONTROL } from '@haibun/core/build/lib/domain-types.js';
|
|
5
5
|
import { BrowserFactory, BROWSERS } from './BrowserFactory.js';
|
|
6
|
-
import { actionNotOK, getStepperOption, boolOrError, intOrError, stringOrError, findStepperFromOption,
|
|
6
|
+
import { actionNotOK, getStepperOption, boolOrError, intOrError, stringOrError, findStepperFromOption, optionOrError } from '@haibun/core/build/lib/util/index.js';
|
|
7
7
|
import { EExecutionMessageType } from '@haibun/core/build/lib/interfaces/logger.js';
|
|
8
8
|
import { EMediaTypes } from '@haibun/domain-storage/build/media-types.js';
|
|
9
|
-
import { restSteps } from './rest-playwright.js';
|
|
10
9
|
import { MonitorHandler } from './monitor/MonitorHandler.js';
|
|
11
|
-
import { rmSync } from 'fs';
|
|
12
10
|
import { AStepper } from '@haibun/core/build/lib/astepper.js';
|
|
11
|
+
import { cycles } from './cycles.js';
|
|
12
|
+
import { interactionSteps } from './interactionSteps.js';
|
|
13
|
+
import { restSteps } from './rest-playwright.js';
|
|
14
|
+
/**
|
|
15
|
+
* This is the infrastructure for web-playwright.
|
|
16
|
+
*
|
|
17
|
+
* @see {@link interactionSteps} for interaction steps
|
|
18
|
+
* @see {@link restSteps} for rest steps
|
|
19
|
+
*/
|
|
13
20
|
export const LAST_REST_RESPONSE = 'LAST_REST_RESPONSE';
|
|
14
21
|
export var EMonitoringTypes;
|
|
15
22
|
(function (EMonitoringTypes) {
|
|
16
23
|
EMonitoringTypes["MONITOR_ALL"] = "all";
|
|
17
24
|
EMonitoringTypes["MONITOR_EACH"] = "each";
|
|
18
25
|
})(EMonitoringTypes || (EMonitoringTypes = {}));
|
|
19
|
-
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
21
|
-
async onFailure(result, step) {
|
|
22
|
-
if (wp.bf?.hasPage(wp.getWorld().tag, wp.tab)) {
|
|
23
|
-
await wp.captureFailureScreenshot(EExecutionMessageType.ON_FAILURE, step);
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
async startFeature() {
|
|
27
|
-
if (wp.monitor === EMonitoringTypes.MONITOR_EACH) {
|
|
28
|
-
await wp.createMonitor();
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
async endFeature({ shouldClose = true }) {
|
|
32
|
-
// leave web server running if there was a failure and it's the last feature
|
|
33
|
-
if (shouldClose) {
|
|
34
|
-
for (const file of wp.downloaded) {
|
|
35
|
-
wp.getWorld().logger.debug(`removing ${JSON.stringify(file)}`);
|
|
36
|
-
rmSync(file);
|
|
37
|
-
wp.downloaded = [];
|
|
38
|
-
}
|
|
39
|
-
if (wp.hasFactory) {
|
|
40
|
-
if (wp.captureVideo) {
|
|
41
|
-
const page = await wp.getPage();
|
|
42
|
-
const path = await wp.storage.getRelativePath(await page.video().path());
|
|
43
|
-
const artifact = { artifactType: 'video', path };
|
|
44
|
-
const context = {
|
|
45
|
-
incident: EExecutionMessageType.FEATURE_END,
|
|
46
|
-
artifact,
|
|
47
|
-
tag: wp.getWorld().tag
|
|
48
|
-
};
|
|
49
|
-
wp.getWorld().logger.log('feature video', context);
|
|
50
|
-
}
|
|
51
|
-
// close the context, which closes any pages
|
|
52
|
-
if (wp.hasFactory) {
|
|
53
|
-
await wp.bf?.closeContext(wp.getWorld().tag);
|
|
54
|
-
}
|
|
55
|
-
await wp.bf?.close();
|
|
56
|
-
wp.bf = undefined;
|
|
57
|
-
wp.hasFactory = false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (wp.monitor === EMonitoringTypes.MONITOR_EACH) {
|
|
61
|
-
await wp.callClosers();
|
|
62
|
-
await WebPlaywright.monitorHandler.writeMonitor();
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
async startExecution() {
|
|
66
|
-
if (wp.monitor === EMonitoringTypes.MONITOR_ALL) {
|
|
67
|
-
await wp.createMonitor();
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
async endExecution() {
|
|
71
|
-
if (wp.monitor === EMonitoringTypes.MONITOR_ALL) {
|
|
72
|
-
await wp.callClosers();
|
|
73
|
-
await WebPlaywright.monitorHandler.writeMonitor();
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
class WebPlaywright extends AStepper {
|
|
26
|
+
export class WebPlaywright extends AStepper {
|
|
78
27
|
cycles = cycles(this);
|
|
79
28
|
static STORAGE = 'STORAGE';
|
|
80
29
|
static PERSISTENT_DIRECTORY = 'PERSISTENT_DIRECTORY';
|
|
@@ -124,13 +73,10 @@ class WebPlaywright extends AStepper {
|
|
|
124
73
|
downloaded = [];
|
|
125
74
|
captureVideo;
|
|
126
75
|
closers = [];
|
|
127
|
-
logElementError;
|
|
128
76
|
monitor;
|
|
129
77
|
static monitorHandler;
|
|
130
|
-
userAgentPages = {};
|
|
131
78
|
apiUserAgent;
|
|
132
79
|
extraHTTPHeaders = {};
|
|
133
|
-
BROWSER_STATE_PATH = undefined;
|
|
134
80
|
expectedDownload;
|
|
135
81
|
headless;
|
|
136
82
|
async setWorld(world, steppers) {
|
|
@@ -216,512 +162,7 @@ class WebPlaywright extends AStepper {
|
|
|
216
162
|
}
|
|
217
163
|
steps = {
|
|
218
164
|
...restSteps(this),
|
|
219
|
-
|
|
220
|
-
gwta: `open devtools`,
|
|
221
|
-
action: async () => {
|
|
222
|
-
await this.withPage(async (page) => {
|
|
223
|
-
await page.goto('about:blank');
|
|
224
|
-
await sleep(2000);
|
|
225
|
-
const targetId = await fetch('http://localhost:9223/json/list');
|
|
226
|
-
await page.goto(`devtools://devtools/bundled/inspector.html?ws=localhost:9223/devtools/page/${targetId}&panel=network`);
|
|
227
|
-
});
|
|
228
|
-
return OK;
|
|
229
|
-
},
|
|
230
|
-
},
|
|
231
|
-
// INPUT
|
|
232
|
-
press: {
|
|
233
|
-
gwta: `press {key}`,
|
|
234
|
-
action: async ({ key }) => {
|
|
235
|
-
await this.withPage(async (page) => await page.keyboard.press(key));
|
|
236
|
-
return OK;
|
|
237
|
-
},
|
|
238
|
-
},
|
|
239
|
-
type: {
|
|
240
|
-
gwta: `type {text}`,
|
|
241
|
-
action: async ({ text }) => {
|
|
242
|
-
await this.withPage(async (page) => await page.keyboard.type(text));
|
|
243
|
-
return OK;
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
inputVariable: {
|
|
247
|
-
gwta: `input {what} for {field}`,
|
|
248
|
-
action: async ({ what, field }) => {
|
|
249
|
-
await this.withPage(async (page) => await page.locator(field).fill(what));
|
|
250
|
-
return OK;
|
|
251
|
-
},
|
|
252
|
-
},
|
|
253
|
-
selectionOption: {
|
|
254
|
-
gwta: `select {option} for {field: ${WEB_CONTROL}}`,
|
|
255
|
-
action: async ({ option, field }) => {
|
|
256
|
-
await this.withPage(async (page) => await page.selectOption(field, { label: option }));
|
|
257
|
-
// FIXME have to use id value
|
|
258
|
-
return OK;
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
// ASSERTIONS
|
|
262
|
-
dialogIs: {
|
|
263
|
-
gwta: 'dialog {what} {type} says {value}',
|
|
264
|
-
action: async ({ what, type, value }) => {
|
|
265
|
-
const cur = this.getWorld().shared.get(what)?.[type];
|
|
266
|
-
return Promise.resolve(cur === value ? OK : actionNotOK(`${what} is ${cur}`));
|
|
267
|
-
},
|
|
268
|
-
},
|
|
269
|
-
dialogIsUnset: {
|
|
270
|
-
gwta: 'dialog {what} {type} not set',
|
|
271
|
-
action: async ({ what, type }) => {
|
|
272
|
-
const cur = this.getWorld().shared.get(what)?.[type];
|
|
273
|
-
return Promise.resolve(!cur ? OK : actionNotOK(`${what} is ${cur}`));
|
|
274
|
-
},
|
|
275
|
-
},
|
|
276
|
-
seeTestId: {
|
|
277
|
-
gwta: 'has test id {testId}',
|
|
278
|
-
action: async ({ testId }) => {
|
|
279
|
-
const found = await this.withPage(async (page) => await page.getByTestId(testId));
|
|
280
|
-
return found ? OK : actionNotOK(`Did not find test id ${testId}`);
|
|
281
|
-
},
|
|
282
|
-
},
|
|
283
|
-
seeTextIn: {
|
|
284
|
-
gwta: 'in {selector}, see {text}',
|
|
285
|
-
action: async ({ text, selector }) => {
|
|
286
|
-
return await this.sees(text, selector);
|
|
287
|
-
},
|
|
288
|
-
},
|
|
289
|
-
seeText: {
|
|
290
|
-
gwta: 'see {text}',
|
|
291
|
-
action: async ({ text }) => {
|
|
292
|
-
return await this.sees(text, 'body');
|
|
293
|
-
},
|
|
294
|
-
},
|
|
295
|
-
waitFor: {
|
|
296
|
-
gwta: 'wait for {what}',
|
|
297
|
-
action: async ({ what }) => {
|
|
298
|
-
const selector = what.match(/^[.#]/) ? what : `text=${what}`;
|
|
299
|
-
const found = await this.withPage(async (page) => await page.waitForSelector(selector));
|
|
300
|
-
if (found) {
|
|
301
|
-
return OK;
|
|
302
|
-
}
|
|
303
|
-
return actionNotOK(`Did not find ${what}`);
|
|
304
|
-
},
|
|
305
|
-
},
|
|
306
|
-
createMonitor: {
|
|
307
|
-
gwta: 'create monitor',
|
|
308
|
-
action: async () => {
|
|
309
|
-
await this.createMonitor();
|
|
310
|
-
return OK;
|
|
311
|
-
},
|
|
312
|
-
},
|
|
313
|
-
finishMonitor: {
|
|
314
|
-
gwta: 'finish monitor',
|
|
315
|
-
action: async () => {
|
|
316
|
-
await WebPlaywright.monitorHandler.writeMonitor();
|
|
317
|
-
return OK;
|
|
318
|
-
},
|
|
319
|
-
},
|
|
320
|
-
onNewPage: {
|
|
321
|
-
gwta: `on a new tab`,
|
|
322
|
-
action: async () => {
|
|
323
|
-
this.newTab();
|
|
324
|
-
return Promise.resolve(OK);
|
|
325
|
-
},
|
|
326
|
-
},
|
|
327
|
-
waitForTabX: {
|
|
328
|
-
gwta: `pause until current tab is {tab}`,
|
|
329
|
-
action: async ({ tab }) => {
|
|
330
|
-
const waitForTab = parseInt(tab, 10);
|
|
331
|
-
let timedOut = false;
|
|
332
|
-
setTimeout(() => {
|
|
333
|
-
timedOut = true;
|
|
334
|
-
}, 5000);
|
|
335
|
-
while (this.tab !== waitForTab && !timedOut) {
|
|
336
|
-
await sleep(100);
|
|
337
|
-
}
|
|
338
|
-
return this.tab === waitForTab ? OK : actionNotOK(`current tab is ${this.tab}, not ${waitForTab}`);
|
|
339
|
-
},
|
|
340
|
-
},
|
|
341
|
-
onTabX: {
|
|
342
|
-
gwta: `on tab {tab}`,
|
|
343
|
-
action: async ({ tab }) => {
|
|
344
|
-
this.tab = parseInt(tab, 10);
|
|
345
|
-
return Promise.resolve(OK);
|
|
346
|
-
},
|
|
347
|
-
},
|
|
348
|
-
beOnPage: {
|
|
349
|
-
gwta: `be on the {name} ${WEB_PAGE}`,
|
|
350
|
-
action: async ({ name }) => {
|
|
351
|
-
const nowon = await this.withPage(async (page) => {
|
|
352
|
-
await page.waitForURL(name);
|
|
353
|
-
return page.url();
|
|
354
|
-
});
|
|
355
|
-
if (nowon === name) {
|
|
356
|
-
return OK;
|
|
357
|
-
}
|
|
358
|
-
return actionNotOK(`expected ${name} but on ${nowon}`);
|
|
359
|
-
},
|
|
360
|
-
},
|
|
361
|
-
extensionContext: {
|
|
362
|
-
gwta: `open extension popup for tab {tab}`,
|
|
363
|
-
action: async ({ tab }) => {
|
|
364
|
-
if (!this.factoryOptions?.persistentDirectory || this.factoryOptions?.launchOptions.headless) {
|
|
365
|
-
throw Error(`extensions require ${WebPlaywright.PERSISTENT_DIRECTORY} and not HEADLESS`);
|
|
366
|
-
}
|
|
367
|
-
const browserContext = await this.getExistingBrowserContext();
|
|
368
|
-
if (!browserContext) {
|
|
369
|
-
throw Error(`no browserContext`);
|
|
370
|
-
}
|
|
371
|
-
const background = browserContext?.serviceWorkers()[0];
|
|
372
|
-
if (!background) {
|
|
373
|
-
// background = await context.waitForEvent("serviceworker");
|
|
374
|
-
}
|
|
375
|
-
console.debug('background', background, browserContext.serviceWorkers());
|
|
376
|
-
const extensionId = background.url().split('/')[2];
|
|
377
|
-
this.getWorld().shared.set('extensionContext', extensionId);
|
|
378
|
-
await this.withPage(async (page) => {
|
|
379
|
-
const popupURI = `chrome-extension://${extensionId}/popup.html?${tab}`;
|
|
380
|
-
return await page.goto(popupURI);
|
|
381
|
-
});
|
|
382
|
-
return OK;
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
cookieIs: {
|
|
386
|
-
gwta: 'cookie {name} is {value}',
|
|
387
|
-
action: async ({ name, value }) => {
|
|
388
|
-
const cookies = await this.getCookies();
|
|
389
|
-
const found = cookies?.find((c) => c.name === name && c.value === value);
|
|
390
|
-
return found ? OK : actionNotOK(`did not find cookie ${name} with value ${value} from ${JSON.stringify(cookies)}`);
|
|
391
|
-
},
|
|
392
|
-
},
|
|
393
|
-
URIContains: {
|
|
394
|
-
gwta: 'URI includes {what}',
|
|
395
|
-
action: async ({ what }) => {
|
|
396
|
-
const uri = await this.withPage(async (page) => await page.url());
|
|
397
|
-
return uri.includes(what) ? OK : actionNotOK(`current URI ${uri} does not contain ${what}`);
|
|
398
|
-
},
|
|
399
|
-
},
|
|
400
|
-
URIQueryParameterIs: {
|
|
401
|
-
gwta: 'URI query parameter {what} is {value}',
|
|
402
|
-
action: async ({ what, value }) => {
|
|
403
|
-
const uri = await this.withPage(async (page) => await page.url());
|
|
404
|
-
const found = new URL(uri).searchParams.get(what);
|
|
405
|
-
if (found === value) {
|
|
406
|
-
return OK;
|
|
407
|
-
}
|
|
408
|
-
return actionNotOK(`URI query ${what} contains "${found}"", not "${value}""`);
|
|
409
|
-
},
|
|
410
|
-
},
|
|
411
|
-
URIStartsWith: {
|
|
412
|
-
gwta: 'URI starts with {start}',
|
|
413
|
-
action: async ({ start }) => {
|
|
414
|
-
const uri = await this.withPage(async (page) => await page.url());
|
|
415
|
-
return uri.startsWith(start) ? OK : actionNotOK(`current URI ${uri} does not start with ${start}`);
|
|
416
|
-
},
|
|
417
|
-
},
|
|
418
|
-
URIMatches: {
|
|
419
|
-
gwta: 'URI matches {what}',
|
|
420
|
-
action: async ({ what }) => {
|
|
421
|
-
const uri = await this.withPage(async (page) => await page.url());
|
|
422
|
-
return uri.match(what) ? OK : actionNotOK(`current URI ${uri} does not match ${what}`);
|
|
423
|
-
},
|
|
424
|
-
},
|
|
425
|
-
caseInsensitiveURIMatches: {
|
|
426
|
-
gwta: 'URI case insensitively matches {what}',
|
|
427
|
-
action: async ({ what }) => {
|
|
428
|
-
const uri = await this.withPage(async (page) => await page.url());
|
|
429
|
-
const matcher = new RegExp(what, 'i');
|
|
430
|
-
return uri.match(matcher) ? OK : actionNotOK(`current URI ${uri} does not match ${what}`);
|
|
431
|
-
},
|
|
432
|
-
},
|
|
433
|
-
// CLICK
|
|
434
|
-
clickByAltText: {
|
|
435
|
-
gwta: 'click by alt text {altText}',
|
|
436
|
-
action: async ({ altText }) => {
|
|
437
|
-
await this.withPage(async (page) => await page.getByAltText(altText).click());
|
|
438
|
-
return OK;
|
|
439
|
-
},
|
|
440
|
-
},
|
|
441
|
-
clickByTestId: {
|
|
442
|
-
gwta: 'click by test id {testId}',
|
|
443
|
-
action: async ({ testId }) => {
|
|
444
|
-
await this.withPage(async (page) => await page.getByTestId(testId).click());
|
|
445
|
-
return OK;
|
|
446
|
-
},
|
|
447
|
-
},
|
|
448
|
-
clickByPlaceholder: {
|
|
449
|
-
gwta: 'click by placeholder {placeholder}',
|
|
450
|
-
action: async ({ placeholder }) => {
|
|
451
|
-
await this.withPage(async (page) => await page.getByPlaceholder(placeholder).click());
|
|
452
|
-
return OK;
|
|
453
|
-
},
|
|
454
|
-
},
|
|
455
|
-
clickByRole: {
|
|
456
|
-
gwta: 'click by role {roleStr}',
|
|
457
|
-
action: async ({ roleStr }) => {
|
|
458
|
-
const [role, ...restStr] = roleStr.split(' ');
|
|
459
|
-
let rest;
|
|
460
|
-
try {
|
|
461
|
-
rest = JSON.parse(restStr.join(' '));
|
|
462
|
-
}
|
|
463
|
-
catch (e) {
|
|
464
|
-
return actionNotOK(`could not parse role ${roleStr} as JSON: ${e}`);
|
|
465
|
-
}
|
|
466
|
-
await this.withPage(async (page) => await page.getByRole(role, rest || {}).click());
|
|
467
|
-
return OK;
|
|
468
|
-
},
|
|
469
|
-
},
|
|
470
|
-
clickByLabel: {
|
|
471
|
-
gwta: 'click by label {label}',
|
|
472
|
-
action: async ({ title: label }) => {
|
|
473
|
-
await this.withPage(async (page) => await page.getByLabel(label).click());
|
|
474
|
-
return OK;
|
|
475
|
-
},
|
|
476
|
-
},
|
|
477
|
-
clickByTitle: {
|
|
478
|
-
gwta: 'click by title {title}',
|
|
479
|
-
action: async ({ title }) => {
|
|
480
|
-
await this.withPage(async (page) => await page.getByTitle(title).click());
|
|
481
|
-
return OK;
|
|
482
|
-
},
|
|
483
|
-
},
|
|
484
|
-
clickByText: {
|
|
485
|
-
gwta: 'click by text {text}',
|
|
486
|
-
action: async ({ text }) => {
|
|
487
|
-
await this.withPage(async (page) => await page.getByText(text).click());
|
|
488
|
-
return OK;
|
|
489
|
-
},
|
|
490
|
-
},
|
|
491
|
-
clickOn: {
|
|
492
|
-
gwta: 'click on (?<name>.[^s]+)',
|
|
493
|
-
action: async ({ name }) => {
|
|
494
|
-
const what = this.getWorld().shared.get(name) || `text=${name}`;
|
|
495
|
-
await this.withPage(async (page) => await page.click(what));
|
|
496
|
-
return OK;
|
|
497
|
-
},
|
|
498
|
-
},
|
|
499
|
-
clickCheckbox: {
|
|
500
|
-
gwta: 'click the checkbox (?<name>.+)',
|
|
501
|
-
action: async ({ name }) => {
|
|
502
|
-
const what = this.getWorld().shared.get(name) || name;
|
|
503
|
-
this.getWorld().logger.log(`click ${name} ${what}`);
|
|
504
|
-
await this.withPage(async (page) => await page.click(what));
|
|
505
|
-
return OK;
|
|
506
|
-
},
|
|
507
|
-
},
|
|
508
|
-
clickShared: {
|
|
509
|
-
gwta: 'click `(?<id>.+)`',
|
|
510
|
-
action: async ({ id }) => {
|
|
511
|
-
const name = this.getWorld().shared.get(id);
|
|
512
|
-
await this.withPage(async (page) => await page.click(name));
|
|
513
|
-
return OK;
|
|
514
|
-
},
|
|
515
|
-
},
|
|
516
|
-
clickQuoted: {
|
|
517
|
-
gwta: 'click "(?<name>.+)"',
|
|
518
|
-
action: async ({ name }) => {
|
|
519
|
-
await this.withPage(async (page) => await page.click(`text=${name}`));
|
|
520
|
-
return OK;
|
|
521
|
-
},
|
|
522
|
-
},
|
|
523
|
-
clickLink: {
|
|
524
|
-
// TODO: generalize modifier
|
|
525
|
-
gwta: 'click( with alt)? the link {name}',
|
|
526
|
-
action: async ({ name }, featureStep) => {
|
|
527
|
-
const modifier = featureStep.in.match(/ with alt /) ? { modifiers: ['Alt'] } : {};
|
|
528
|
-
const field = this.getWorld().shared.get(name) || name;
|
|
529
|
-
await this.withPage(async (page) => await page.click(field, modifier));
|
|
530
|
-
return OK;
|
|
531
|
-
},
|
|
532
|
-
},
|
|
533
|
-
clickButton: {
|
|
534
|
-
gwta: 'click the button (?<id>.+)',
|
|
535
|
-
action: async ({ id }) => {
|
|
536
|
-
const field = this.getWorld().shared.get(id) || id;
|
|
537
|
-
await this.withPage(async (page) => await page.click(field));
|
|
538
|
-
return OK;
|
|
539
|
-
},
|
|
540
|
-
},
|
|
541
|
-
// NAVIGATION
|
|
542
|
-
// formerly On the {name} ${WEB_PAGE}
|
|
543
|
-
gotoPage: {
|
|
544
|
-
gwta: `go to the {name} ${WEB_PAGE}`,
|
|
545
|
-
action: async ({ name }) => {
|
|
546
|
-
const response = await this.withPage(async (page) => {
|
|
547
|
-
return await page.goto(name);
|
|
548
|
-
});
|
|
549
|
-
const messageContext = {
|
|
550
|
-
incident: EExecutionMessageType.ACTION,
|
|
551
|
-
incidentDetails: { ...response?.allHeaders, summary: response?.statusText() }
|
|
552
|
-
};
|
|
553
|
-
return response?.ok ? OK : actionNotOK(`response not ok`, { messageContext });
|
|
554
|
-
},
|
|
555
|
-
},
|
|
556
|
-
reloadPage: {
|
|
557
|
-
gwta: 'reload page',
|
|
558
|
-
action: async () => {
|
|
559
|
-
await this.withPage(async (page) => await page.reload());
|
|
560
|
-
return OK;
|
|
561
|
-
},
|
|
562
|
-
},
|
|
563
|
-
goBack: {
|
|
564
|
-
gwta: 'go back',
|
|
565
|
-
action: async () => {
|
|
566
|
-
await this.withPage(async (page) => await page.goBack());
|
|
567
|
-
return OK;
|
|
568
|
-
},
|
|
569
|
-
},
|
|
570
|
-
blur: {
|
|
571
|
-
gwta: 'blur {what}',
|
|
572
|
-
action: async ({ what }) => {
|
|
573
|
-
await this.withPage(async (page) => await page.locator(what).evaluate((e) => e.blur()));
|
|
574
|
-
return OK;
|
|
575
|
-
},
|
|
576
|
-
},
|
|
577
|
-
// BROWSER
|
|
578
|
-
usingBrowserVar: {
|
|
579
|
-
gwta: 'using {browser} browser',
|
|
580
|
-
action: async ({ browser }) => {
|
|
581
|
-
if (!BROWSERS[browser]) {
|
|
582
|
-
throw Error(`browserType not recognized ${browser} from ${BROWSERS.toString()}`);
|
|
583
|
-
}
|
|
584
|
-
return Promise.resolve(this.setBrowser(browser));
|
|
585
|
-
},
|
|
586
|
-
},
|
|
587
|
-
// FILE DOWNLOAD/UPLOAD
|
|
588
|
-
uploadFile: {
|
|
589
|
-
gwta: 'upload file {file} using {selector}',
|
|
590
|
-
action: async ({ file, selector }) => {
|
|
591
|
-
await this.withPage(async (page) => await page.setInputFiles(selector, file));
|
|
592
|
-
return OK;
|
|
593
|
-
},
|
|
594
|
-
},
|
|
595
|
-
waitForFileChooser: {
|
|
596
|
-
gwta: 'upload file {file} with {selector}',
|
|
597
|
-
action: async ({ file, selector }) => {
|
|
598
|
-
try {
|
|
599
|
-
await this.withPage(async (page) => {
|
|
600
|
-
const [fileChooser] = await Promise.all([page.waitForEvent('filechooser'), page.locator('#uploadFile').click()]);
|
|
601
|
-
const changeButton = page.locator(selector);
|
|
602
|
-
await changeButton.click();
|
|
603
|
-
await fileChooser.setFiles(file);
|
|
604
|
-
});
|
|
605
|
-
return OK;
|
|
606
|
-
}
|
|
607
|
-
catch (e) {
|
|
608
|
-
return actionNotOK(e);
|
|
609
|
-
}
|
|
610
|
-
},
|
|
611
|
-
},
|
|
612
|
-
expectDownload: {
|
|
613
|
-
gwta: 'expect a download',
|
|
614
|
-
action: async () => {
|
|
615
|
-
try {
|
|
616
|
-
this.expectedDownload = this.withPage(async (page) => page.waitForEvent('download'));
|
|
617
|
-
return Promise.resolve(OK);
|
|
618
|
-
}
|
|
619
|
-
catch (e) {
|
|
620
|
-
return Promise.resolve(actionNotOK(e));
|
|
621
|
-
}
|
|
622
|
-
},
|
|
623
|
-
},
|
|
624
|
-
receiveDownload: {
|
|
625
|
-
gwta: 'receive download as {file}',
|
|
626
|
-
action: async ({ file }) => {
|
|
627
|
-
try {
|
|
628
|
-
const download = await this.expectedDownload;
|
|
629
|
-
await download.saveAs(file);
|
|
630
|
-
this.downloaded.push(file);
|
|
631
|
-
return OK;
|
|
632
|
-
}
|
|
633
|
-
catch (e) {
|
|
634
|
-
return actionNotOK(e);
|
|
635
|
-
}
|
|
636
|
-
},
|
|
637
|
-
},
|
|
638
|
-
waitForDownload: {
|
|
639
|
-
gwta: 'save download to {file}',
|
|
640
|
-
action: async ({ file }) => {
|
|
641
|
-
try {
|
|
642
|
-
const download = await this.withPage(async (page) => page.waitForEvent('download'));
|
|
643
|
-
await download.saveAs(file);
|
|
644
|
-
this.downloaded.push(file);
|
|
645
|
-
return OK;
|
|
646
|
-
}
|
|
647
|
-
catch (e) {
|
|
648
|
-
return actionNotOK(e);
|
|
649
|
-
}
|
|
650
|
-
},
|
|
651
|
-
},
|
|
652
|
-
// MISC
|
|
653
|
-
withFrame: {
|
|
654
|
-
gwta: 'with frame {name}',
|
|
655
|
-
action: async ({ name }) => {
|
|
656
|
-
this.withFrame = name;
|
|
657
|
-
return Promise.resolve(OK);
|
|
658
|
-
},
|
|
659
|
-
},
|
|
660
|
-
captureDialog: {
|
|
661
|
-
gwta: 'Accept next dialog to {where}',
|
|
662
|
-
action: async ({ where }) => {
|
|
663
|
-
await this.withPage((page) => {
|
|
664
|
-
return page.on('dialog', async (dialog) => {
|
|
665
|
-
const res = {
|
|
666
|
-
defaultValue: dialog.defaultValue(),
|
|
667
|
-
message: dialog.message(),
|
|
668
|
-
type: dialog.type(),
|
|
669
|
-
};
|
|
670
|
-
await dialog.accept();
|
|
671
|
-
this.getWorld().shared.setJSON(where, res);
|
|
672
|
-
});
|
|
673
|
-
});
|
|
674
|
-
return Promise.resolve(OK);
|
|
675
|
-
},
|
|
676
|
-
},
|
|
677
|
-
takeScreenshot: {
|
|
678
|
-
gwta: 'take a screenshot',
|
|
679
|
-
action: async (notUsed, featureStep) => {
|
|
680
|
-
try {
|
|
681
|
-
await this.captureScreenshotAndLog(EExecutionMessageType.ACTION, featureStep);
|
|
682
|
-
return OK;
|
|
683
|
-
}
|
|
684
|
-
catch (e) {
|
|
685
|
-
return actionNotOK(e);
|
|
686
|
-
}
|
|
687
|
-
},
|
|
688
|
-
},
|
|
689
|
-
assertOpen: {
|
|
690
|
-
gwta: '{what} is expanded with the {using}',
|
|
691
|
-
action: async ({ what, using }) => {
|
|
692
|
-
const isVisible = await this.withPage(async (page) => await page.isVisible(what));
|
|
693
|
-
if (!isVisible) {
|
|
694
|
-
await this.withPage(async (page) => await page.click(using));
|
|
695
|
-
}
|
|
696
|
-
return OK;
|
|
697
|
-
},
|
|
698
|
-
},
|
|
699
|
-
setToURIQueryParameter: {
|
|
700
|
-
gwta: 'save URI query parameter {what} to {where}',
|
|
701
|
-
action: async ({ what, where }) => {
|
|
702
|
-
const uri = await this.withPage(async (page) => await page.url());
|
|
703
|
-
const found = new URL(uri).searchParams.get(what);
|
|
704
|
-
this.getWorld().shared.set(where, found);
|
|
705
|
-
return OK;
|
|
706
|
-
},
|
|
707
|
-
},
|
|
708
|
-
resizeWindow: {
|
|
709
|
-
gwta: 'resize window to {width}x{height}',
|
|
710
|
-
action: async ({ width, height }) => {
|
|
711
|
-
await this.withPage(async (page) => await page.setViewportSize({ width: parseInt(width), height: parseInt(height) }));
|
|
712
|
-
return OK;
|
|
713
|
-
},
|
|
714
|
-
},
|
|
715
|
-
resizeAvailable: {
|
|
716
|
-
gwta: 'resize window to largest dimensions',
|
|
717
|
-
action: async () => {
|
|
718
|
-
await this.withPage(async (page) => {
|
|
719
|
-
const { availHeight: height, availWidth: width } = await page.evaluate(() => ({ availHeight: window.screen.availHeight, availWidth: window.screen.availWidth }));
|
|
720
|
-
return await page.setViewportSize({ width, height });
|
|
721
|
-
});
|
|
722
|
-
return OK;
|
|
723
|
-
},
|
|
724
|
-
},
|
|
165
|
+
...interactionSteps(this),
|
|
725
166
|
};
|
|
726
167
|
setBrowser(browser) {
|
|
727
168
|
this.factoryOptions.type = browser;
|