@dev-blinq/bvt-playwright-js 1.0.0-dev.4.latest.158.1 → 1.0.0-dev.4.latest.172.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/index.d.mts CHANGED
@@ -277,6 +277,7 @@ declare const elementAssertionSchema: z.ZodDiscriminatedUnion<[
277
277
  type: z.ZodLiteral<"toHaveProperty">;
278
278
  name: z.ZodString;
279
279
  operator: z.ZodOptional<z.ZodEnum<{
280
+ regex: "regex";
280
281
  equals: "equals";
281
282
  notEquals: "notEquals";
282
283
  contains: "contains";
@@ -2021,6 +2022,7 @@ declare const CommandSchema: z.ZodDiscriminatedUnion<[
2021
2022
  type: z.ZodLiteral<"toHaveProperty">;
2022
2023
  name: z.ZodString;
2023
2024
  operator: z.ZodOptional<z.ZodEnum<{
2025
+ regex: "regex";
2024
2026
  equals: "equals";
2025
2027
  notEquals: "notEquals";
2026
2028
  contains: "contains";
@@ -5031,6 +5033,7 @@ declare const StepDefinitionSchema: z.ZodObject<{
5031
5033
  type: z.ZodLiteral<"toHaveProperty">;
5032
5034
  name: z.ZodString;
5033
5035
  operator: z.ZodOptional<z.ZodEnum<{
5036
+ regex: "regex";
5034
5037
  equals: "equals";
5035
5038
  notEquals: "notEquals";
5036
5039
  contains: "contains";
@@ -9323,6 +9326,7 @@ type ExecuteStepsOptions = {
9323
9326
  onFinish?: () => Promise<void>;
9324
9327
  onError?: (error: Error) => Promise<void>;
9325
9328
  abortController?: AbortController;
9329
+ recoveryAbortController?: AbortController;
9326
9330
  };
9327
9331
  type GetAPIClient = (sessionToken: string) => TesterApiClient;
9328
9332
  declare class Tester {
package/index.mjs CHANGED
@@ -5170,7 +5170,8 @@ const ASSERTION_OPERATORS = [
5170
5170
  "contains",
5171
5171
  "lessThan",
5172
5172
  "greaterThan",
5173
- "exists"
5173
+ "exists",
5174
+ "regex"
5174
5175
  ];
5175
5176
 
5176
5177
  //#endregion
@@ -10936,6 +10937,7 @@ const AiChatDataExecutionStatusPartSchema = object({
10936
10937
  * from the call sites in `apps/ai-server/src/mastra/agents/`:
10937
10938
  * - `observe-act-loop` (observe-act-completion happy path)
10938
10939
  * - `observe-act-loop-cap-reached` (loop hit iteration cap mid-run)
10940
+ * - `form-fill-batch` (on-mode form-fill fast-path success)
10939
10941
  * - `segment-followup` (apps/ai-server/src/trpc/router.ts segment-followup path)
10940
10942
  * Plus the AiStepDraftMode values used by client-side fixtures that did not
10941
10943
  * originate from the observe-act loop (legacy: `new-ai-step`, `edit-ai-step`).
@@ -10946,6 +10948,7 @@ const AiChatDataExecutionStatusPartSchema = object({
10946
10948
  const AiChatDataCompleteModeSchema = _enum([
10947
10949
  "observe-act-loop",
10948
10950
  "observe-act-loop-cap-reached",
10951
+ "form-fill-batch",
10949
10952
  "segment-followup",
10950
10953
  "new-ai-step",
10951
10954
  "edit-ai-step"
@@ -26320,6 +26323,9 @@ const NEW_TOUR_MAINTENANCE_RECOVERY_ARTIFACT = {
26320
26323
  aiLog: "BlinqIO matched the original gender-selection intent to the new radio button UI and rewrote the stale command.",
26321
26324
  description: "The repaired step selects the gender radio option, then continues the registration flow successfully."
26322
26325
  };
26326
+ function isAbortError(error) {
26327
+ return error instanceof Error && error.name === "AbortError";
26328
+ }
26323
26329
  const unconfiguredGetAPIClient = () => {
26324
26330
  throw new Error("Tester was created without an API client.");
26325
26331
  };
@@ -27275,7 +27281,21 @@ var Tester = class {
27275
27281
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
27276
27282
  };
27277
27283
  const failureContext = this.buildFailureContext(command, recorderStep, stepDefinitionId, commandIndex, commandContext, executionError);
27278
- const recoveryResult = await this.recoveryController.analyzeAndPropose(failureContext);
27284
+ const recoveryContext = {
27285
+ ...failureContext,
27286
+ abortSignal: options.recoveryAbortController?.signal ?? failureContext.abortSignal
27287
+ };
27288
+ let recoveryResult;
27289
+ try {
27290
+ recoveryResult = await this.recoveryController.analyzeAndPropose(recoveryContext);
27291
+ } catch (recoveryError) {
27292
+ if (isAbortError(recoveryError)) {
27293
+ this.obs.logger.log("AI recovery cancelled; preserving original command failure", { commandId: command._id });
27294
+ yield await this.onCommandFail(command, stepDefinitionId, executionError, session);
27295
+ throw executionError;
27296
+ }
27297
+ throw recoveryError;
27298
+ }
27279
27299
  const { decision } = recoveryResult;
27280
27300
  let artifact = recoveryResult.artifact;
27281
27301
  if (this.shouldAttemptAiRecovery(session)) {
@@ -27344,7 +27364,7 @@ var Tester = class {
27344
27364
  if (!persistResult.success) throw new Error(persistResult.error);
27345
27365
  artifact = await this.generateRecoveryArtifactForOutcome({
27346
27366
  decision,
27347
- failureContext,
27367
+ failureContext: recoveryContext,
27348
27368
  recoverySucceeded: true,
27349
27369
  stoppedReason: "accept-repair",
27350
27370
  attemptLog: this.buildStepRepairAttemptLog(decision, "succeeded")
@@ -27403,7 +27423,7 @@ var Tester = class {
27403
27423
  });
27404
27424
  artifact = await this.generateRecoveryArtifactForOutcome({
27405
27425
  decision,
27406
- failureContext,
27426
+ failureContext: recoveryContext,
27407
27427
  recoverySucceeded: false,
27408
27428
  stoppedReason: "retry_failed",
27409
27429
  attemptLog: this.buildStepRepairAttemptLog(decision, "failed")
@@ -27424,7 +27444,7 @@ var Tester = class {
27424
27444
  terminalExecutionError = /* @__PURE__ */ new Error(`${decision.userFacingMessages.failed}. Repair application failure: ${appliedRepair.error}. Original failure: ${executionError.message}`);
27425
27445
  artifact = await this.generateRecoveryArtifactForOutcome({
27426
27446
  decision,
27427
- failureContext,
27447
+ failureContext: recoveryContext,
27428
27448
  recoverySucceeded: false,
27429
27449
  stoppedReason: "repair_application_failed",
27430
27450
  attemptLog: this.buildStepRepairAttemptLog(decision, "failed")
@@ -27485,7 +27505,7 @@ var Tester = class {
27485
27505
  if (!persistResult.success) throw new Error(persistResult.error);
27486
27506
  artifact = await this.generateRecoveryArtifactForOutcome({
27487
27507
  decision,
27488
- failureContext,
27508
+ failureContext: recoveryContext,
27489
27509
  recoverySucceeded: true,
27490
27510
  stoppedReason: "accept-repair",
27491
27511
  attemptLog: this.buildStepRepairAttemptLog(decision, "succeeded")
@@ -27545,7 +27565,7 @@ var Tester = class {
27545
27565
  });
27546
27566
  artifact = await this.generateRecoveryArtifactForOutcome({
27547
27567
  decision,
27548
- failureContext,
27568
+ failureContext: recoveryContext,
27549
27569
  recoverySucceeded: false,
27550
27570
  stoppedReason: "retry_failed",
27551
27571
  attemptLog: this.buildStepRepairAttemptLog(decision, "failed")
@@ -27565,7 +27585,7 @@ var Tester = class {
27565
27585
  else {
27566
27586
  artifact = await this.generateRecoveryArtifactForOutcome({
27567
27587
  decision,
27568
- failureContext,
27588
+ failureContext: recoveryContext,
27569
27589
  recoverySucceeded: false,
27570
27590
  stoppedReason: "repair_application_failed",
27571
27591
  attemptLog: this.buildStepRepairAttemptLog(decision, "failed")
@@ -27978,6 +27998,33 @@ var Tester = class {
27978
27998
  if (!(actual > threshold)) throw new Error(`Property "${assertion.name}" expected to be greater than ${threshold}, but got ${actual}`);
27979
27999
  }
27980
28000
  break;
28001
+ case "regex":
28002
+ if (assertion.value !== void 0) {
28003
+ const raw = getValueFromPrimitiveOrRegex(assertion.value);
28004
+ const pattern = raw instanceof RegExp ? raw : new RegExp(String(raw));
28005
+ this.obs.logger.info(`Expected property "${assertion.name}" to match pattern: ${pattern}`);
28006
+ const propName = assertion.name;
28007
+ const isTextProp = propName === "textContent" || propName === "innerText";
28008
+ const isHtmlAttr = [
28009
+ "href",
28010
+ "src",
28011
+ "class",
28012
+ "id",
28013
+ "placeholder",
28014
+ "title",
28015
+ "alt",
28016
+ "name",
28017
+ "type",
28018
+ "action",
28019
+ "target",
28020
+ "rel",
28021
+ "value"
28022
+ ].includes(propName) || propName.startsWith("data-") || propName.startsWith("aria-");
28023
+ if (isTextProp) await expect(locator).toHaveText(pattern, assertion.options);
28024
+ else if (isHtmlAttr) await expect(locator).toHaveAttribute(propName, pattern, assertion.options);
28025
+ else await expect.poll(async () => locator.evaluate((el, name) => String(el[name] ?? ""), propName), { timeout: assertion.options?.timeout }).toMatch(pattern);
28026
+ }
28027
+ break;
27981
28028
  case "exists": {
27982
28029
  const exists = await locator.evaluate((el, name) => el[name] !== void 0, assertion.name);
27983
28030
  this.obs.logger.info(`Expected property "${assertion.name}" to exist: ${exists}`);
@@ -28033,7 +28080,9 @@ var Tester = class {
28033
28080
  const frame = await this.getFrameObjectFromFrameScope(frameScope);
28034
28081
  this.obs.logger.info(`Checking for absence of element with text ${value} using "${locator.first()?._selector}" `);
28035
28082
  this.obs.logger.info(`Waiting for page to load and stabilize before checking for absence of text to reduce flakiness...`);
28036
- await frame.waitForLoadState("networkidle", { timeout: 3e4 });
28083
+ await frame.waitForLoadState("networkidle", { timeout: 3e4 }).catch((error) => {
28084
+ this.obs.logger.error(`Frame load timeout, the page may not be in the desired state yet`, error);
28085
+ });
28037
28086
  this.obs.logger.info(`frame load detected. Waiting an additional 500ms for stabilization...`);
28038
28087
  await frame.waitForTimeout(500);
28039
28088
  this.obs.logger.info(`Checking for element with text "${value}" after page load and stabilization delay...`);