@cqa-lib/cqa-ui 1.1.269 → 1.1.270

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.
@@ -9161,6 +9161,7 @@ class BasicStepComponent extends BaseStepComponent {
9161
9161
  remainingSeconds: timeoutSeconds,
9162
9162
  status: 'running'
9163
9163
  };
9164
+ this.addDurationToWaitLocatorGroupEntry(subStep);
9164
9165
  this.processedSubSteps.push(this.waitLocatorGroupEntry);
9165
9166
  // Tick down every second
9166
9167
  this.countdownIntervalId = setInterval(() => {
@@ -9190,6 +9191,7 @@ class BasicStepComponent extends BaseStepComponent {
9190
9191
  const newText = subStep.description || subStep.text || subStep.title;
9191
9192
  if (newText)
9192
9193
  this.waitLocatorGroupEntry.description = newText;
9194
+ this.addDurationToWaitLocatorGroupEntry(subStep);
9193
9195
  }
9194
9196
  else {
9195
9197
  // No active group – push FIND_LOCATOR normally once countdown is cleared
@@ -9213,6 +9215,7 @@ class BasicStepComponent extends BaseStepComponent {
9213
9215
  if (newText)
9214
9216
  this.waitLocatorGroupEntry.description = newText;
9215
9217
  this.waitLocatorGroupEntry.status = 'success';
9218
+ this.addDurationToWaitLocatorGroupEntry(subStep);
9216
9219
  this.waitLocatorGroupEntry.remainingSeconds = null;
9217
9220
  this.clearCountdownTimer();
9218
9221
  this.waitLocatorGroupEntry = null;
@@ -9314,6 +9317,33 @@ class BasicStepComponent extends BaseStepComponent {
9314
9317
  this.countdownIntervalId = null;
9315
9318
  }
9316
9319
  }
9320
+ addDurationToWaitLocatorGroupEntry(subStep) {
9321
+ if (!this.waitLocatorGroupEntry) {
9322
+ return;
9323
+ }
9324
+ const rawDuration = subStep?.duration;
9325
+ let delta = 0;
9326
+ if (typeof rawDuration === 'number') {
9327
+ delta = rawDuration;
9328
+ }
9329
+ else if (typeof rawDuration === 'string' && rawDuration.trim() !== '') {
9330
+ const parsed = parseFloat(rawDuration);
9331
+ delta = Number.isFinite(parsed) ? parsed : 0;
9332
+ }
9333
+ if (delta <= 0) {
9334
+ return;
9335
+ }
9336
+ const currentRaw = this.waitLocatorGroupEntry.duration;
9337
+ let current = 0;
9338
+ if (typeof currentRaw === 'number') {
9339
+ current = currentRaw;
9340
+ }
9341
+ else if (typeof currentRaw === 'string' && currentRaw.trim() !== '') {
9342
+ const parsedCurrent = parseFloat(currentRaw);
9343
+ current = Number.isFinite(parsedCurrent) ? parsedCurrent : 0;
9344
+ }
9345
+ this.waitLocatorGroupEntry.duration = current + delta;
9346
+ }
9317
9347
  processSubStepsForRunResult() {
9318
9348
  const allSubSteps = (this.subSteps || []);
9319
9349
  this.processedSubStepsForRunResult = [];
@@ -10787,6 +10817,7 @@ class LoopStepComponent extends BaseStepComponent {
10787
10817
  remainingSeconds: timeoutSeconds,
10788
10818
  status: 'running'
10789
10819
  };
10820
+ this.addDurationToWaitLocatorGroupEntry(subStep);
10790
10821
  this.processedSubSteps.push(this.waitLocatorGroupEntry);
10791
10822
  // Tick down every second
10792
10823
  this.countdownIntervalId = setInterval(() => {
@@ -10816,6 +10847,7 @@ class LoopStepComponent extends BaseStepComponent {
10816
10847
  const newText = subStep.description || subStep.text || subStep.title;
10817
10848
  if (newText)
10818
10849
  this.waitLocatorGroupEntry.description = newText;
10850
+ this.addDurationToWaitLocatorGroupEntry(subStep);
10819
10851
  }
10820
10852
  else {
10821
10853
  // No active group – push FIND_LOCATOR normally once countdown is cleared
@@ -10839,6 +10871,7 @@ class LoopStepComponent extends BaseStepComponent {
10839
10871
  if (newText)
10840
10872
  this.waitLocatorGroupEntry.description = newText;
10841
10873
  this.waitLocatorGroupEntry.status = 'success';
10874
+ this.addDurationToWaitLocatorGroupEntry(subStep);
10842
10875
  this.waitLocatorGroupEntry.remainingSeconds = null;
10843
10876
  this.clearCountdownTimer();
10844
10877
  this.waitLocatorGroupEntry = null;
@@ -10940,6 +10973,33 @@ class LoopStepComponent extends BaseStepComponent {
10940
10973
  this.countdownIntervalId = null;
10941
10974
  }
10942
10975
  }
10976
+ addDurationToWaitLocatorGroupEntry(subStep) {
10977
+ if (!this.waitLocatorGroupEntry) {
10978
+ return;
10979
+ }
10980
+ const rawDuration = subStep?.duration;
10981
+ let delta = 0;
10982
+ if (typeof rawDuration === 'number') {
10983
+ delta = rawDuration;
10984
+ }
10985
+ else if (typeof rawDuration === 'string' && rawDuration.trim() !== '') {
10986
+ const parsed = parseFloat(rawDuration);
10987
+ delta = Number.isFinite(parsed) ? parsed : 0;
10988
+ }
10989
+ if (delta <= 0) {
10990
+ return;
10991
+ }
10992
+ const currentRaw = this.waitLocatorGroupEntry.duration;
10993
+ let current = 0;
10994
+ if (typeof currentRaw === 'number') {
10995
+ current = currentRaw;
10996
+ }
10997
+ else if (typeof currentRaw === 'string' && currentRaw.trim() !== '') {
10998
+ const parsedCurrent = parseFloat(currentRaw);
10999
+ current = Number.isFinite(parsedCurrent) ? parsedCurrent : 0;
11000
+ }
11001
+ this.waitLocatorGroupEntry.duration = current + delta;
11002
+ }
10943
11003
  processSubStepsForRunResult() {
10944
11004
  if (!this.selectedIteration || !this.selectedIteration.subSteps) {
10945
11005
  this.processedSubStepsForRunResult = [];
@@ -13005,6 +13065,7 @@ class ApiStepComponent extends BaseStepComponent {
13005
13065
  remainingSeconds: timeoutSeconds,
13006
13066
  status: 'running'
13007
13067
  };
13068
+ this.addDurationToWaitLocatorGroupEntry(action);
13008
13069
  this.processedInitialActions.push(this.waitLocatorGroupEntry);
13009
13070
  // Tick down every second
13010
13071
  this.countdownIntervalId = setInterval(() => {
@@ -13034,6 +13095,7 @@ class ApiStepComponent extends BaseStepComponent {
13034
13095
  const newText = action.description || action.text || action.title;
13035
13096
  if (newText)
13036
13097
  this.waitLocatorGroupEntry.description = newText;
13098
+ this.addDurationToWaitLocatorGroupEntry(action);
13037
13099
  }
13038
13100
  else {
13039
13101
  // No active group – push FIND_LOCATOR normally once countdown is cleared
@@ -13057,6 +13119,7 @@ class ApiStepComponent extends BaseStepComponent {
13057
13119
  if (newText)
13058
13120
  this.waitLocatorGroupEntry.description = newText;
13059
13121
  this.waitLocatorGroupEntry.status = 'success';
13122
+ this.addDurationToWaitLocatorGroupEntry(action);
13060
13123
  this.waitLocatorGroupEntry.remainingSeconds = null;
13061
13124
  this.clearCountdownTimer();
13062
13125
  this.waitLocatorGroupEntry = null;
@@ -13158,6 +13221,33 @@ class ApiStepComponent extends BaseStepComponent {
13158
13221
  this.countdownIntervalId = null;
13159
13222
  }
13160
13223
  }
13224
+ addDurationToWaitLocatorGroupEntry(action) {
13225
+ if (!this.waitLocatorGroupEntry) {
13226
+ return;
13227
+ }
13228
+ const rawDuration = action?.duration;
13229
+ let delta = 0;
13230
+ if (typeof rawDuration === 'number') {
13231
+ delta = rawDuration;
13232
+ }
13233
+ else if (typeof rawDuration === 'string' && rawDuration.trim() !== '') {
13234
+ const parsed = parseFloat(rawDuration);
13235
+ delta = Number.isFinite(parsed) ? parsed : 0;
13236
+ }
13237
+ if (delta <= 0) {
13238
+ return;
13239
+ }
13240
+ const currentRaw = this.waitLocatorGroupEntry.duration;
13241
+ let current = 0;
13242
+ if (typeof currentRaw === 'number') {
13243
+ current = currentRaw;
13244
+ }
13245
+ else if (typeof currentRaw === 'string' && currentRaw.trim() !== '') {
13246
+ const parsedCurrent = parseFloat(currentRaw);
13247
+ current = Number.isFinite(parsedCurrent) ? parsedCurrent : 0;
13248
+ }
13249
+ this.waitLocatorGroupEntry.duration = current + delta;
13250
+ }
13161
13251
  onJumpToTimestamp(event) {
13162
13252
  event.stopPropagation();
13163
13253
  if (this.jumpToTimestampHandler && this.step?.executedResult?.video_start_time !== undefined && this.step?.executedResult?.video_start_time !== null) {
@@ -13822,6 +13912,7 @@ class LiveExecutionStepComponent extends BaseStepComponent {
13822
13912
  remainingSeconds: timeoutSeconds,
13823
13913
  status: 'pending'
13824
13914
  };
13915
+ this.addDurationToWaitLocatorGroupEntry(subStep);
13825
13916
  this.processedSubSteps.push(this.waitLocatorGroupEntry);
13826
13917
  // Tick down every second
13827
13918
  this.countdownIntervalId = setInterval(() => {
@@ -13852,6 +13943,7 @@ class LiveExecutionStepComponent extends BaseStepComponent {
13852
13943
  const newText = subStep.text || subStep.description || subStep.title;
13853
13944
  if (newText)
13854
13945
  this.waitLocatorGroupEntry.text = newText;
13946
+ this.addDurationToWaitLocatorGroupEntry(subStep);
13855
13947
  }
13856
13948
  else {
13857
13949
  // No active group – push FIND_LOCATOR normally once countdown is cleared
@@ -13876,6 +13968,7 @@ class LiveExecutionStepComponent extends BaseStepComponent {
13876
13968
  this.waitLocatorGroupEntry.text = newText;
13877
13969
  this.waitLocatorGroupEntry.isRunning = false;
13878
13970
  this.waitLocatorGroupEntry.status = 'success';
13971
+ this.addDurationToWaitLocatorGroupEntry(subStep);
13879
13972
  this.waitLocatorGroupEntry.remainingSeconds = null;
13880
13973
  this.clearCountdownTimer();
13881
13974
  this.waitLocatorGroupEntry = null;
@@ -13985,6 +14078,33 @@ class LiveExecutionStepComponent extends BaseStepComponent {
13985
14078
  this.countdownIntervalId = null;
13986
14079
  }
13987
14080
  }
14081
+ addDurationToWaitLocatorGroupEntry(subStep) {
14082
+ if (!this.waitLocatorGroupEntry) {
14083
+ return;
14084
+ }
14085
+ const rawDuration = subStep?.duration;
14086
+ let delta = 0;
14087
+ if (typeof rawDuration === 'number') {
14088
+ delta = rawDuration;
14089
+ }
14090
+ else if (typeof rawDuration === 'string' && rawDuration.trim() !== '') {
14091
+ const parsed = parseFloat(rawDuration);
14092
+ delta = Number.isFinite(parsed) ? parsed : 0;
14093
+ }
14094
+ if (delta <= 0) {
14095
+ return;
14096
+ }
14097
+ const currentRaw = this.waitLocatorGroupEntry.duration;
14098
+ let current = 0;
14099
+ if (typeof currentRaw === 'number') {
14100
+ current = currentRaw;
14101
+ }
14102
+ else if (typeof currentRaw === 'string' && currentRaw.trim() !== '') {
14103
+ const parsedCurrent = parseFloat(currentRaw);
14104
+ current = Number.isFinite(parsedCurrent) ? parsedCurrent : 0;
14105
+ }
14106
+ this.waitLocatorGroupEntry.duration = current + delta;
14107
+ }
13988
14108
  }
13989
14109
  LiveExecutionStepComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: LiveExecutionStepComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
13990
14110
  LiveExecutionStepComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: LiveExecutionStepComponent, selector: "cqa-live-execution-step", inputs: { id: "id", testStepResultId: "testStepResultId", stepNumber: "stepNumber", title: "title", status: "status", isDebug: "isDebug", debugPointSet: "debugPointSet", addStepMenuOptions: "addStepMenuOptions", stepMoreMenuOptions: "stepMoreMenuOptions", duration: "duration", expanded: "expanded", subSteps: "subSteps", stepDeleted: "stepDeleted" }, outputs: { debugPointChange: "debugPointChange", editStep: "editStep", addStepOptionSelect: "addStepOptionSelect", stepMoreOptionSelect: "stepMoreOptionSelect" }, host: { classAttribute: "cqa-ui-root cqa-w-full" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-font-inter cqa-w-full\">\n <!-- Header -->\n <div\n class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-p-2 cqa-cursor-pointer\"\n (click)=\"toggle()\"\n style=\"border-bottom: '1px solid #F3F4F6'\"\n >\n <div *ngIf=\"showDebugIcon\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <button type=\"button\" class=\"cqa-p-0 cqa-border-0 cqa-bg-transparent cqa-cursor-pointer cqa-rounded-full hover:cqa-opacity-80 cqa-transition-opacity focus:cqa-outline-none\" (click)=\"onDebugPointClick($event)\" [attr.aria-label]=\"debugPointSet ? 'Remove debug point' : 'Set debug point'\">\n <svg *ngIf=\"debugPointSet\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"7\" cy=\"7\" r=\"6\" fill=\"#C63535\"/>\n </svg>\n <svg *ngIf=\"!debugPointSet\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"7\" cy=\"7\" r=\"6\" stroke=\"#C63535\" stroke-width=\"1.5\" fill=\"none\"/>\n </svg>\n </button>\n </div>\n <!-- Status Icon -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <!-- Success -->\n <svg *ngIf=\"status.toLowerCase() === 'success'\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10.9005 4.99999C11.1289 6.12064 10.9662 7.28571 10.4395 8.30089C9.91279 9.31608 9.054 10.12 8.00631 10.5787C6.95862 11.0373 5.78536 11.1229 4.6822 10.8212C3.57904 10.5195 2.61265 9.84869 1.94419 8.92071C1.27573 7.99272 0.945611 6.86361 1.00888 5.72169C1.07215 4.57976 1.52499 3.49404 2.29188 2.64558C3.05876 1.79712 4.09334 1.23721 5.22308 1.05922C6.35282 0.881233 7.50944 1.09592 8.50005 1.66749\" stroke=\"#22C55E\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.5 5.5L6 7L11 2\" stroke=\"#22C55E\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <!-- Failed -->\n <svg *ngIf=\"status.toLowerCase() === 'failure' || status.toLowerCase() === 'failed'\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11Z\" stroke=\"#EF4444\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4 4L8 8M8 4L4 8\" stroke=\"#EF4444\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <!-- Pending -->\n <svg *ngIf=\"status.toLowerCase() === 'pending'\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11Z\" stroke=\"#9CA3AF\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M6 3V6L8 7\" stroke=\"#9CA3AF\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <!-- Running - Show spinner -->\n <svg *ngIf=\"status.toLowerCase() === 'running'\" class=\"cqa-animate-spin cqa-text-[#3B82F6]\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"5\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" opacity=\"0.25\"/>\n <path d=\"M6 1A5 5 0 0 1 11 6\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>\n </svg>\n <!-- Skipped -->\n <span *ngIf=\"status.toLowerCase() === 'skipped'\" class=\"material-symbols-outlined cqa-text-[#9CA3AF] cqa-text-[12px]\">\n skip_next\n </span>\n </div>\n\n <!-- Step Number and Title -->\n <div class=\"cqa-font-semibold cqa-flex-1 cqa-text-[#334155] cqa-text-[14px] cqa-leading-[18px] cqa-font-inter cqa-flex cqa-items-center cqa-gap-1\" style=\"word-break: break-word;\">\n <span>{{ stepNumber }}. <span [innerHTML]=\"title\"></span></span>\n <span *ngIf=\"config.stepDeleted\" class=\"cqa-px-1.5 cqa-py-[2px] cqa-rounded-[4px] cqa-text-[10px] cqa-leading-[12px] cqa-font-medium cqa-text-[#B42318] cqa-bg-[#FEF3F2] cqa-border cqa-border-[#FEE4E2]\">\n Deleted\n </span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1 cqa-font-inter\">\n <div *ngIf=\"isDebug\" class=\"cqa-flex cqa-items-center cqa-gap-0.5 cqa-text-[#9CA3AF]\" (click)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"cqa-p-0 cqa-border-0 cqa-bg-transparent cqa-cursor-pointer hover:cqa-opacity-80 cqa-transition-opacity focus:cqa-outline-none\" aria-label=\"Edit\" (click)=\"onEditStep($event)\">\n <mat-icon class=\"!cqa-text-[14px] !cqa-w-[14px] !cqa-h-[14px]\">edit</mat-icon>\n </button>\n <button type=\"button\" class=\"cqa-p-0 cqa-border-0 cqa-bg-transparent cqa-cursor-pointer hover:cqa-opacity-80 cqa-transition-opacity focus:cqa-outline-none\" aria-label=\"Add\" [matMenuTriggerFor]=\"addStepMenu\">\n <mat-icon class=\"!cqa-text-[14px] !cqa-w-[14px] !cqa-h-[14px]\">add</mat-icon>\n </button>\n <mat-menu #addStepMenu=\"matMenu\" class=\"cqa-add-step-menu\" xPosition=\"before\" yPosition=\"below\">\n <button mat-menu-item *ngFor=\"let opt of addStepMenuOptions\" (click)=\"onAddStepOptionSelect(opt, $event)\">{{ opt.label }}</button>\n </mat-menu>\n <button type=\"button\" class=\"cqa-p-0 cqa-border-0 cqa-bg-transparent cqa-cursor-pointer hover:cqa-opacity-80 cqa-transition-opacity focus:cqa-outline-none\" aria-label=\"More options\" [matMenuTriggerFor]=\"stepMoreMenu\">\n <mat-icon class=\"!cqa-text-[14px] !cqa-w-[14px] !cqa-h-[14px]\">more_vert</mat-icon>\n </button>\n <mat-menu #stepMoreMenu=\"matMenu\" class=\"cqa-step-more-menu\" xPosition=\"before\" yPosition=\"below\">\n <button mat-menu-item *ngFor=\"let opt of stepMoreMenuOptions\" (click)=\"onStepMoreOptionSelect(opt, $event)\">{{ opt.label }}</button>\n </mat-menu>\n </div>\n <span class=\"cqa-text-[12px] cqa-leading-[15px] cqa-text-[#9CA3AF] cqa-font-medium\">\n {{ formatDuration(duration) }}\n </span>\n <svg *ngIf=\"hasSubSteps\" [class.cqa-rotate-180]=\"isExpanded\" class=\"cqa-transition-transform\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3.5 5L7 8.5L10.5 5\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </div>\n </div>\n\n <!-- Expanded Content -->\n <div *ngIf=\"isExpanded && hasSubSteps\">\n <!-- Sub-steps -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-pt-1 cqa-pl-9\">\n <!-- Single loop: render all entries in chronological order -->\n <ng-container *ngFor=\"let subStep of processedSubSteps; trackBy: trackBySubStepId\">\n <!-- AI_AUTO_HEAL result entries: render with ai-agent-step style -->\n <cqa-ai-logs-with-reasoning\n *ngIf=\"subStep.isAiAutoHealResult\"\n [status]=\"subStep.status\"\n [text]=\"subStep.text\"\n [description]=\"subStep.description\"\n [reasoning]=\"subStep.reasoning\"\n [duration]=\"subStep.duration\">\n </cqa-ai-logs-with-reasoning>\n\n <!-- Regular sub-steps (non-AI_AUTO_HEAL) -->\n <div\n *ngIf=\"!subStep.isAiAutoHealResult\"\n class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-py-[5.5px] cqa-px-3\">\n \n <!-- Sub-step Status Icon or Loader -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-3 cqa-h-3\">\n <!-- Loader when running -->\n <svg *ngIf=\"subStep.isRunning\" class=\"cqa-animate-spin cqa-text-[#3B82F6]\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"5\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" opacity=\"0.25\"/>\n <path d=\"M6 1A5 5 0 0 1 11 6\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>\n </svg>\n \n <!-- Success Icon when complete -->\n <svg *ngIf=\"!subStep.isRunning && (subStep?.status?.toLowerCase() === 'passed' || subStep?.status?.toLowerCase() === 'success')\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11Z\" stroke=\"#00A63E\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M4.5 6L5.5 7L7.5 5\" stroke=\"#00A63E\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <svg *ngIf=\"!subStep.isRunning && subStep?.status?.toLowerCase() === 'failed'\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11Z\" stroke=\"#EF4444\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4 4L8 8M8 4L4 8\" stroke=\"#EF4444\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <!-- Sub-step Description (text from socket) with typing animation -->\n <span class=\"cqa-flex-1 cqa-text-[13px] cqa-leading-[15px] cqa-text-[#364153]\" style=\"word-break: break-word;\">\n <span style=\"display: inline-flex; align-items: baseline; flex-wrap: wrap;\">\n <ngx-typed-js \n *ngIf=\"subStep.isRunning && subStep.text\"\n [strings]=\"[subStep.text]\"\n [typeSpeed]=\"30\"\n [showCursor]=\"false\"\n [fadeOut]=\"false\"\n style=\"display: inline;\">\n <span class=\"typing\"></span>\n </ngx-typed-js>\n <span *ngIf=\"!subStep.isRunning\" style=\"display: inline;\">{{ subStep.text }}</span>\n <!-- Countdown remaining for WAIT_FOR_LOCATOR group -->\n <span *ngIf=\"subStep.remainingSeconds != null\" class=\"cqa-text-[#F97316] cqa-font-medium cqa-ml-1\" style=\"display: inline;\">({{ subStep.remainingSeconds }}s remaining)</span>\n </span>\n </span>\n <span class=\"cqa-text-[10px] cqa-leading-[15px] cqa-text-[#6A7282] cqa-font-medium\" style=\"white-space: pre-line;\">\n {{ formatDuration(subStep.duration || 0) }}\n </span>\n </div>\n </ng-container>\n </div>\n </div>\n</div>\n\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: i2$1.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { type: i2$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { type: AiLogsWithReasoningComponent, selector: "cqa-ai-logs-with-reasoning", inputs: ["status", "text", "description", "reasoning", "duration"] }, { type: i4$1.NgxTypedJsComponent, selector: "ngx-typed-js", inputs: ["cursorColor", "strings", "stringsElement", "typeSpeed", "startDelay", "backSpeed", "smartBackspace", "shuffle", "backDelay", "fadeOut", "fadeOutClass", "fadeOutDelay", "loop", "loopCount", "showCursor", "cursorChar", "autoInsertCss", "attr", "bindInputFocusEvents", "contentType"], outputs: ["completed", "preStringTyped", "stringTyped", "lastStringBackspaced", "typingPaused", "typingResumed", "reset", "stopped", "started", "destroyed"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
@@ -18682,6 +18802,7 @@ class DbVerificationStepComponent extends BaseStepComponent {
18682
18802
  remainingSeconds: timeoutSeconds,
18683
18803
  status: 'running'
18684
18804
  };
18805
+ this.addDurationToWaitLocatorGroupEntry(subStep);
18685
18806
  this.processedSubSteps.push(this.waitLocatorGroupEntry);
18686
18807
  this.countdownIntervalId = setInterval(() => {
18687
18808
  if (this.waitLocatorGroupEntry) {
@@ -18708,6 +18829,7 @@ class DbVerificationStepComponent extends BaseStepComponent {
18708
18829
  const newText = subStep.description || subStep.text || subStep.title;
18709
18830
  if (newText)
18710
18831
  this.waitLocatorGroupEntry.description = newText;
18832
+ this.addDurationToWaitLocatorGroupEntry(subStep);
18711
18833
  }
18712
18834
  else {
18713
18835
  this.processedSubSteps.push({ ...subStep });
@@ -18728,6 +18850,7 @@ class DbVerificationStepComponent extends BaseStepComponent {
18728
18850
  if (newText)
18729
18851
  this.waitLocatorGroupEntry.description = newText;
18730
18852
  this.waitLocatorGroupEntry.status = 'success';
18853
+ this.addDurationToWaitLocatorGroupEntry(subStep);
18731
18854
  this.waitLocatorGroupEntry.remainingSeconds = null;
18732
18855
  this.clearCountdownTimer();
18733
18856
  this.waitLocatorGroupEntry = null;
@@ -18821,6 +18944,33 @@ class DbVerificationStepComponent extends BaseStepComponent {
18821
18944
  this.countdownIntervalId = null;
18822
18945
  }
18823
18946
  }
18947
+ addDurationToWaitLocatorGroupEntry(subStep) {
18948
+ if (!this.waitLocatorGroupEntry) {
18949
+ return;
18950
+ }
18951
+ const rawDuration = subStep?.duration;
18952
+ let delta = 0;
18953
+ if (typeof rawDuration === 'number') {
18954
+ delta = rawDuration;
18955
+ }
18956
+ else if (typeof rawDuration === 'string' && rawDuration.trim() !== '') {
18957
+ const parsed = parseFloat(rawDuration);
18958
+ delta = Number.isFinite(parsed) ? parsed : 0;
18959
+ }
18960
+ if (delta <= 0) {
18961
+ return;
18962
+ }
18963
+ const currentRaw = this.waitLocatorGroupEntry.duration;
18964
+ let current = 0;
18965
+ if (typeof currentRaw === 'number') {
18966
+ current = currentRaw;
18967
+ }
18968
+ else if (typeof currentRaw === 'string' && currentRaw.trim() !== '') {
18969
+ const parsedCurrent = parseFloat(currentRaw);
18970
+ current = Number.isFinite(parsedCurrent) ? parsedCurrent : 0;
18971
+ }
18972
+ this.waitLocatorGroupEntry.duration = current + delta;
18973
+ }
18824
18974
  processSubStepsForRunResult() {
18825
18975
  const allSubSteps = (this.subSteps || []);
18826
18976
  this.processedSubStepsForRunResult = [];