flowstride 1.0.11 → 1.0.13
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/dist/adapters/web/playwright.d.ts +1 -0
- package/dist/adapters/web/playwright.js +60 -0
- package/dist/cli/index.js +1 -1
- package/dist/parser/lexer.js +25 -8
- package/dist/parser/parser.d.ts +6 -0
- package/dist/parser/parser.js +106 -30
- package/dist/runner/flow_orchestrator.d.ts +1 -0
- package/dist/runner/flow_orchestrator.js +20 -5
- package/dist/runner/flow_worker.d.ts +1 -0
- package/dist/runner/flow_worker.js +204 -131
- package/package.json +1 -1
- package/src/ui/dist/assets/flow_logo-CjiL4Lvy.png +0 -0
- package/src/ui/dist/assets/index-BCdexgt5.js +0 -270
- package/src/ui/dist/assets/index-DXTn_ThB.css +0 -1
- package/src/ui/dist/favicon.png +0 -0
- package/src/ui/dist/favicon.svg +0 -1
- package/src/ui/dist/icons.svg +0 -24
- package/src/ui/dist/index.html +0 -14
|
@@ -55,6 +55,7 @@ class FlowWorker extends events_1.EventEmitter {
|
|
|
55
55
|
pluginManager;
|
|
56
56
|
isSilent = process.env.FLOWSTRIDE_PARALLEL === "true";
|
|
57
57
|
isAborted = false;
|
|
58
|
+
isDebugHalted = false;
|
|
58
59
|
currentStepContext = "Initializing...";
|
|
59
60
|
currentFileName = "System";
|
|
60
61
|
activeAudioPath = undefined;
|
|
@@ -171,6 +172,8 @@ class FlowWorker extends events_1.EventEmitter {
|
|
|
171
172
|
extractFromJsonPath(obj, path) {
|
|
172
173
|
if (!obj)
|
|
173
174
|
return undefined;
|
|
175
|
+
if (!path)
|
|
176
|
+
return obj;
|
|
174
177
|
const parts = path.replace(/\[(\d+)\]/g, ".$1").split(".");
|
|
175
178
|
let current = obj;
|
|
176
179
|
for (const part of parts) {
|
|
@@ -186,11 +189,11 @@ class FlowWorker extends events_1.EventEmitter {
|
|
|
186
189
|
const state = this.api.getState();
|
|
187
190
|
for (const ext of extracts) {
|
|
188
191
|
let val;
|
|
189
|
-
if (ext.target === "
|
|
192
|
+
if (ext.target === "resBody") {
|
|
190
193
|
val = this.extractFromJsonPath(state.body, ext.jsonPath);
|
|
191
194
|
}
|
|
192
|
-
else if (ext.target === "
|
|
193
|
-
val = state.headers?.[ext.jsonPath.toLowerCase()];
|
|
195
|
+
else if (ext.target === "resHeader") {
|
|
196
|
+
val = state.headers?.[(ext.jsonPath || "").toLowerCase()];
|
|
194
197
|
}
|
|
195
198
|
else if (ext.target === "cookie") {
|
|
196
199
|
const cookies = state.headers?.["set-cookie"];
|
|
@@ -340,136 +343,174 @@ class FlowWorker extends events_1.EventEmitter {
|
|
|
340
343
|
this.config.headless = true;
|
|
341
344
|
this.activeAudioPath = undefined;
|
|
342
345
|
this.isAborted = false;
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
const rawPath = audioMatch[1];
|
|
348
|
-
const absolutePath = path.resolve(process.cwd(), rawPath);
|
|
349
|
-
if (!fs.existsSync(absolutePath)) {
|
|
350
|
-
throw new Error(`Pre-launch initialization failed: Audio file not found at ${absolutePath}`);
|
|
351
|
-
}
|
|
352
|
-
this.activeAudioPath = absolutePath;
|
|
353
|
-
break;
|
|
346
|
+
this.isDebugHalted = false;
|
|
347
|
+
const sigintHandler = async () => {
|
|
348
|
+
if (!this.isSilent) {
|
|
349
|
+
console.log(chalk_1.default.yellow("\n[Flowstride]: Process interrupted. Gracefully shutting down..."));
|
|
354
350
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
if (this.isAborted)
|
|
358
|
-
break;
|
|
359
|
-
const fileStartTime = Date.now();
|
|
351
|
+
this.abort();
|
|
352
|
+
this.broadcast("SERVER_SHUTDOWN", { message: "Terminal closed." });
|
|
360
353
|
try {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
await this.setupNetworkInterception();
|
|
354
|
+
await this.web.shutdown();
|
|
355
|
+
}
|
|
356
|
+
catch (e) { }
|
|
357
|
+
process.exit(0);
|
|
358
|
+
};
|
|
359
|
+
process.once("SIGINT", sigintHandler);
|
|
360
|
+
try {
|
|
361
|
+
for (const filePath of filesToProcess) {
|
|
370
362
|
const content = fs.readFileSync(filePath, "utf8");
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
363
|
+
const audioMatch = content.match(/(?:flow\.)?injectAudio\s+["']([^"']+)["']/i);
|
|
364
|
+
if (audioMatch && audioMatch[1]) {
|
|
365
|
+
const rawPath = audioMatch[1];
|
|
366
|
+
const absolutePath = path.resolve(process.cwd(), rawPath);
|
|
367
|
+
if (!fs.existsSync(absolutePath)) {
|
|
368
|
+
throw new Error(`Pre-launch initialization failed: Audio file not found at ${absolutePath}`);
|
|
369
|
+
}
|
|
370
|
+
this.activeAudioPath = absolutePath;
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
for (const filePath of filesToProcess) {
|
|
375
|
+
if (this.isAborted || this.isDebugHalted)
|
|
376
|
+
break;
|
|
377
|
+
const fileStartTime = Date.now();
|
|
378
|
+
try {
|
|
379
|
+
const fileName = path.basename(filePath);
|
|
380
|
+
this.currentFileName = fileName;
|
|
381
|
+
this.localVariables = {};
|
|
382
|
+
this.localBrowserSessions = {};
|
|
383
|
+
this.api.resetState();
|
|
384
|
+
this.dataGen = new data_generators_1.DataGenerators();
|
|
385
|
+
await this.web.initialise(this.activeAudioPath);
|
|
386
|
+
await this.startStreaming();
|
|
387
|
+
await this.setupNetworkInterception();
|
|
388
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
389
|
+
const hasSessionIntent = content.includes("use session") ||
|
|
390
|
+
content.includes("use global session");
|
|
391
|
+
if (!hasSessionIntent) {
|
|
392
|
+
try {
|
|
393
|
+
const page = this.web.getPage();
|
|
394
|
+
if (page) {
|
|
395
|
+
await page
|
|
396
|
+
.context()
|
|
397
|
+
.clearCookies()
|
|
398
|
+
.catch(() => { });
|
|
399
|
+
await page
|
|
400
|
+
.evaluate(() => {
|
|
401
|
+
try {
|
|
402
|
+
localStorage.clear();
|
|
403
|
+
}
|
|
404
|
+
catch (e) { }
|
|
405
|
+
try {
|
|
406
|
+
sessionStorage.clear();
|
|
407
|
+
}
|
|
408
|
+
catch (e) { }
|
|
409
|
+
})
|
|
410
|
+
.catch(() => { });
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
catch (e) { }
|
|
414
|
+
}
|
|
415
|
+
if (!this.isSilent)
|
|
416
|
+
console.log(chalk_1.default.blue.bold(`\n[Execution]: Processing file: ${fileName}`));
|
|
417
|
+
this.emitLog("FILE_HEADER", "info", fileName, { filePath });
|
|
418
|
+
const features = new parser_1.Parser(new lexer_1.Lexer(content).tokenise()).parse();
|
|
419
|
+
const hasOnlyMode = features.some((f) => f.scenarios.some((s) => s.isOnly));
|
|
420
|
+
if (hasOnlyMode) {
|
|
421
|
+
if (!this.isSilent) {
|
|
422
|
+
console.log(chalk_1.default.yellow(` > [Debug Mode]: 'only.Scenario' detected. Operating in Ghost Mode.`));
|
|
423
|
+
}
|
|
424
|
+
features.forEach((f) => {
|
|
425
|
+
f.scenarios = f.scenarios.filter((s) => s.isOnly);
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
for (const f of features) {
|
|
429
|
+
if (this.isAborted || this.isDebugHalted)
|
|
430
|
+
break;
|
|
431
|
+
if (f.scenarios.length === 0)
|
|
432
|
+
continue;
|
|
433
|
+
if (!this.isSilent)
|
|
434
|
+
console.log(chalk_1.default.magenta.bold(` Feature: ${f.name}`));
|
|
435
|
+
for (const s of f.scenarios) {
|
|
436
|
+
if (this.isAborted || this.isDebugHalted)
|
|
437
|
+
break;
|
|
438
|
+
if (!this.isSilent)
|
|
439
|
+
console.log(chalk_1.default.cyan(` Scenario: ${s.name}`));
|
|
440
|
+
this.broadcast("RUN_START", {
|
|
441
|
+
scenarioName: s.name,
|
|
442
|
+
fileName: this.currentFileName,
|
|
443
|
+
});
|
|
444
|
+
await this.runScenario(s, f.declarations);
|
|
445
|
+
if (this.isDebugHalted)
|
|
446
|
+
break;
|
|
447
|
+
await this.web
|
|
448
|
+
.getPage()
|
|
449
|
+
.waitForLoadState("load", { timeout: 4000 })
|
|
380
450
|
.catch(() => { });
|
|
381
|
-
await
|
|
382
|
-
.
|
|
383
|
-
|
|
384
|
-
localStorage.clear();
|
|
385
|
-
}
|
|
386
|
-
catch (e) { }
|
|
387
|
-
try {
|
|
388
|
-
sessionStorage.clear();
|
|
389
|
-
}
|
|
390
|
-
catch (e) { }
|
|
391
|
-
})
|
|
451
|
+
await this.web
|
|
452
|
+
.getPage()
|
|
453
|
+
.waitForLoadState("networkidle", { timeout: 4000 })
|
|
392
454
|
.catch(() => { });
|
|
455
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
393
456
|
}
|
|
394
457
|
}
|
|
395
|
-
catch (e) { }
|
|
396
|
-
}
|
|
397
|
-
if (!this.isSilent)
|
|
398
|
-
console.log(chalk_1.default.blue.bold(`\n[Execution]: Processing file: ${fileName}`));
|
|
399
|
-
this.emitLog("FILE_HEADER", "info", fileName, { filePath });
|
|
400
|
-
const features = new parser_1.Parser(new lexer_1.Lexer(content).tokenise()).parse();
|
|
401
|
-
for (const f of features) {
|
|
402
458
|
if (this.isAborted)
|
|
403
459
|
break;
|
|
404
460
|
if (!this.isSilent)
|
|
405
|
-
console.log(chalk_1.default.
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
461
|
+
console.log(chalk_1.default.gray("\n[Execution]: Finalizing browser actions..."));
|
|
462
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
463
|
+
try {
|
|
464
|
+
const baseName = this.currentFileName.replace(".flow", "");
|
|
465
|
+
const mockCloudDir = path.join(process.cwd(), ".flowstride", "mock-cloud");
|
|
466
|
+
if (!fs.existsSync(mockCloudDir))
|
|
467
|
+
fs.mkdirSync(mockCloudDir, { recursive: true });
|
|
468
|
+
const targetVideoPath = path.join(mockCloudDir, `${baseName}.webm`);
|
|
469
|
+
await this.web.shutdown(targetVideoPath);
|
|
409
470
|
if (!this.isSilent)
|
|
410
|
-
console.log(chalk_1.default.
|
|
411
|
-
this.broadcast("RUN_START", {
|
|
412
|
-
scenarioName: s.name,
|
|
413
|
-
fileName: this.currentFileName,
|
|
414
|
-
});
|
|
415
|
-
await this.runScenario(s, f.declarations);
|
|
416
|
-
await this.web
|
|
417
|
-
.getPage()
|
|
418
|
-
.waitForLoadState("load", { timeout: 4000 })
|
|
419
|
-
.catch(() => { });
|
|
420
|
-
await this.web
|
|
421
|
-
.getPage()
|
|
422
|
-
.waitForLoadState("networkidle", { timeout: 4000 })
|
|
423
|
-
.catch(() => { });
|
|
424
|
-
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
471
|
+
console.log(chalk_1.default.gray(` [Cloud Sync]: Video safely encoded and preserved for ${this.currentFileName}`));
|
|
425
472
|
}
|
|
473
|
+
catch (err) { }
|
|
474
|
+
this.broadcast("FILE_COMPLETE", {
|
|
475
|
+
fileName: this.currentFileName,
|
|
476
|
+
duration: Date.now() - fileStartTime,
|
|
477
|
+
});
|
|
426
478
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
console.log(chalk_1.default.gray("\n[Execution]: Finalizing browser actions..."));
|
|
431
|
-
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
432
|
-
try {
|
|
433
|
-
const baseName = this.currentFileName.replace(".flow", "");
|
|
434
|
-
const mockCloudDir = path.join(process.cwd(), ".flowstride", "mock-cloud");
|
|
435
|
-
if (!fs.existsSync(mockCloudDir))
|
|
436
|
-
fs.mkdirSync(mockCloudDir, { recursive: true });
|
|
437
|
-
const targetVideoPath = path.join(mockCloudDir, `${baseName}.webm`);
|
|
438
|
-
await this.web.shutdown(targetVideoPath);
|
|
479
|
+
catch (e) {
|
|
480
|
+
if (this.isAborted)
|
|
481
|
+
break;
|
|
439
482
|
if (!this.isSilent)
|
|
440
|
-
console.
|
|
483
|
+
console.error(chalk_1.default.red(`\n[Execution]: Failed processing ${this.currentFileName}: ${e.message}`));
|
|
484
|
+
try {
|
|
485
|
+
const baseName = this.currentFileName.replace(".flow", "");
|
|
486
|
+
const mockCloudDir = path.join(process.cwd(), ".flowstride", "mock-cloud");
|
|
487
|
+
if (!fs.existsSync(mockCloudDir))
|
|
488
|
+
fs.mkdirSync(mockCloudDir, { recursive: true });
|
|
489
|
+
const targetVideoPath = path.join(mockCloudDir, `${baseName}.webm`);
|
|
490
|
+
await this.web.shutdown(targetVideoPath);
|
|
491
|
+
if (!this.isSilent)
|
|
492
|
+
console.log(chalk_1.default.gray(` [Cloud Sync]: Video safely encoded and preserved for ${this.currentFileName}`));
|
|
493
|
+
}
|
|
494
|
+
catch (err) { }
|
|
495
|
+
this.broadcast("FILE_FAILED", {
|
|
496
|
+
fileName: this.currentFileName,
|
|
497
|
+
duration: Date.now() - fileStartTime,
|
|
498
|
+
error: e.message,
|
|
499
|
+
});
|
|
441
500
|
}
|
|
442
|
-
catch (err) { }
|
|
443
|
-
this.broadcast("FILE_COMPLETE", {
|
|
444
|
-
fileName: this.currentFileName,
|
|
445
|
-
duration: Date.now() - fileStartTime,
|
|
446
|
-
});
|
|
447
501
|
}
|
|
448
|
-
|
|
449
|
-
if (this.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
const baseName = this.currentFileName.replace(".flow", "");
|
|
455
|
-
const mockCloudDir = path.join(process.cwd(), ".flowstride", "mock-cloud");
|
|
456
|
-
if (!fs.existsSync(mockCloudDir))
|
|
457
|
-
fs.mkdirSync(mockCloudDir, { recursive: true });
|
|
458
|
-
const targetVideoPath = path.join(mockCloudDir, `${baseName}.webm`);
|
|
459
|
-
await this.web.shutdown(targetVideoPath);
|
|
460
|
-
if (!this.isSilent)
|
|
461
|
-
console.log(chalk_1.default.gray(` [Cloud Sync]: Video safely encoded and preserved for ${this.currentFileName}`));
|
|
502
|
+
if (!this.isSilent && !this.isAborted) {
|
|
503
|
+
if (this.isDebugHalted) {
|
|
504
|
+
console.log(chalk_1.default.cyan("\n[Execution]: Test suite halted by debug flag."));
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
console.log(chalk_1.default.green("\n[Execution]: All suites completed successfully."));
|
|
462
508
|
}
|
|
463
|
-
catch (err) { }
|
|
464
|
-
this.broadcast("FILE_FAILED", {
|
|
465
|
-
fileName: this.currentFileName,
|
|
466
|
-
duration: Date.now() - fileStartTime,
|
|
467
|
-
error: e.message,
|
|
468
|
-
});
|
|
469
509
|
}
|
|
470
510
|
}
|
|
471
|
-
|
|
472
|
-
|
|
511
|
+
finally {
|
|
512
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
513
|
+
}
|
|
473
514
|
}
|
|
474
515
|
async runScenario(scenario, globalDeclarations = []) {
|
|
475
516
|
for (const step of scenario.steps) {
|
|
@@ -529,6 +570,13 @@ class FlowWorker extends events_1.EventEmitter {
|
|
|
529
570
|
screenshot: stepContext.screenshot,
|
|
530
571
|
fileName: this.currentFileName,
|
|
531
572
|
});
|
|
573
|
+
if (step.isStop) {
|
|
574
|
+
if (!this.isSilent) {
|
|
575
|
+
console.log(chalk_1.default.cyan(` > [Execution]: Debug stop triggered. Halting global execution.`));
|
|
576
|
+
}
|
|
577
|
+
this.isDebugHalted = true;
|
|
578
|
+
break;
|
|
579
|
+
}
|
|
532
580
|
}
|
|
533
581
|
catch (e) {
|
|
534
582
|
if (this.isAborted)
|
|
@@ -561,6 +609,7 @@ class FlowWorker extends events_1.EventEmitter {
|
|
|
561
609
|
}
|
|
562
610
|
const isUIAction = [
|
|
563
611
|
"click",
|
|
612
|
+
"hover",
|
|
564
613
|
"type",
|
|
565
614
|
"forceClick",
|
|
566
615
|
"forceType",
|
|
@@ -639,11 +688,23 @@ class FlowWorker extends events_1.EventEmitter {
|
|
|
639
688
|
}
|
|
640
689
|
}
|
|
641
690
|
async executeStep(action, payload, localDeclarations = [], globalDeclarations = []) {
|
|
691
|
+
if (payload && payload.selector === "smart-burger-fallback") {
|
|
692
|
+
payload.selector = [
|
|
693
|
+
'button[aria-label*="menu" i]',
|
|
694
|
+
'[aria-label*="menu" i]',
|
|
695
|
+
'[title*="menu" i]',
|
|
696
|
+
".bm-burger-button",
|
|
697
|
+
'[class*="hamburger" i]',
|
|
698
|
+
'[class*="burger" i]',
|
|
699
|
+
'[id*="hamburger" i]',
|
|
700
|
+
'[id*="burger" i]',
|
|
701
|
+
].join(", ");
|
|
702
|
+
}
|
|
642
703
|
switch (action) {
|
|
643
704
|
case "extract":
|
|
644
705
|
this.processExtractions([
|
|
645
706
|
{
|
|
646
|
-
target: payload.target
|
|
707
|
+
target: payload.target,
|
|
647
708
|
jsonPath: payload.jsonPath,
|
|
648
709
|
variableName: payload.variableName,
|
|
649
710
|
isGlobal: payload.isGlobal,
|
|
@@ -791,6 +852,9 @@ class FlowWorker extends events_1.EventEmitter {
|
|
|
791
852
|
case "click":
|
|
792
853
|
await this.web.click(payload.selector, payload.elementType);
|
|
793
854
|
break;
|
|
855
|
+
case "hover":
|
|
856
|
+
await this.web.hover(payload.selector, payload.elementType);
|
|
857
|
+
break;
|
|
794
858
|
case "forceClick":
|
|
795
859
|
await this.web.forceClick(payload.selector, payload.elementType);
|
|
796
860
|
break;
|
|
@@ -841,23 +905,27 @@ class FlowWorker extends events_1.EventEmitter {
|
|
|
841
905
|
await this.waitForPipeline();
|
|
842
906
|
break;
|
|
843
907
|
case "expect":
|
|
844
|
-
|
|
908
|
+
const expectType = payload.type;
|
|
909
|
+
if (["status", "responseTime", "resBody", "resHeader", "cookie"].includes(expectType)) {
|
|
845
910
|
const apiState = this.api.getState();
|
|
846
|
-
if (
|
|
847
|
-
|
|
848
|
-
|
|
911
|
+
if (expectType === "status") {
|
|
912
|
+
const expectedStatus = payload.statusCode || payload.value;
|
|
913
|
+
if (String(apiState.status) !== String(expectedStatus))
|
|
914
|
+
throw new Error(`API Assertion Failed: Expected HTTP status ${expectedStatus}, but got ${apiState.status}`);
|
|
849
915
|
}
|
|
850
|
-
else if (
|
|
851
|
-
|
|
852
|
-
|
|
916
|
+
else if (expectType === "responseTime") {
|
|
917
|
+
const threshold = payload.threshold || payload.value;
|
|
918
|
+
if (apiState.responseTime > parseInt(threshold, 10))
|
|
919
|
+
throw new Error(`API Assertion Failed: Expected response time to be less than ${threshold}ms, but got ${apiState.responseTime}ms`);
|
|
853
920
|
}
|
|
854
921
|
else {
|
|
855
922
|
let actualValue;
|
|
856
|
-
if (
|
|
923
|
+
if (expectType === "resBody")
|
|
857
924
|
actualValue = this.extractFromJsonPath(apiState.body, payload.jsonPath);
|
|
858
|
-
else if (
|
|
859
|
-
actualValue =
|
|
860
|
-
|
|
925
|
+
else if (expectType === "resHeader")
|
|
926
|
+
actualValue =
|
|
927
|
+
apiState.headers?.[(payload.jsonPath || "").toLowerCase()];
|
|
928
|
+
else if (expectType === "cookie") {
|
|
861
929
|
const cookies = apiState.headers?.["set-cookie"];
|
|
862
930
|
if (Array.isArray(cookies)) {
|
|
863
931
|
const match = cookies.find((c) => c.startsWith(`${payload.jsonPath}=`));
|
|
@@ -865,7 +933,12 @@ class FlowWorker extends events_1.EventEmitter {
|
|
|
865
933
|
actualValue = match.split("=")[1].split(";")[0];
|
|
866
934
|
}
|
|
867
935
|
}
|
|
868
|
-
|
|
936
|
+
const assertionsArray = Array.isArray(payload.assertions)
|
|
937
|
+
? payload.assertions
|
|
938
|
+
: payload.condition
|
|
939
|
+
? [{ condition: payload.condition, value: payload.value }]
|
|
940
|
+
: [];
|
|
941
|
+
for (const assertion of assertionsArray) {
|
|
869
942
|
const condition = assertion.condition;
|
|
870
943
|
const rawExpected = assertion.value;
|
|
871
944
|
const expectedLower = String(rawExpected || "").toLowerCase();
|
|
@@ -1014,13 +1087,13 @@ class FlowWorker extends events_1.EventEmitter {
|
|
|
1014
1087
|
}
|
|
1015
1088
|
}
|
|
1016
1089
|
}
|
|
1017
|
-
else if (
|
|
1090
|
+
else if (expectType === "visible")
|
|
1018
1091
|
await this.web.expectVisible(payload.selector, payload.elementType);
|
|
1019
|
-
else if (
|
|
1092
|
+
else if (expectType === "text")
|
|
1020
1093
|
await this.web.expectText(payload.selector, payload.fuzzy, payload.elementType);
|
|
1021
|
-
else if (
|
|
1094
|
+
else if (expectType === "value")
|
|
1022
1095
|
await this.web.expectValue(payload.selector, payload.text, payload.elementType);
|
|
1023
|
-
else if (
|
|
1096
|
+
else if (expectType === "transcript")
|
|
1024
1097
|
await this.web.expectTranscript(payload.text);
|
|
1025
1098
|
break;
|
|
1026
1099
|
}
|
package/package.json
CHANGED
|
Binary file
|