@cqa-lib/cqa-ui 1.1.395 → 1.1.397
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/esm2020/lib/execution-screen/step-renderer/step-renderer.component.mjs +38 -74
- package/esm2020/lib/step-builder/template-variables-form/template-variables-form.component.mjs +28 -17
- package/fesm2015/cqa-lib-cqa-ui.mjs +66 -92
- package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
- package/fesm2020/cqa-lib-cqa-ui.mjs +64 -89
- package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
- package/lib/execution-screen/step-renderer/step-renderer.component.d.ts +8 -0
- package/package.json +1 -1
|
@@ -7570,6 +7570,26 @@ class StepRendererComponent {
|
|
|
7570
7570
|
return this.getDebugPointSetHandler(this.step);
|
|
7571
7571
|
return false;
|
|
7572
7572
|
}
|
|
7573
|
+
/**
|
|
7574
|
+
* Safely trigger change detection on a child component.
|
|
7575
|
+
* Calls detectChanges() only if the child's ngOnInit has already run (i.e. config is built).
|
|
7576
|
+
* Before initialization, falls back to markForCheck() which queues CD for the next cycle
|
|
7577
|
+
* without forcing immediate template evaluation.
|
|
7578
|
+
*/
|
|
7579
|
+
safeDetectChanges(componentRef) {
|
|
7580
|
+
if (!componentRef?.injector)
|
|
7581
|
+
return;
|
|
7582
|
+
const instanceCdr = componentRef.injector.get(ChangeDetectorRef, null);
|
|
7583
|
+
if (!instanceCdr)
|
|
7584
|
+
return;
|
|
7585
|
+
if (StepRendererComponent.componentInitialized.get(this.container)) {
|
|
7586
|
+
instanceCdr.markForCheck();
|
|
7587
|
+
instanceCdr.detectChanges();
|
|
7588
|
+
}
|
|
7589
|
+
else {
|
|
7590
|
+
instanceCdr.markForCheck();
|
|
7591
|
+
}
|
|
7592
|
+
}
|
|
7573
7593
|
ngOnChanges(changes) {
|
|
7574
7594
|
if (!this.container || !this.step)
|
|
7575
7595
|
return;
|
|
@@ -7595,13 +7615,7 @@ class StepRendererComponent {
|
|
|
7595
7615
|
// Try to update selectedIteration if iterations are available
|
|
7596
7616
|
this.updateLoopStepSelectedIteration(instance, currentValue);
|
|
7597
7617
|
// Trigger change detection on the loop-step component
|
|
7598
|
-
|
|
7599
|
-
const instanceCdr = componentRef.injector.get(ChangeDetectorRef, null);
|
|
7600
|
-
if (instanceCdr) {
|
|
7601
|
-
instanceCdr.markForCheck();
|
|
7602
|
-
instanceCdr.detectChanges();
|
|
7603
|
-
}
|
|
7604
|
-
}
|
|
7618
|
+
this.safeDetectChanges(componentRef);
|
|
7605
7619
|
}
|
|
7606
7620
|
}
|
|
7607
7621
|
}
|
|
@@ -7619,13 +7633,7 @@ class StepRendererComponent {
|
|
|
7619
7633
|
instance.config.stepNumber = currentValue;
|
|
7620
7634
|
}
|
|
7621
7635
|
// Trigger change detection on the component instance
|
|
7622
|
-
|
|
7623
|
-
const instanceCdr = componentRef.injector.get(ChangeDetectorRef, null);
|
|
7624
|
-
if (instanceCdr) {
|
|
7625
|
-
instanceCdr.markForCheck();
|
|
7626
|
-
instanceCdr.detectChanges();
|
|
7627
|
-
}
|
|
7628
|
-
}
|
|
7636
|
+
this.safeDetectChanges(componentRef);
|
|
7629
7637
|
}
|
|
7630
7638
|
}
|
|
7631
7639
|
}
|
|
@@ -7651,13 +7659,7 @@ class StepRendererComponent {
|
|
|
7651
7659
|
}
|
|
7652
7660
|
}
|
|
7653
7661
|
// Trigger change detection on the component instance
|
|
7654
|
-
|
|
7655
|
-
const instanceCdr = componentRef.injector.get(ChangeDetectorRef, null);
|
|
7656
|
-
if (instanceCdr) {
|
|
7657
|
-
instanceCdr.markForCheck();
|
|
7658
|
-
instanceCdr.detectChanges();
|
|
7659
|
-
}
|
|
7660
|
-
}
|
|
7662
|
+
this.safeDetectChanges(componentRef);
|
|
7661
7663
|
}
|
|
7662
7664
|
}
|
|
7663
7665
|
// If downloadingStepId changed, update file-download instance isDownloading
|
|
@@ -7667,13 +7669,7 @@ class StepRendererComponent {
|
|
|
7667
7669
|
if (instance && componentRef && this.getEffectiveStepType(currentStep) === 'file-download') {
|
|
7668
7670
|
const tid = currentStep.testStepResultId;
|
|
7669
7671
|
instance.isDownloading = !!tid && this.downloadingStepId === tid;
|
|
7670
|
-
|
|
7671
|
-
const instanceCdr = componentRef.injector.get(ChangeDetectorRef, null);
|
|
7672
|
-
if (instanceCdr) {
|
|
7673
|
-
instanceCdr.markForCheck();
|
|
7674
|
-
instanceCdr.detectChanges();
|
|
7675
|
-
}
|
|
7676
|
-
}
|
|
7672
|
+
this.safeDetectChanges(componentRef);
|
|
7677
7673
|
}
|
|
7678
7674
|
}
|
|
7679
7675
|
// If isDebug, debugPointSet or getDebugPointSetHandler changed (e.g. user toggled debug in portal/Storybook), update nested instance
|
|
@@ -7751,13 +7747,7 @@ class StepRendererComponent {
|
|
|
7751
7747
|
subscribedEvents.add('stepMoreOptionSelect');
|
|
7752
7748
|
}
|
|
7753
7749
|
}
|
|
7754
|
-
|
|
7755
|
-
const instanceCdr = componentRef.injector.get(ChangeDetectorRef, null);
|
|
7756
|
-
if (instanceCdr) {
|
|
7757
|
-
instanceCdr.markForCheck();
|
|
7758
|
-
instanceCdr.detectChanges();
|
|
7759
|
-
}
|
|
7760
|
-
}
|
|
7750
|
+
this.safeDetectChanges(componentRef);
|
|
7761
7751
|
}
|
|
7762
7752
|
}
|
|
7763
7753
|
// Get step identifiers (use effective type: generateDocument -> file-download)
|
|
@@ -8018,8 +8008,6 @@ class StepRendererComponent {
|
|
|
8018
8008
|
if (currentStep.displayType === 'condition' && currentStep.nestedSteps !== undefined) {
|
|
8019
8009
|
const currentNestedSteps = currentStep.nestedSteps || [];
|
|
8020
8010
|
const previousNestedSteps = previousStep.nestedSteps || [];
|
|
8021
|
-
console.log('🔄 step-renderer: currentNestedSteps', currentNestedSteps);
|
|
8022
|
-
console.log('🔄 step-renderer: previousNestedSteps', previousNestedSteps);
|
|
8023
8011
|
// Use deep comparison to detect content changes, not just reference changes
|
|
8024
8012
|
// This is critical when switching between IF and ELSE_IF branches
|
|
8025
8013
|
if (this.hasNestedStepsChanged(currentNestedSteps, previousNestedSteps)) {
|
|
@@ -8029,11 +8017,6 @@ class StepRendererComponent {
|
|
|
8029
8017
|
instance.config.nestedSteps = [...currentNestedSteps];
|
|
8030
8018
|
}
|
|
8031
8019
|
hasChanges = true;
|
|
8032
|
-
console.log('🔄 step-renderer: nestedSteps updated for condition-step', {
|
|
8033
|
-
stepId: currentStep.id,
|
|
8034
|
-
previousCount: previousNestedSteps.length,
|
|
8035
|
-
currentCount: currentNestedSteps.length
|
|
8036
|
-
});
|
|
8037
8020
|
}
|
|
8038
8021
|
}
|
|
8039
8022
|
// Special handling for file-download (including generateDocument): sync from generateDocumentResult
|
|
@@ -8157,19 +8140,7 @@ class StepRendererComponent {
|
|
|
8157
8140
|
// Trigger change detection on the component instance if there were changes
|
|
8158
8141
|
// This ensures only the nested step updates without affecting parent steps
|
|
8159
8142
|
if (hasChanges) {
|
|
8160
|
-
|
|
8161
|
-
const instanceCdr = componentRef.injector.get(ChangeDetectorRef, null);
|
|
8162
|
-
if (instanceCdr) {
|
|
8163
|
-
instanceCdr.markForCheck();
|
|
8164
|
-
instanceCdr.detectChanges();
|
|
8165
|
-
}
|
|
8166
|
-
}
|
|
8167
|
-
else if (instance.cdr) {
|
|
8168
|
-
instance.cdr.detectChanges();
|
|
8169
|
-
}
|
|
8170
|
-
else if (instance.changeDetectorRef) {
|
|
8171
|
-
instance.changeDetectorRef.detectChanges();
|
|
8172
|
-
}
|
|
8143
|
+
this.safeDetectChanges(componentRef);
|
|
8173
8144
|
// Don't call markForCheck on this component to avoid triggering parent re-renders
|
|
8174
8145
|
}
|
|
8175
8146
|
}
|
|
@@ -8338,6 +8309,7 @@ class StepRendererComponent {
|
|
|
8338
8309
|
}
|
|
8339
8310
|
StepRendererComponent.componentInstances.delete(this.container);
|
|
8340
8311
|
StepRendererComponent.componentRefs.delete(this.container);
|
|
8312
|
+
StepRendererComponent.componentInitialized.delete(this.container);
|
|
8341
8313
|
this.lastStepId = currentStepId;
|
|
8342
8314
|
this.lastStepType = currentStepType;
|
|
8343
8315
|
}
|
|
@@ -8541,7 +8513,6 @@ class StepRendererComponent {
|
|
|
8541
8513
|
}
|
|
8542
8514
|
// Special handling for loop-step: initialize iterations if not present
|
|
8543
8515
|
if (this.isLoopStep(this.step) && !instance.iterations) {
|
|
8544
|
-
console.log(" changes['selectedIterationId'] step", this.selectedIterationId, instance.iterations);
|
|
8545
8516
|
// Use handler if available, otherwise try to initialize from step.executedResult.stepResult
|
|
8546
8517
|
if (this.getLoopIterationsHandler) {
|
|
8547
8518
|
instance.iterations = this.getLoopIterationsHandler(this.step);
|
|
@@ -8582,7 +8553,6 @@ class StepRendererComponent {
|
|
|
8582
8553
|
}
|
|
8583
8554
|
// Special handling for loop-step: set defaultIteration and selectedIterationId
|
|
8584
8555
|
if (this.isLoopStep(this.step)) {
|
|
8585
|
-
console.log(" changes['selectedIterationId'] step 2", this.selectedIterationId, instance.iterations);
|
|
8586
8556
|
// Set defaultIteration to 'last' if not already set
|
|
8587
8557
|
if (!instance.defaultIteration) {
|
|
8588
8558
|
instance.defaultIteration = 'last';
|
|
@@ -8995,9 +8965,11 @@ class StepRendererComponent {
|
|
|
8995
8965
|
instanceCdr.markForCheck();
|
|
8996
8966
|
}
|
|
8997
8967
|
}
|
|
8998
|
-
//
|
|
8999
|
-
//
|
|
8968
|
+
// Mark component as initialized after the next CD cycle completes.
|
|
8969
|
+
// By then, the child's ngOnInit will have run and config is built.
|
|
8970
|
+
// After this, safeDetectChanges() will use detectChanges() for immediate updates.
|
|
9000
8971
|
setTimeout(() => {
|
|
8972
|
+
StepRendererComponent.componentInitialized.set(this.container, true);
|
|
9001
8973
|
this.componentReady.emit();
|
|
9002
8974
|
}, 0);
|
|
9003
8975
|
}
|
|
@@ -9060,13 +9032,7 @@ class StepRendererComponent {
|
|
|
9060
9032
|
// Update the step object's expanded property to keep it in sync
|
|
9061
9033
|
this.step.expanded = currentExpanded;
|
|
9062
9034
|
// Trigger change detection
|
|
9063
|
-
|
|
9064
|
-
const instanceCdr = componentRef.injector.get(ChangeDetectorRef, null);
|
|
9065
|
-
if (instanceCdr) {
|
|
9066
|
-
instanceCdr.markForCheck();
|
|
9067
|
-
instanceCdr.detectChanges();
|
|
9068
|
-
}
|
|
9069
|
-
}
|
|
9035
|
+
this.safeDetectChanges(componentRef);
|
|
9070
9036
|
}
|
|
9071
9037
|
// Check if iterations are now available and we need to update selectedIteration
|
|
9072
9038
|
if (this.isLoopStep(this.step) && this.selectedIterationId) {
|
|
@@ -9078,13 +9044,7 @@ class StepRendererComponent {
|
|
|
9078
9044
|
const shouldBeSelected = iterations.find((iter) => iter.id === selectedIterationId);
|
|
9079
9045
|
if (shouldBeSelected && currentSelectedIteration?.id !== selectedIterationId) {
|
|
9080
9046
|
this.updateLoopStepSelectedIteration(instance, selectedIterationId);
|
|
9081
|
-
|
|
9082
|
-
const instanceCdr = componentRef.injector.get(ChangeDetectorRef, null);
|
|
9083
|
-
if (instanceCdr) {
|
|
9084
|
-
instanceCdr.markForCheck();
|
|
9085
|
-
instanceCdr.detectChanges();
|
|
9086
|
-
}
|
|
9087
|
-
}
|
|
9047
|
+
this.safeDetectChanges(componentRef);
|
|
9088
9048
|
}
|
|
9089
9049
|
}
|
|
9090
9050
|
}
|
|
@@ -9129,6 +9089,10 @@ class StepRendererComponent {
|
|
|
9129
9089
|
StepRendererComponent.componentInstances = new WeakMap();
|
|
9130
9090
|
StepRendererComponent.componentRefs = new WeakMap();
|
|
9131
9091
|
StepRendererComponent.subscribedEventEmitters = new WeakMap(); // Track which EventEmitters have been subscribed to
|
|
9092
|
+
// Track whether child component's ngOnInit has run (config is built).
|
|
9093
|
+
// detectChanges() must NOT be called before initialization — it forces template
|
|
9094
|
+
// evaluation which crashes on undefined config properties.
|
|
9095
|
+
StepRendererComponent.componentInitialized = new WeakMap();
|
|
9132
9096
|
StepRendererComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepRendererComponent, deps: [{ token: STEP_COMPONENT_MAP }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
9133
9097
|
StepRendererComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepRendererComponent, selector: "cqa-step-renderer", inputs: { step: "step", onExpandHandler: "onExpandHandler", getConditionBranchesHandler: "getConditionBranchesHandler", isStepLoadingHandler: "isStepLoadingHandler", isStepExpandedHandler: "isStepExpandedHandler", convertMsToSecondsHandler: "convertMsToSecondsHandler", formatFailureDetailsHandler: "formatFailureDetailsHandler", getSelfHealAnalysisHandler: "getSelfHealAnalysisHandler", onMakeCurrentBaselineHandler: "onMakeCurrentBaselineHandler", onUploadBaselineHandler: "onUploadBaselineHandler", onAnalyzeHandler: "onAnalyzeHandler", onViewFullLogsHandler: "onViewFullLogsHandler", onSelfHealActionHandler: "onSelfHealActionHandler", getSelfHealLoadingStatesHandler: "getSelfHealLoadingStatesHandler", isUploadingBaseline: "isUploadingBaseline", isMakingCurrentBaseline: "isMakingCurrentBaseline", selectedIterationId: "selectedIterationId", getLoopIterationsHandler: "getLoopIterationsHandler", getApiAssertionsHandler: "getApiAssertionsHandler", formatActionsHandler: "formatActionsHandler", onViewAllIterationsHandler: "onViewAllIterationsHandler", onConditionBranchClickHandler: "onConditionBranchClickHandler", onStepClickHandler: "onStepClickHandler", onJsonPathCopiedHandler: "onJsonPathCopiedHandler", onDownloadHandler: "onDownloadHandler", onFilePathCopiedHandler: "onFilePathCopiedHandler", onTextCopiedHandler: "onTextCopiedHandler", jumpToTimestampHandler: "jumpToTimestampHandler", downloadingStepId: "downloadingStepId", isLive: "isLive", isDebug: "isDebug", debugPointSet: "debugPointSet", getDebugPointSetHandler: "getDebugPointSetHandler", onDebugPointChangeHandler: "onDebugPointChangeHandler", onEditStepHandler: "onEditStepHandler", addStepMenuOptions: "addStepMenuOptions", onAddStepOptionSelectHandler: "onAddStepOptionSelectHandler", stepMoreMenuOptions: "stepMoreMenuOptions", onStepMoreOptionSelectHandler: "onStepMoreOptionSelectHandler", getAddStepMenuOptionsForNested: "getAddStepMenuOptionsForNested", getStepMoreMenuOptionsForNested: "getStepMoreMenuOptionsForNested", stepNumber: "stepNumber", parentSkipped: "parentSkipped" }, outputs: { addStepOptionSelect: "addStepOptionSelect", stepMoreOptionSelect: "stepMoreOptionSelect", addStepInsideLoop: "addStepInsideLoop", componentReady: "componentReady" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef }], usesOnChanges: true, ngImport: i0, template: '<ng-container #container></ng-container>', isInline: true });
|
|
9134
9098
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepRendererComponent, decorators: [{
|
|
@@ -31329,20 +31293,23 @@ class TemplateVariablesFormComponent {
|
|
|
31329
31293
|
this.cdr.markForCheck();
|
|
31330
31294
|
}
|
|
31331
31295
|
}
|
|
31332
|
-
//
|
|
31333
|
-
//
|
|
31334
|
-
//
|
|
31335
|
-
//
|
|
31296
|
+
// Re-run initializeTestDataVariables whenever parameterOptions changes and there are still
|
|
31297
|
+
// variables that need initialization (have profileId but missing profile name or dataSet).
|
|
31298
|
+
// We do NOT use firstChange here because the saved profile may arrive in a second API call
|
|
31299
|
+
// (id@<profileId>) after the initial paginated list, so firstChange would miss it.
|
|
31300
|
+
// The inner some() guard ensures we only re-run when variables are still incomplete,
|
|
31301
|
+
// preventing unnecessary re-runs on user search updates.
|
|
31336
31302
|
if (changes['parameterOptions'] &&
|
|
31337
|
-
changes['parameterOptions'].firstChange &&
|
|
31338
31303
|
this.parameterOptions.length > 0 &&
|
|
31339
|
-
(
|
|
31340
|
-
|
|
31341
|
-
|
|
31342
|
-
|
|
31343
|
-
|
|
31344
|
-
|
|
31345
|
-
|
|
31304
|
+
(
|
|
31305
|
+
// Check if any variable has selectedTestDataProfileId but is missing selectedTestDataProfile or selectedDataSet
|
|
31306
|
+
// This happens when loading a saved step - setTemplateVariables sets the ID, but we need parameterOptions to set the name and data set
|
|
31307
|
+
this.templateVariables?.some(v => this.needsDataTypeDropdown(v) &&
|
|
31308
|
+
v.dataType === 'parameter' &&
|
|
31309
|
+
v.selectedTestDataProfileId != null &&
|
|
31310
|
+
(!v.selectedTestDataProfile || !v.selectedDataSet)) ||
|
|
31311
|
+
(this.defaultTestDataProfileId && this.defaultTestDataStartIndex != null &&
|
|
31312
|
+
this.templateVariables?.some(v => this.needsDataTypeDropdown(v) && v.dataType === 'parameter' && !v.selectedTestDataProfile)) ||
|
|
31346
31313
|
// The extra uninitialized-variable check below is debug-only: only run it in debug mode
|
|
31347
31314
|
// to avoid double-initialising variables in non-debug step-builder flows.
|
|
31348
31315
|
(this.isDebug && this.templateVariables?.some(v => this.needsDataTypeDropdown(v) && v.dataType === 'parameter' && !v.selectedTestDataProfile)))) {
|
|
@@ -31555,14 +31522,22 @@ class TemplateVariablesFormComponent {
|
|
|
31555
31522
|
// For environment type, parse the value to extract environment and parameter
|
|
31556
31523
|
if (dataType === 'environment') {
|
|
31557
31524
|
// Environment values are in format *|parameterName|
|
|
31558
|
-
// We need to find which environment this parameter belongs to
|
|
31559
31525
|
const paramName = rawValue;
|
|
31560
31526
|
if (paramName) {
|
|
31561
|
-
//
|
|
31562
|
-
|
|
31527
|
+
// If we have a saved environmentId, use it for an exact match (env-{id}-{param})
|
|
31528
|
+
// to avoid selecting the wrong environment when multiple environments share param names.
|
|
31529
|
+
let envOption;
|
|
31530
|
+
if (variable.selectedEnvironmentId != null) {
|
|
31531
|
+
const exactId = `env-${variable.selectedEnvironmentId}-${paramName}`;
|
|
31532
|
+
envOption = this.environmentOptions.find(env => env.id === exactId);
|
|
31533
|
+
}
|
|
31534
|
+
// Fallback: match by param name only (legacy / first-time save)
|
|
31535
|
+
if (!envOption) {
|
|
31536
|
+
envOption = this.environmentOptions.find(env => env.name === paramName);
|
|
31537
|
+
}
|
|
31563
31538
|
if (envOption) {
|
|
31564
31539
|
variable.selectedEnvironment = envOption.environment;
|
|
31565
|
-
// Extract and store environment ID
|
|
31540
|
+
// Extract and store environment ID from the option id
|
|
31566
31541
|
const idMatch = envOption.id.match(/env-(\d+)-/);
|
|
31567
31542
|
if (idMatch && idMatch[1]) {
|
|
31568
31543
|
variable.selectedEnvironmentId = parseInt(idMatch[1], 10);
|