automation_model 1.0.724-dev → 1.0.726-dev

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.
@@ -17,6 +17,7 @@ export declare const Types: {
17
17
  ANALYZE_TABLE: string;
18
18
  SELECT: string;
19
19
  VERIFY_PAGE_PATH: string;
20
+ VERIFY_PAGE_TITLE: string;
20
21
  TYPE_PRESS: string;
21
22
  PRESS: string;
22
23
  HOVER: string;
@@ -143,8 +144,27 @@ declare class StableBrowser {
143
144
  emailCode: any;
144
145
  }>;
145
146
  _highlightElements(scope: any, css: any): Promise<void>;
146
- verifyPagePath(pathPart: any, options?: {}, world?: null): Promise<{} | undefined>;
147
- verifyPageTitle(title: any, options?: {}, world?: null): Promise<{} | undefined>;
147
+ _matcher(text: any): {
148
+ matcher: any;
149
+ queryText: any;
150
+ };
151
+ _getDomain(url: string): string;
152
+ /**
153
+ * Verify the page path matches the given path.
154
+ * @param {string} pathPart - The path to verify.
155
+ * @param {object} options - Options for verification.
156
+ * @param {object} world - The world context.
157
+ * @returns {Promise<object>} - The state info after verification.
158
+ */
159
+ verifyPagePath(pathPart: string, options?: object, world?: object): Promise<object>;
160
+ /**
161
+ * Verify the page title matches the given title.
162
+ * @param {string} title - The title to verify.
163
+ * @param {object} options - Options for verification.
164
+ * @param {object} world - The world context.
165
+ * @returns {Promise<object>} - The state info after verification.
166
+ */
167
+ verifyPageTitle(title: string, options?: object, world?: object): Promise<object>;
148
168
  findTextInAllFrames(dateAlternatives: any, numberAlternatives: any, text: any, state: any, partial?: boolean, ignoreCase?: boolean): Promise<{
149
169
  elementCount: number;
150
170
  randomToken: string;
@@ -42,6 +42,7 @@ export const Types = {
42
42
  ANALYZE_TABLE: "analyze_table",
43
43
  SELECT: "select_combobox", //
44
44
  VERIFY_PAGE_PATH: "verify_page_path",
45
+ VERIFY_PAGE_TITLE: "verify_page_title",
45
46
  TYPE_PRESS: "type_press",
46
47
  PRESS: "press_key",
47
48
  HOVER: "hover_element",
@@ -2388,8 +2389,49 @@ class StableBrowser {
2388
2389
  console.debug(error);
2389
2390
  }
2390
2391
  }
2392
+ _matcher(text) {
2393
+ if (!text) {
2394
+ return { matcher: "contains", queryText: "" };
2395
+ }
2396
+ if (text.length < 2) {
2397
+ return { matcher: "contains", queryText: text };
2398
+ }
2399
+ const split = text.split(":");
2400
+ const matcher = split[0].toLowerCase();
2401
+ const queryText = split.slice(1).join(":").trim();
2402
+ return { matcher, queryText };
2403
+ }
2404
+ _getDomain(url) {
2405
+ if (url.length === 0 || (!url.startsWith("http://") && !url.startsWith("https://"))) {
2406
+ return "";
2407
+ }
2408
+ let hostnameFragments = url.split("/")[2].split(".");
2409
+ if (hostnameFragments.some((fragment) => fragment.includes(":"))) {
2410
+ return hostnameFragments.join("-").split(":").join("-");
2411
+ }
2412
+ let n = hostnameFragments.length;
2413
+ let fragments = [...hostnameFragments];
2414
+ while (n > 0 && hostnameFragments[n - 1].length <= 3) {
2415
+ hostnameFragments.pop();
2416
+ n = hostnameFragments.length;
2417
+ }
2418
+ if (n == 0) {
2419
+ if (fragments[0] === "www")
2420
+ fragments = fragments.slice(1);
2421
+ return fragments.length > 1 ? fragments.slice(0, fragments.length - 1).join("-") : fragments.join("-");
2422
+ }
2423
+ if (hostnameFragments[0] === "www")
2424
+ hostnameFragments = hostnameFragments.slice(1);
2425
+ return hostnameFragments.join(".");
2426
+ }
2427
+ /**
2428
+ * Verify the page path matches the given path.
2429
+ * @param {string} pathPart - The path to verify.
2430
+ * @param {object} options - Options for verification.
2431
+ * @param {object} world - The world context.
2432
+ * @returns {Promise<object>} - The state info after verification.
2433
+ */
2391
2434
  async verifyPagePath(pathPart, options = {}, world = null) {
2392
- const startTime = Date.now();
2393
2435
  let error = null;
2394
2436
  let screenshotId = null;
2395
2437
  let screenshotPath = null;
@@ -2403,113 +2445,212 @@ class StableBrowser {
2403
2445
  pathPart = newValue;
2404
2446
  }
2405
2447
  info.pathPart = pathPart;
2448
+ const { matcher, queryText } = this._matcher(pathPart);
2449
+ const state = {
2450
+ text_search: queryText,
2451
+ options,
2452
+ world,
2453
+ locate: false,
2454
+ scroll: false,
2455
+ highlight: false,
2456
+ type: Types.VERIFY_PAGE_PATH,
2457
+ text: `Verify the page url is ${queryText}`,
2458
+ _text: `Verify the page url is ${queryText}`,
2459
+ operation: "verifyPagePath",
2460
+ log: "***** verify page url is " + queryText + " *****\n",
2461
+ };
2406
2462
  try {
2463
+ await _preCommand(state, this);
2464
+ state.info.text = queryText;
2407
2465
  for (let i = 0; i < 30; i++) {
2408
2466
  const url = await this.page.url();
2409
- if (!url.includes(pathPart)) {
2410
- if (i === 29) {
2411
- throw new Error(`url ${url} doesn't contain ${pathPart}`);
2412
- }
2413
- await new Promise((resolve) => setTimeout(resolve, 1000));
2414
- continue;
2467
+ switch (matcher) {
2468
+ case "exact":
2469
+ if (url !== queryText) {
2470
+ if (i === 29) {
2471
+ throw new Error(`Page URL ${url} is not equal to ${queryText}`);
2472
+ }
2473
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2474
+ continue;
2475
+ }
2476
+ break;
2477
+ case "contains":
2478
+ if (!url.includes(queryText)) {
2479
+ if (i === 29) {
2480
+ throw new Error(`Page URL ${url} doesn't contain ${queryText}`);
2481
+ }
2482
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2483
+ continue;
2484
+ }
2485
+ break;
2486
+ case "starts-with":
2487
+ {
2488
+ const domain = this._getDomain(url);
2489
+ if (domain.length > 0 && domain !== queryText) {
2490
+ if (i === 29) {
2491
+ throw new Error(`Page URL ${url} doesn't start with ${queryText}`);
2492
+ }
2493
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2494
+ continue;
2495
+ }
2496
+ }
2497
+ break;
2498
+ case "ends-with":
2499
+ {
2500
+ const urlObj = new URL(url);
2501
+ let route = "/";
2502
+ if (urlObj.pathname !== "/") {
2503
+ route = urlObj.pathname.split("/").slice(-1)[0].trim();
2504
+ }
2505
+ else {
2506
+ route = "/";
2507
+ }
2508
+ if (route !== queryText) {
2509
+ if (i === 29) {
2510
+ throw new Error(`Page URL ${url} doesn't end with ${queryText}`);
2511
+ }
2512
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2513
+ continue;
2514
+ }
2515
+ }
2516
+ break;
2517
+ case "regex":
2518
+ const regex = new RegExp(queryText.slice(1, -1), "g");
2519
+ if (!regex.test(url)) {
2520
+ if (i === 29) {
2521
+ throw new Error(`Page URL ${url} doesn't match regex ${queryText}`);
2522
+ }
2523
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2524
+ continue;
2525
+ }
2526
+ break;
2527
+ default:
2528
+ console.log("Unknown matching type, defaulting to contains match");
2529
+ if (!url.includes(queryText)) {
2530
+ if (i === 29) {
2531
+ throw new Error(`Page URL ${url} does not contain ${queryText}`);
2532
+ }
2533
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2534
+ continue;
2535
+ }
2415
2536
  }
2416
- ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
2417
- return info;
2537
+ await _screenshot(state, this);
2538
+ return state.info;
2418
2539
  }
2419
2540
  }
2420
2541
  catch (e) {
2421
- //await this.closeUnexpectedPopups();
2422
- this.logger.error("verify page path failed " + info.log);
2423
- ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
2424
- info.screenshotPath = screenshotPath;
2425
- Object.assign(e, { info: info });
2426
- error = e;
2427
- // throw e;
2428
- await _commandError({ text: "verifyPagePath", operation: "verifyPagePath", pathPart, info, throwError: true }, e, this);
2542
+ state.info.failCause.lastError = e.message;
2543
+ state.info.failCause.assertionFailed = true;
2544
+ await _commandError(state, e, this);
2429
2545
  }
2430
2546
  finally {
2431
- const endTime = Date.now();
2432
- _reportToWorld(world, {
2433
- type: Types.VERIFY_PAGE_PATH,
2434
- text: "Verify page path",
2435
- _text: "Verify the page path contains " + pathPart,
2436
- screenshotId,
2437
- result: error
2438
- ? {
2439
- status: "FAILED",
2440
- startTime,
2441
- endTime,
2442
- message: error?.message,
2443
- }
2444
- : {
2445
- status: "PASSED",
2446
- startTime,
2447
- endTime,
2448
- },
2449
- info: info,
2450
- });
2547
+ await _commandFinally(state, this);
2451
2548
  }
2452
2549
  }
2550
+ /**
2551
+ * Verify the page title matches the given title.
2552
+ * @param {string} title - The title to verify.
2553
+ * @param {object} options - Options for verification.
2554
+ * @param {object} world - The world context.
2555
+ * @returns {Promise<object>} - The state info after verification.
2556
+ */
2453
2557
  async verifyPageTitle(title, options = {}, world = null) {
2454
- const startTime = Date.now();
2455
2558
  let error = null;
2456
2559
  let screenshotId = null;
2457
2560
  let screenshotPath = null;
2458
2561
  await new Promise((resolve) => setTimeout(resolve, 2000));
2459
- const info = {};
2460
- info.log = "***** verify page title " + title + " *****\n";
2461
- info.operation = "verifyPageTitle";
2462
2562
  const newValue = await this._replaceWithLocalData(title, world);
2463
2563
  if (newValue !== title) {
2464
2564
  this.logger.info(title + "=" + newValue);
2465
2565
  title = newValue;
2466
2566
  }
2467
- info.title = title;
2567
+ const { matcher, queryText } = this._matcher(title);
2568
+ const state = {
2569
+ text_search: queryText,
2570
+ options,
2571
+ world,
2572
+ locate: false,
2573
+ scroll: false,
2574
+ highlight: false,
2575
+ type: Types.VERIFY_PAGE_TITLE,
2576
+ text: `Verify the page title is ${queryText}`,
2577
+ _text: `Verify the page title is ${queryText}`,
2578
+ operation: "verifyPageTitle",
2579
+ log: "***** verify page title is " + queryText + " *****\n",
2580
+ };
2468
2581
  try {
2582
+ await _preCommand(state, this);
2583
+ state.info.text = queryText;
2469
2584
  for (let i = 0; i < 30; i++) {
2470
2585
  const foundTitle = await this.page.title();
2471
- if (!foundTitle.includes(title)) {
2472
- if (i === 29) {
2473
- throw new Error(`url ${foundTitle} doesn't contain ${title}`);
2474
- }
2475
- await new Promise((resolve) => setTimeout(resolve, 1000));
2476
- continue;
2586
+ switch (matcher) {
2587
+ case "exact":
2588
+ if (foundTitle !== queryText) {
2589
+ if (i === 29) {
2590
+ throw new Error(`Page Title ${foundTitle} is not equal to ${queryText}`);
2591
+ }
2592
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2593
+ continue;
2594
+ }
2595
+ break;
2596
+ case "contains":
2597
+ if (!foundTitle.includes(queryText)) {
2598
+ if (i === 29) {
2599
+ throw new Error(`Page Title ${foundTitle} doesn't contain ${queryText}`);
2600
+ }
2601
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2602
+ continue;
2603
+ }
2604
+ break;
2605
+ case "starts-with":
2606
+ if (!foundTitle.startsWith(queryText)) {
2607
+ if (i === 29) {
2608
+ throw new Error(`Page title ${foundTitle} doesn't start with ${queryText}`);
2609
+ }
2610
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2611
+ continue;
2612
+ }
2613
+ break;
2614
+ case "ends-with":
2615
+ if (!foundTitle.endsWith(queryText)) {
2616
+ if (i === 29) {
2617
+ throw new Error(`Page Title ${foundTitle} doesn't end with ${queryText}`);
2618
+ }
2619
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2620
+ continue;
2621
+ }
2622
+ break;
2623
+ case "regex":
2624
+ const regex = new RegExp(queryText.slice(1, -1), "g");
2625
+ if (!regex.test(foundTitle)) {
2626
+ if (i === 29) {
2627
+ throw new Error(`Page Title ${foundTitle} doesn't match regex ${queryText}`);
2628
+ }
2629
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2630
+ continue;
2631
+ }
2632
+ break;
2633
+ default:
2634
+ console.log("Unknown matching type, defaulting to contains match");
2635
+ if (foundTitle !== queryText) {
2636
+ if (i === 29) {
2637
+ throw new Error(`Page Title ${foundTitle} does not contain ${queryText}`);
2638
+ }
2639
+ await new Promise((resolve) => setTimeout(resolve, 1000));
2640
+ continue;
2641
+ }
2477
2642
  }
2478
- ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
2479
- return info;
2643
+ await _screenshot(state, this);
2644
+ return state.info;
2480
2645
  }
2481
2646
  }
2482
2647
  catch (e) {
2483
- //await this.closeUnexpectedPopups();
2484
- this.logger.error("verify page title failed " + info.log);
2485
- ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
2486
- info.screenshotPath = screenshotPath;
2487
- Object.assign(e, { info: info });
2488
- error = e;
2489
- // throw e;
2490
- await _commandError({ text: "verifyPageTitle", operation: "verifyPageTitle", title, info, throwError: true }, e, this);
2648
+ state.info.failCause.lastError = e.message;
2649
+ state.info.failCause.assertionFailed = true;
2650
+ await _commandError(state, e, this);
2491
2651
  }
2492
2652
  finally {
2493
- const endTime = Date.now();
2494
- _reportToWorld(world, {
2495
- type: Types.VERIFY_PAGE_PATH,
2496
- text: "Verify page title",
2497
- _text: "Verify the page title contains " + title,
2498
- screenshotId,
2499
- result: error
2500
- ? {
2501
- status: "FAILED",
2502
- startTime,
2503
- endTime,
2504
- message: error?.message,
2505
- }
2506
- : {
2507
- status: "PASSED",
2508
- startTime,
2509
- endTime,
2510
- },
2511
- info: info,
2512
- });
2653
+ await _commandFinally(state, this);
2513
2654
  }
2514
2655
  }
2515
2656
  async findTextInAllFrames(dateAlternatives, numberAlternatives, text, state, partial = true, ignoreCase = false) {
@@ -2593,27 +2734,10 @@ class StableBrowser {
2593
2734
  const frame = resultWithElementsFound[0].frame;
2594
2735
  const dataAttribute = `[data-blinq-id-${resultWithElementsFound[0].randomToken}]`;
2595
2736
  await this._highlightElements(frame, dataAttribute);
2596
- // if (world && world.screenshot && !world.screenshotPath) {
2597
- // console.log(`Highlighting for verify text is found while running from recorder`);
2598
- // this._highlightElements(frame, dataAttribute).then(async () => {
2599
- // await new Promise((resolve) => setTimeout(resolve, 1000));
2600
- // this._unhighlightElements(frame, dataAttribute)
2601
- // .then(async () => {
2602
- // console.log(`Unhighlighted frame dataAttribute successfully`);
2603
- // })
2604
- // .catch(
2605
- // (e) => {}
2606
- // console.error(e)
2607
- // );
2608
- // });
2609
- // }
2610
2737
  const element = await frame.locator(dataAttribute).first();
2611
- // await new Promise((resolve) => setTimeout(resolve, 100));
2612
- // await this._unhighlightElements(frame, dataAttribute);
2613
2738
  if (element) {
2614
2739
  await this.scrollIfNeeded(element, state.info);
2615
2740
  await element.dispatchEvent("bvt_verify_page_contains_text");
2616
- // await _screenshot(state, this, element);
2617
2741
  }
2618
2742
  }
2619
2743
  await _screenshot(state, this);
@@ -2623,7 +2747,6 @@ class StableBrowser {
2623
2747
  console.error(error);
2624
2748
  }
2625
2749
  }
2626
- // await expect(element).toHaveCount(1, { timeout: 10000 });
2627
2750
  }
2628
2751
  catch (e) {
2629
2752
  await _commandError(state, e, this);