@memberjunction/ng-core-entity-forms 5.34.0 → 5.35.0
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/lib/custom/Tests/test-form.component.d.ts +25 -1
- package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.js +898 -547
- package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts +56 -1
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.js +1647 -788
- package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
- package/dist/lib/custom/custom-forms.module.d.ts +25 -24
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +4 -0
- package/dist/lib/custom/custom-forms.module.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js +215 -213
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js +23 -23
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIConfiguration/mjaiconfiguration.form.component.js +12 -12
- package/dist/lib/generated/Entities/MJAIConfiguration/mjaiconfiguration.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIModality/mjaimodality.form.component.js +17 -17
- package/dist/lib/generated/Entities/MJAIModality/mjaimodality.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js +51 -51
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js +31 -31
- package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js +9 -9
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIVendor/mjaivendor.form.component.js +25 -25
- package/dist/lib/generated/Entities/MJAIVendor/mjaivendor.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAPIKey/mjapikey.form.component.js +13 -13
- package/dist/lib/generated/Entities/MJAPIKey/mjapikey.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAPIScope/mjapiscope.form.component.js +9 -9
- package/dist/lib/generated/Entities/MJAPIScope/mjapiscope.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAction/mjaction.form.component.js +19 -19
- package/dist/lib/generated/Entities/MJAction/mjaction.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.js +17 -17
- package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJArtifactType/mjartifacttype.form.component.js +53 -47
- package/dist/lib/generated/Entities/MJArtifactType/mjartifacttype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJArtifactVersion/mjartifactversion.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJArtifactVersion/mjartifactversion.form.component.js +53 -33
- package/dist/lib/generated/Entities/MJArtifactVersion/mjartifactversion.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAuditLogType/mjauditlogtype.form.component.js +10 -10
- package/dist/lib/generated/Entities/MJAuditLogType/mjauditlogtype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAuthorization/mjauthorization.form.component.js +20 -20
- package/dist/lib/generated/Entities/MJAuthorization/mjauthorization.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCommunicationProvider/mjcommunicationprovider.form.component.js +19 -19
- package/dist/lib/generated/Entities/MJCommunicationProvider/mjcommunicationprovider.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCompany/mjcompany.form.component.js +9 -9
- package/dist/lib/generated/Entities/MJCompany/mjcompany.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCompanyIntegration/mjcompanyintegration.form.component.js +17 -17
- package/dist/lib/generated/Entities/MJCompanyIntegration/mjcompanyintegration.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCompanyIntegrationRun/mjcompanyintegrationrun.form.component.js +10 -10
- package/dist/lib/generated/Entities/MJCompanyIntegrationRun/mjcompanyintegrationrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js +9 -9
- package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.js +10 -10
- package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJConversationDetailAttachment/mjconversationdetailattachment.form.component.js +7 -5
- package/dist/lib/generated/Entities/MJConversationDetailAttachment/mjconversationdetailattachment.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJDashboard/mjdashboard.form.component.js +17 -17
- package/dist/lib/generated/Entities/MJDashboard/mjdashboard.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJDashboardCategory/mjdashboardcategory.form.component.js +9 -9
- package/dist/lib/generated/Entities/MJDashboardCategory/mjdashboardcategory.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEmployee/mjemployee.form.component.js +15 -15
- package/dist/lib/generated/Entities/MJEmployee/mjemployee.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +208 -208
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityAction/mjentityaction.form.component.js +9 -9
- package/dist/lib/generated/Entities/MJEntityAction/mjentityaction.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFileCategory/mjfilecategory.form.component.js +10 -10
- package/dist/lib/generated/Entities/MJFileCategory/mjfilecategory.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFileStorageAccount/mjfilestorageaccount.form.component.js +9 -9
- package/dist/lib/generated/Entities/MJFileStorageAccount/mjfilestorageaccount.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJIntegration/mjintegration.form.component.js +9 -9
- package/dist/lib/generated/Entities/MJIntegration/mjintegration.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJList/mjlist.form.component.js +17 -17
- package/dist/lib/generated/Entities/MJList/mjlist.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJMCPServerConnection/mjmcpserverconnection.form.component.js +12 -12
- package/dist/lib/generated/Entities/MJMCPServerConnection/mjmcpserverconnection.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js +30 -30
- package/dist/lib/generated/Entities/MJQuery/mjquery.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJQueryCategory/mjquerycategory.form.component.js +10 -10
- package/dist/lib/generated/Entities/MJQueryCategory/mjquerycategory.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJRecordChange/mjrecordchange.form.component.js +10 -10
- package/dist/lib/generated/Entities/MJRecordChange/mjrecordchange.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJRecordMergeLog/mjrecordmergelog.form.component.js +10 -10
- package/dist/lib/generated/Entities/MJRecordMergeLog/mjrecordmergelog.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js +34 -34
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJSearchScope/mjsearchscope.form.component.js +19 -19
- package/dist/lib/generated/Entities/MJSearchScope/mjsearchscope.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTag/mjtag.form.component.js +16 -16
- package/dist/lib/generated/Entities/MJTag/mjtag.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTemplate/mjtemplate.form.component.js +16 -16
- package/dist/lib/generated/Entities/MJTemplate/mjtemplate.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTemplateCategory/mjtemplatecategory.form.component.js +10 -10
- package/dist/lib/generated/Entities/MJTemplateCategory/mjtemplatecategory.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js +330 -330
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.js +13 -13
- package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJVectorDatabase/mjvectordatabase.form.component.js +10 -10
- package/dist/lib/generated/Entities/MJVectorDatabase/mjvectordatabase.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJVectorIndex/mjvectorindex.form.component.js +9 -9
- package/dist/lib/generated/Entities/MJVectorIndex/mjvectorindex.form.component.js.map +1 -1
- package/package.json +37 -36
|
@@ -9,6 +9,7 @@ import * as d3 from 'd3';
|
|
|
9
9
|
import { Subject } from 'rxjs';
|
|
10
10
|
import { takeUntil, debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
|
11
11
|
import { CompositeKey, RunView } from '@memberjunction/core';
|
|
12
|
+
import { moveItemInArray } from '@angular/cdk/drag-drop';
|
|
12
13
|
import { UserInfoEngine } from '@memberjunction/core-entities';
|
|
13
14
|
import { BaseFormComponent } from '@memberjunction/ng-base-forms';
|
|
14
15
|
import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
|
|
@@ -19,10 +20,11 @@ import { TestingDialogService, TagsHelper, EvaluationPreferencesService } from '
|
|
|
19
20
|
import * as i0 from "@angular/core";
|
|
20
21
|
import * as i1 from "@angular/common";
|
|
21
22
|
import * as i2 from "@angular/forms";
|
|
22
|
-
import * as i3 from "@
|
|
23
|
-
import * as i4 from "@memberjunction/ng-
|
|
24
|
-
import * as i5 from "@memberjunction/ng-
|
|
25
|
-
import * as i6 from "@memberjunction/ng-
|
|
23
|
+
import * as i3 from "@angular/cdk/drag-drop";
|
|
24
|
+
import * as i4 from "@memberjunction/ng-ui-components";
|
|
25
|
+
import * as i5 from "@memberjunction/ng-testing";
|
|
26
|
+
import * as i6 from "@memberjunction/ng-shared-generic";
|
|
27
|
+
import * as i7 from "@memberjunction/ng-versions";
|
|
26
28
|
const _c0 = ["chartContainer"];
|
|
27
29
|
const _c1 = () => [1, 2, 3, 4, 5];
|
|
28
30
|
const _c2 = () => [1, 2, 3];
|
|
@@ -32,9 +34,15 @@ const _c5 = (a0, a1, a2) => ({ "high": a0, "medium": a1, "low": a2 });
|
|
|
32
34
|
const _c6 = (a0, a1) => ({ "positive": a0, "negative": a1 });
|
|
33
35
|
const _c7 = (a0, a1, a2) => ({ "fa-arrow-down": a0, "fa-arrow-up": a1, "fa-minus": a2 });
|
|
34
36
|
const _c8 = (a0, a1) => ({ "improved": a0, "regressed": a1 });
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
i0.ɵɵ
|
|
37
|
+
const _forTrack0 = ($index, $item) => $item.ID;
|
|
38
|
+
function MJTestSuiteFormComponentExtended_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
39
|
+
i0.ɵɵelementStart(0, "span", 16);
|
|
40
|
+
i0.ɵɵtext(1, "\u25CF");
|
|
41
|
+
i0.ɵɵelementEnd();
|
|
42
|
+
} }
|
|
43
|
+
function MJTestSuiteFormComponentExtended_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
44
|
+
i0.ɵɵelementStart(0, "span", 20);
|
|
45
|
+
i0.ɵɵelement(1, "i", 33);
|
|
38
46
|
i0.ɵɵtext(2);
|
|
39
47
|
i0.ɵɵelementEnd();
|
|
40
48
|
} if (rf & 2) {
|
|
@@ -42,8 +50,14 @@ function MJTestSuiteFormComponentExtended_Conditional_25_Template(rf, ctx) { if
|
|
|
42
50
|
i0.ɵɵadvance(2);
|
|
43
51
|
i0.ɵɵtextInterpolate1(" ", ctx_r0.suiteTests.length, " tests ");
|
|
44
52
|
} }
|
|
45
|
-
function
|
|
46
|
-
i0.ɵɵelementStart(0, "
|
|
53
|
+
function MJTestSuiteFormComponentExtended_Conditional_27_Template(rf, ctx) { if (rf & 1) {
|
|
54
|
+
i0.ɵɵelementStart(0, "span", 21);
|
|
55
|
+
i0.ɵɵelement(1, "i", 57);
|
|
56
|
+
i0.ɵɵtext(2, " Unsaved ");
|
|
57
|
+
i0.ɵɵelementEnd();
|
|
58
|
+
} }
|
|
59
|
+
function MJTestSuiteFormComponentExtended_Conditional_39_Template(rf, ctx) { if (rf & 1) {
|
|
60
|
+
i0.ɵɵelementStart(0, "div", 28)(1, "p");
|
|
47
61
|
i0.ɵɵtext(2);
|
|
48
62
|
i0.ɵɵelementEnd()();
|
|
49
63
|
} if (rf & 2) {
|
|
@@ -51,8 +65,8 @@ function MJTestSuiteFormComponentExtended_Conditional_37_Template(rf, ctx) { if
|
|
|
51
65
|
i0.ɵɵadvance(2);
|
|
52
66
|
i0.ɵɵtextInterpolate(ctx_r0.record.Description);
|
|
53
67
|
} }
|
|
54
|
-
function
|
|
55
|
-
i0.ɵɵelementStart(0, "span",
|
|
68
|
+
function MJTestSuiteFormComponentExtended_Conditional_48_Template(rf, ctx) { if (rf & 1) {
|
|
69
|
+
i0.ɵɵelementStart(0, "span", 34);
|
|
56
70
|
i0.ɵɵtext(1);
|
|
57
71
|
i0.ɵɵelementEnd();
|
|
58
72
|
} if (rf & 2) {
|
|
@@ -60,8 +74,8 @@ function MJTestSuiteFormComponentExtended_Conditional_46_Template(rf, ctx) { if
|
|
|
60
74
|
i0.ɵɵadvance();
|
|
61
75
|
i0.ɵɵtextInterpolate(ctx_r0.suiteTests.length);
|
|
62
76
|
} }
|
|
63
|
-
function
|
|
64
|
-
i0.ɵɵelementStart(0, "span",
|
|
77
|
+
function MJTestSuiteFormComponentExtended_Conditional_52_Template(rf, ctx) { if (rf & 1) {
|
|
78
|
+
i0.ɵɵelementStart(0, "span", 34);
|
|
65
79
|
i0.ɵɵtext(1);
|
|
66
80
|
i0.ɵɵelementEnd();
|
|
67
81
|
} if (rf & 2) {
|
|
@@ -69,303 +83,468 @@ function MJTestSuiteFormComponentExtended_Conditional_50_Template(rf, ctx) { if
|
|
|
69
83
|
i0.ɵɵadvance();
|
|
70
84
|
i0.ɵɵtextInterpolate(ctx_r0.suiteRuns.length);
|
|
71
85
|
} }
|
|
72
|
-
function
|
|
86
|
+
function MJTestSuiteFormComponentExtended_Conditional_60_For_25_Template(rf, ctx) { if (rf & 1) {
|
|
87
|
+
i0.ɵɵelementStart(0, "option", 73);
|
|
88
|
+
i0.ɵɵtext(1);
|
|
89
|
+
i0.ɵɵelementEnd();
|
|
90
|
+
} if (rf & 2) {
|
|
91
|
+
const opt_r3 = ctx.$implicit;
|
|
92
|
+
i0.ɵɵproperty("ngValue", opt_r3);
|
|
93
|
+
i0.ɵɵadvance();
|
|
94
|
+
i0.ɵɵtextInterpolate(opt_r3);
|
|
95
|
+
} }
|
|
96
|
+
function MJTestSuiteFormComponentExtended_Conditional_60_For_33_Template(rf, ctx) { if (rf & 1) {
|
|
97
|
+
i0.ɵɵelementStart(0, "option", 73);
|
|
98
|
+
i0.ɵɵtext(1);
|
|
99
|
+
i0.ɵɵelementEnd();
|
|
100
|
+
} if (rf & 2) {
|
|
101
|
+
const s_r4 = ctx.$implicit;
|
|
102
|
+
i0.ɵɵproperty("ngValue", s_r4.ID);
|
|
103
|
+
i0.ɵɵadvance();
|
|
104
|
+
i0.ɵɵtextInterpolate(s_r4.Name);
|
|
105
|
+
} }
|
|
106
|
+
function MJTestSuiteFormComponentExtended_Conditional_60_For_39_Template(rf, ctx) { if (rf & 1) {
|
|
107
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
108
|
+
i0.ɵɵelementStart(0, "span", 78);
|
|
109
|
+
i0.ɵɵtext(1);
|
|
110
|
+
i0.ɵɵelementStart(2, "button", 90);
|
|
111
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_60_For_39_Template_button_click_2_listener($event) { const tag_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); ctx_r0.removeTag(tag_r7); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
112
|
+
i0.ɵɵelement(3, "i", 91);
|
|
113
|
+
i0.ɵɵelementEnd()();
|
|
114
|
+
} if (rf & 2) {
|
|
115
|
+
const tag_r7 = ctx.$implicit;
|
|
116
|
+
i0.ɵɵadvance();
|
|
117
|
+
i0.ɵɵtextInterpolate1(" ", tag_r7, " ");
|
|
118
|
+
i0.ɵɵadvance();
|
|
119
|
+
i0.ɵɵattribute("aria-label", "Remove tag " + tag_r7);
|
|
120
|
+
} }
|
|
121
|
+
function MJTestSuiteFormComponentExtended_Conditional_60_Template(rf, ctx) { if (rf & 1) {
|
|
73
122
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
74
|
-
i0.ɵɵelementStart(0, "div",
|
|
75
|
-
i0.ɵɵelement(
|
|
76
|
-
i0.ɵɵtext(
|
|
123
|
+
i0.ɵɵelementStart(0, "div", 39)(1, "section", 58)(2, "header", 59)(3, "h3");
|
|
124
|
+
i0.ɵɵelement(4, "i", 60);
|
|
125
|
+
i0.ɵɵtext(5, " Details");
|
|
77
126
|
i0.ɵɵelementEnd();
|
|
78
|
-
i0.ɵɵelementStart(
|
|
79
|
-
i0.ɵɵtext(
|
|
127
|
+
i0.ɵɵelementStart(6, "p", 61);
|
|
128
|
+
i0.ɵɵtext(7, "Edit any field \u2014 changes are saved with the bar at the bottom.");
|
|
129
|
+
i0.ɵɵelementEnd()();
|
|
130
|
+
i0.ɵɵelementStart(8, "div", 62)(9, "div", 63)(10, "label", 64);
|
|
131
|
+
i0.ɵɵtext(11, "Name ");
|
|
132
|
+
i0.ɵɵelementStart(12, "span", 65);
|
|
133
|
+
i0.ɵɵtext(13, "*");
|
|
134
|
+
i0.ɵɵelementEnd()();
|
|
135
|
+
i0.ɵɵelementStart(14, "input", 66);
|
|
136
|
+
i0.ɵɵtwoWayListener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_60_Template_input_ngModelChange_14_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.record.Name, $event) || (ctx_r0.record.Name = $event); return i0.ɵɵresetView($event); });
|
|
137
|
+
i0.ɵɵelementEnd()();
|
|
138
|
+
i0.ɵɵelementStart(15, "div", 63)(16, "label", 67);
|
|
139
|
+
i0.ɵɵtext(17, "Description");
|
|
80
140
|
i0.ɵɵelementEnd();
|
|
81
|
-
i0.ɵɵelementStart(
|
|
82
|
-
i0.ɵɵ
|
|
141
|
+
i0.ɵɵelementStart(18, "textarea", 68);
|
|
142
|
+
i0.ɵɵlistener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_60_Template_textarea_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.record.Description = $event || null); });
|
|
83
143
|
i0.ɵɵelementEnd()();
|
|
84
|
-
i0.ɵɵelementStart(
|
|
85
|
-
i0.ɵɵtext(
|
|
144
|
+
i0.ɵɵelementStart(19, "div", 69)(20, "label", 70);
|
|
145
|
+
i0.ɵɵtext(21, "Status");
|
|
86
146
|
i0.ɵɵelementEnd();
|
|
87
|
-
i0.ɵɵelementStart(
|
|
88
|
-
i0.ɵɵ
|
|
147
|
+
i0.ɵɵelementStart(22, "div", 71)(23, "select", 72);
|
|
148
|
+
i0.ɵɵtwoWayListener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_60_Template_select_ngModelChange_23_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.record.Status, $event) || (ctx_r0.record.Status = $event); return i0.ɵɵresetView($event); });
|
|
149
|
+
i0.ɵɵrepeaterCreate(24, MJTestSuiteFormComponentExtended_Conditional_60_For_25_Template, 2, 2, "option", 73, i0.ɵɵrepeaterTrackByIdentity);
|
|
89
150
|
i0.ɵɵelementEnd()()();
|
|
90
|
-
i0.ɵɵelementStart(
|
|
91
|
-
i0.ɵɵtext(
|
|
151
|
+
i0.ɵɵelementStart(26, "div", 69)(27, "label", 74);
|
|
152
|
+
i0.ɵɵtext(28, "Parent Suite");
|
|
92
153
|
i0.ɵɵelementEnd();
|
|
93
|
-
i0.ɵɵelementStart(
|
|
94
|
-
i0.ɵɵ
|
|
95
|
-
i0.ɵɵ
|
|
96
|
-
i0.ɵɵ
|
|
97
|
-
i0.ɵɵelementStart(23, "div", 47)(24, "div", 48);
|
|
98
|
-
i0.ɵɵtext(25, "Updated");
|
|
154
|
+
i0.ɵɵelementStart(29, "select", 75);
|
|
155
|
+
i0.ɵɵlistener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_60_Template_select_ngModelChange_29_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.record.ParentID = $event || null); });
|
|
156
|
+
i0.ɵɵelementStart(30, "option", 73);
|
|
157
|
+
i0.ɵɵtext(31, "\u2014 None (top-level) \u2014");
|
|
99
158
|
i0.ɵɵelementEnd();
|
|
100
|
-
i0.ɵɵ
|
|
101
|
-
i0.ɵɵtext(27);
|
|
102
|
-
i0.ɵɵpipe(28, "date");
|
|
159
|
+
i0.ɵɵrepeaterCreate(32, MJTestSuiteFormComponentExtended_Conditional_60_For_33_Template, 2, 2, "option", 73, _forTrack0);
|
|
103
160
|
i0.ɵɵelementEnd()();
|
|
104
|
-
i0.ɵɵelementStart(
|
|
105
|
-
i0.ɵɵtext(
|
|
161
|
+
i0.ɵɵelementStart(34, "div", 63)(35, "label", 76);
|
|
162
|
+
i0.ɵɵtext(36, "Tags");
|
|
163
|
+
i0.ɵɵelementEnd();
|
|
164
|
+
i0.ɵɵelementStart(37, "div", 77);
|
|
165
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_60_Template_div_click_37_listener() { i0.ɵɵrestoreView(_r2); const tagInput_r5 = i0.ɵɵreference(41); return i0.ɵɵresetView(tagInput_r5.focus()); });
|
|
166
|
+
i0.ɵɵrepeaterCreate(38, MJTestSuiteFormComponentExtended_Conditional_60_For_39_Template, 4, 2, "span", 78, i0.ɵɵrepeaterTrackByIdentity);
|
|
167
|
+
i0.ɵɵelementStart(40, "input", 79, 0);
|
|
168
|
+
i0.ɵɵtwoWayListener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_60_Template_input_ngModelChange_40_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.tagDraft, $event) || (ctx_r0.tagDraft = $event); return i0.ɵɵresetView($event); });
|
|
169
|
+
i0.ɵɵlistener("keydown", function MJTestSuiteFormComponentExtended_Conditional_60_Template_input_keydown_40_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onTagInputKeydown($event)); })("blur", function MJTestSuiteFormComponentExtended_Conditional_60_Template_input_blur_40_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.addTagFromDraft()); });
|
|
170
|
+
i0.ɵɵelementEnd()();
|
|
171
|
+
i0.ɵɵelementStart(42, "span", 80);
|
|
172
|
+
i0.ɵɵtext(43, "Press Enter or comma to add a tag. Backspace on empty input removes the last tag.");
|
|
173
|
+
i0.ɵɵelementEnd()()()();
|
|
174
|
+
i0.ɵɵelementStart(44, "section", 58)(45, "header", 59)(46, "h3");
|
|
175
|
+
i0.ɵɵelement(47, "i", 81);
|
|
176
|
+
i0.ɵɵtext(48, " Execution Settings");
|
|
177
|
+
i0.ɵɵelementEnd()();
|
|
178
|
+
i0.ɵɵelementStart(49, "div", 62)(50, "div", 69)(51, "label", 82);
|
|
179
|
+
i0.ɵɵtext(52, "Max Execution Time (ms)");
|
|
106
180
|
i0.ɵɵelementEnd();
|
|
107
|
-
i0.ɵɵelementStart(
|
|
108
|
-
i0.ɵɵ
|
|
181
|
+
i0.ɵɵelementStart(53, "input", 83);
|
|
182
|
+
i0.ɵɵlistener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_60_Template_input_ngModelChange_53_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.record.MaxExecutionTimeMS = $event === "" || $event === null ? null : +$event); });
|
|
183
|
+
i0.ɵɵelementEnd();
|
|
184
|
+
i0.ɵɵelementStart(54, "span", 80);
|
|
185
|
+
i0.ɵɵtext(55);
|
|
109
186
|
i0.ɵɵelementEnd()()()();
|
|
110
|
-
i0.ɵɵelementStart(
|
|
111
|
-
i0.ɵɵ
|
|
112
|
-
i0.ɵɵtext(37, " Execution Settings");
|
|
187
|
+
i0.ɵɵelementStart(56, "section", 84)(57, "div", 85)(58, "div", 86)(59, "div", 87);
|
|
188
|
+
i0.ɵɵtext(60, "Created");
|
|
113
189
|
i0.ɵɵelementEnd();
|
|
114
|
-
i0.ɵɵelementStart(
|
|
115
|
-
i0.ɵɵtext(
|
|
190
|
+
i0.ɵɵelementStart(61, "div", 88);
|
|
191
|
+
i0.ɵɵtext(62);
|
|
192
|
+
i0.ɵɵpipe(63, "date");
|
|
193
|
+
i0.ɵɵelementEnd()();
|
|
194
|
+
i0.ɵɵelementStart(64, "div", 86)(65, "div", 87);
|
|
195
|
+
i0.ɵɵtext(66, "Last updated");
|
|
116
196
|
i0.ɵɵelementEnd();
|
|
117
|
-
i0.ɵɵelementStart(
|
|
118
|
-
i0.ɵɵ
|
|
197
|
+
i0.ɵɵelementStart(67, "div", 88);
|
|
198
|
+
i0.ɵɵtext(68);
|
|
199
|
+
i0.ɵɵpipe(69, "date");
|
|
200
|
+
i0.ɵɵelementEnd()();
|
|
201
|
+
i0.ɵɵelementStart(70, "div", 86)(71, "div", 87);
|
|
202
|
+
i0.ɵɵtext(72, "Suite ID");
|
|
119
203
|
i0.ɵɵelementEnd();
|
|
120
|
-
i0.ɵɵelementStart(
|
|
121
|
-
i0.ɵɵtext(
|
|
204
|
+
i0.ɵɵelementStart(73, "div", 89);
|
|
205
|
+
i0.ɵɵtext(74);
|
|
122
206
|
i0.ɵɵelementEnd()()()()();
|
|
123
207
|
} if (rf & 2) {
|
|
124
208
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
125
|
-
i0.ɵɵadvance(
|
|
126
|
-
i0.ɵɵ
|
|
209
|
+
i0.ɵɵadvance(14);
|
|
210
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r0.record.Name);
|
|
211
|
+
i0.ɵɵadvance(4);
|
|
212
|
+
i0.ɵɵproperty("ngModel", ctx_r0.record.Description);
|
|
127
213
|
i0.ɵɵadvance(5);
|
|
128
|
-
i0.ɵɵ
|
|
214
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r0.record.Status);
|
|
129
215
|
i0.ɵɵadvance();
|
|
130
|
-
i0.ɵɵ
|
|
216
|
+
i0.ɵɵrepeater(ctx_r0.statusOptions);
|
|
131
217
|
i0.ɵɵadvance(5);
|
|
132
|
-
i0.ɵɵ
|
|
218
|
+
i0.ɵɵproperty("ngModel", ctx_r0.record.ParentID);
|
|
219
|
+
i0.ɵɵadvance();
|
|
220
|
+
i0.ɵɵproperty("ngValue", null);
|
|
221
|
+
i0.ɵɵadvance(2);
|
|
222
|
+
i0.ɵɵrepeater(ctx_r0.parentSuiteOptions);
|
|
133
223
|
i0.ɵɵadvance(6);
|
|
134
|
-
i0.ɵɵ
|
|
224
|
+
i0.ɵɵrepeater(ctx_r0.tags);
|
|
225
|
+
i0.ɵɵadvance(2);
|
|
226
|
+
i0.ɵɵproperty("placeholder", ctx_r0.tags.length === 0 ? "Add tags, press Enter or comma..." : "");
|
|
227
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r0.tagDraft);
|
|
228
|
+
i0.ɵɵadvance(13);
|
|
229
|
+
i0.ɵɵproperty("ngModel", ctx_r0.record.MaxExecutionTimeMS);
|
|
230
|
+
i0.ɵɵadvance(2);
|
|
231
|
+
i0.ɵɵtextInterpolate1("Default timeout for tests in this suite. Currently: ", ctx_r0.formatTimeout(ctx_r0.record.MaxExecutionTimeMS));
|
|
232
|
+
i0.ɵɵadvance(7);
|
|
233
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(63, 12, ctx_r0.record.__mj_CreatedAt, "medium"));
|
|
135
234
|
i0.ɵɵadvance(6);
|
|
136
|
-
i0.ɵɵtextInterpolate(
|
|
137
|
-
i0.ɵɵadvance(
|
|
138
|
-
i0.ɵɵ
|
|
235
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(69, 15, ctx_r0.record.__mj_UpdatedAt, "medium"));
|
|
236
|
+
i0.ɵɵadvance(6);
|
|
237
|
+
i0.ɵɵtextInterpolate(ctx_r0.record.ID);
|
|
238
|
+
} }
|
|
239
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
240
|
+
i0.ɵɵelementStart(0, "span", 94);
|
|
241
|
+
i0.ɵɵtext(1);
|
|
242
|
+
i0.ɵɵelementEnd();
|
|
243
|
+
} if (rf & 2) {
|
|
244
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
245
|
+
i0.ɵɵadvance();
|
|
246
|
+
i0.ɵɵtextInterpolate(ctx_r0.suiteTests.length);
|
|
139
247
|
} }
|
|
140
|
-
function
|
|
141
|
-
i0.ɵɵelementStart(0, "div",
|
|
142
|
-
i0.ɵɵelement(1, "div",
|
|
143
|
-
i0.ɵɵelementStart(3, "div",
|
|
144
|
-
i0.ɵɵelement(4, "div",
|
|
248
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_12_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
249
|
+
i0.ɵɵelementStart(0, "div", 103);
|
|
250
|
+
i0.ɵɵelement(1, "div", 104)(2, "div", 105);
|
|
251
|
+
i0.ɵɵelementStart(3, "div", 106);
|
|
252
|
+
i0.ɵɵelement(4, "div", 107)(5, "div", 108);
|
|
145
253
|
i0.ɵɵelementEnd()();
|
|
146
254
|
} }
|
|
147
|
-
function
|
|
148
|
-
i0.ɵɵelementStart(0, "div",
|
|
149
|
-
i0.ɵɵrepeaterCreate(2,
|
|
255
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
256
|
+
i0.ɵɵelementStart(0, "div", 99)(1, "div", 102);
|
|
257
|
+
i0.ɵɵrepeaterCreate(2, MJTestSuiteFormComponentExtended_Conditional_61_Conditional_12_For_3_Template, 6, 0, "div", 103, i0.ɵɵrepeaterTrackByIdentity);
|
|
150
258
|
i0.ɵɵelementEnd()();
|
|
151
259
|
} if (rf & 2) {
|
|
152
260
|
i0.ɵɵadvance(2);
|
|
153
261
|
i0.ɵɵrepeater(i0.ɵɵpureFunction0(0, _c1));
|
|
154
262
|
} }
|
|
155
|
-
function
|
|
263
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
156
264
|
i0.ɵɵelementStart(0, "span");
|
|
157
|
-
i0.ɵɵelement(1, "i",
|
|
265
|
+
i0.ɵɵelement(1, "i", 119);
|
|
158
266
|
i0.ɵɵtext(2);
|
|
159
267
|
i0.ɵɵelementEnd();
|
|
160
268
|
} if (rf & 2) {
|
|
161
|
-
const
|
|
269
|
+
const test_r11 = i0.ɵɵnextContext().$implicit;
|
|
162
270
|
i0.ɵɵadvance(2);
|
|
163
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
271
|
+
i0.ɵɵtextInterpolate1(" ", test_r11.Status);
|
|
164
272
|
} }
|
|
165
|
-
function
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
i0.ɵɵ
|
|
170
|
-
|
|
273
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_12_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
274
|
+
i0.ɵɵelement(0, "i", 123);
|
|
275
|
+
} }
|
|
276
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_12_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
277
|
+
i0.ɵɵtext(0, " Remove ");
|
|
278
|
+
} }
|
|
279
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
280
|
+
const _r12 = i0.ɵɵgetCurrentView();
|
|
281
|
+
i0.ɵɵelementStart(0, "div", 120);
|
|
282
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_12_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r12); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
283
|
+
i0.ɵɵelementStart(1, "span", 121);
|
|
284
|
+
i0.ɵɵtext(2, "Remove from suite?");
|
|
285
|
+
i0.ɵɵelementEnd();
|
|
286
|
+
i0.ɵɵelementStart(3, "button", 122);
|
|
287
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_12_Template_button_click_3_listener($event) { i0.ɵɵrestoreView(_r12); const test_r11 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.confirmRemoveTest(test_r11, $event)); });
|
|
288
|
+
i0.ɵɵconditionalCreate(4, MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_12_Conditional_4_Template, 1, 0, "i", 123)(5, MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_12_Conditional_5_Template, 1, 0);
|
|
289
|
+
i0.ɵɵelementEnd();
|
|
290
|
+
i0.ɵɵelementStart(6, "button", 124);
|
|
291
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_12_Template_button_click_6_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.cancelRemoveTest($event)); });
|
|
292
|
+
i0.ɵɵtext(7, " Cancel ");
|
|
293
|
+
i0.ɵɵelementEnd()();
|
|
294
|
+
} if (rf & 2) {
|
|
295
|
+
const ctx_r0 = i0.ɵɵnextContext(4);
|
|
296
|
+
i0.ɵɵadvance(3);
|
|
297
|
+
i0.ɵɵproperty("disabled", ctx_r0.isRemovingTest);
|
|
298
|
+
i0.ɵɵadvance();
|
|
299
|
+
i0.ɵɵconditional(ctx_r0.isRemovingTest ? 4 : 5);
|
|
300
|
+
i0.ɵɵadvance(2);
|
|
301
|
+
i0.ɵɵproperty("disabled", ctx_r0.isRemovingTest);
|
|
302
|
+
} }
|
|
303
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
304
|
+
const _r13 = i0.ɵɵgetCurrentView();
|
|
305
|
+
i0.ɵɵelementStart(0, "button", 125);
|
|
306
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_13_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r13); const test_r11 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.requestRemoveTest(test_r11, $event)); });
|
|
307
|
+
i0.ɵɵelement(1, "i", 91);
|
|
171
308
|
i0.ɵɵelementEnd();
|
|
172
|
-
i0.ɵɵelementStart(
|
|
173
|
-
i0.ɵɵ
|
|
309
|
+
i0.ɵɵelementStart(2, "i", 126);
|
|
310
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_13_Template_i_click_2_listener() { i0.ɵɵrestoreView(_r13); const test_r11 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.openTest(test_r11.TestID)); });
|
|
174
311
|
i0.ɵɵelementEnd();
|
|
175
|
-
|
|
176
|
-
|
|
312
|
+
} }
|
|
313
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
314
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
315
|
+
i0.ɵɵelementStart(0, "div", 110)(1, "span", 111);
|
|
316
|
+
i0.ɵɵelement(2, "i", 112);
|
|
177
317
|
i0.ɵɵelementEnd();
|
|
178
|
-
i0.ɵɵelementStart(
|
|
179
|
-
i0.ɵɵ
|
|
318
|
+
i0.ɵɵelementStart(3, "div", 113);
|
|
319
|
+
i0.ɵɵtext(4);
|
|
320
|
+
i0.ɵɵelementEnd();
|
|
321
|
+
i0.ɵɵelementStart(5, "div", 114);
|
|
322
|
+
i0.ɵɵelement(6, "i", 33);
|
|
323
|
+
i0.ɵɵelementEnd();
|
|
324
|
+
i0.ɵɵelementStart(7, "div", 115);
|
|
325
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Template_div_click_7_listener() { const test_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.openTest(test_r11.TestID)); });
|
|
326
|
+
i0.ɵɵelementStart(8, "div", 116);
|
|
327
|
+
i0.ɵɵtext(9);
|
|
328
|
+
i0.ɵɵelementEnd();
|
|
329
|
+
i0.ɵɵelementStart(10, "div", 117);
|
|
330
|
+
i0.ɵɵconditionalCreate(11, MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_11_Template, 3, 1, "span");
|
|
180
331
|
i0.ɵɵelementEnd()();
|
|
181
|
-
i0.ɵɵ
|
|
332
|
+
i0.ɵɵconditionalCreate(12, MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_12_Template, 8, 3, "div", 118)(13, MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Conditional_13_Template, 3, 0);
|
|
182
333
|
i0.ɵɵelementEnd();
|
|
183
334
|
} if (rf & 2) {
|
|
184
|
-
const
|
|
185
|
-
i0.ɵɵ
|
|
186
|
-
i0.ɵɵ
|
|
335
|
+
const test_r11 = ctx.$implicit;
|
|
336
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
337
|
+
i0.ɵɵproperty("cdkDragDisabled", ctx_r0.isReorderingTests || ctx_r0.isRemovingTest);
|
|
338
|
+
i0.ɵɵadvance(4);
|
|
339
|
+
i0.ɵɵtextInterpolate(test_r11.Sequence);
|
|
187
340
|
i0.ɵɵadvance(5);
|
|
188
|
-
i0.ɵɵtextInterpolate(
|
|
341
|
+
i0.ɵɵtextInterpolate(test_r11.Test);
|
|
189
342
|
i0.ɵɵadvance(2);
|
|
190
|
-
i0.ɵɵconditional(
|
|
343
|
+
i0.ɵɵconditional(test_r11.Status ? 11 : -1);
|
|
344
|
+
i0.ɵɵadvance();
|
|
345
|
+
i0.ɵɵconditional(ctx_r0.confirmingRemoveSuiteTestId === test_r11.ID ? 12 : 13);
|
|
191
346
|
} }
|
|
192
|
-
function
|
|
193
|
-
i0.ɵɵ
|
|
194
|
-
i0.ɵɵ
|
|
347
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
348
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
349
|
+
i0.ɵɵelementStart(0, "div", 109);
|
|
350
|
+
i0.ɵɵlistener("cdkDropListDropped", function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_Template_div_cdkDropListDropped_0_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onTestDrop($event)); });
|
|
351
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Template, 14, 5, "div", 110, _forTrack0);
|
|
195
352
|
i0.ɵɵelementEnd();
|
|
196
353
|
} if (rf & 2) {
|
|
197
354
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
198
355
|
i0.ɵɵadvance();
|
|
199
356
|
i0.ɵɵrepeater(ctx_r0.suiteTests);
|
|
200
357
|
} }
|
|
201
|
-
function
|
|
202
|
-
i0.ɵɵ
|
|
203
|
-
i0.ɵɵ
|
|
358
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
359
|
+
const _r14 = i0.ɵɵgetCurrentView();
|
|
360
|
+
i0.ɵɵelementStart(0, "div", 101)(1, "div", 127);
|
|
361
|
+
i0.ɵɵelement(2, "i", 33);
|
|
204
362
|
i0.ɵɵelementEnd();
|
|
205
363
|
i0.ɵɵelementStart(3, "h4");
|
|
206
364
|
i0.ɵɵtext(4, "No Tests in Suite");
|
|
207
365
|
i0.ɵɵelementEnd();
|
|
208
366
|
i0.ɵɵelementStart(5, "p");
|
|
209
367
|
i0.ɵɵtext(6, "Add tests to this suite to start running them together.");
|
|
368
|
+
i0.ɵɵelementEnd();
|
|
369
|
+
i0.ɵɵelementStart(7, "button", 25);
|
|
370
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_14_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r14); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.openAddTestsDialog()); });
|
|
371
|
+
i0.ɵɵelement(8, "i", 98);
|
|
372
|
+
i0.ɵɵtext(9, " Add tests ");
|
|
210
373
|
i0.ɵɵelementEnd()();
|
|
211
374
|
} }
|
|
212
|
-
function
|
|
213
|
-
i0.ɵɵ
|
|
214
|
-
i0.ɵɵ
|
|
215
|
-
i0.ɵɵ
|
|
216
|
-
i0.ɵɵ
|
|
375
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Template(rf, ctx) { if (rf & 1) {
|
|
376
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
377
|
+
i0.ɵɵelementStart(0, "div", 40)(1, "div", 92)(2, "div", 93)(3, "strong");
|
|
378
|
+
i0.ɵɵtext(4, "Suite tests");
|
|
379
|
+
i0.ɵɵelementEnd();
|
|
380
|
+
i0.ɵɵconditionalCreate(5, MJTestSuiteFormComponentExtended_Conditional_61_Conditional_5_Template, 2, 1, "span", 94);
|
|
381
|
+
i0.ɵɵelementStart(6, "span", 95);
|
|
382
|
+
i0.ɵɵtext(7, "Drag to reorder \u00B7 Hover a row to remove");
|
|
383
|
+
i0.ɵɵelementEnd()();
|
|
384
|
+
i0.ɵɵelementStart(8, "div", 96)(9, "button", 97);
|
|
385
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_61_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r8); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.openAddTestsDialog()); });
|
|
386
|
+
i0.ɵɵelement(10, "i", 98);
|
|
387
|
+
i0.ɵɵtext(11, " Add tests ");
|
|
388
|
+
i0.ɵɵelementEnd()()();
|
|
389
|
+
i0.ɵɵconditionalCreate(12, MJTestSuiteFormComponentExtended_Conditional_61_Conditional_12_Template, 4, 1, "div", 99);
|
|
390
|
+
i0.ɵɵconditionalCreate(13, MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_Template, 3, 0, "div", 100);
|
|
391
|
+
i0.ɵɵconditionalCreate(14, MJTestSuiteFormComponentExtended_Conditional_61_Conditional_14_Template, 10, 0, "div", 101);
|
|
217
392
|
i0.ɵɵelementEnd();
|
|
218
393
|
} if (rf & 2) {
|
|
219
394
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
395
|
+
i0.ɵɵadvance(5);
|
|
396
|
+
i0.ɵɵconditional(ctx_r0.testsLoaded ? 5 : -1);
|
|
397
|
+
i0.ɵɵadvance(4);
|
|
398
|
+
i0.ɵɵproperty("disabled", ctx_r0.isReorderingTests);
|
|
399
|
+
i0.ɵɵadvance(3);
|
|
400
|
+
i0.ɵɵconditional(ctx_r0.loadingTests ? 12 : -1);
|
|
220
401
|
i0.ɵɵadvance();
|
|
221
|
-
i0.ɵɵconditional(ctx_r0.loadingTests ?
|
|
222
|
-
i0.ɵɵadvance();
|
|
223
|
-
i0.ɵɵconditional(!ctx_r0.loadingTests && ctx_r0.suiteTests.length > 0 ? 2 : -1);
|
|
402
|
+
i0.ɵɵconditional(!ctx_r0.loadingTests && ctx_r0.suiteTests.length > 0 ? 13 : -1);
|
|
224
403
|
i0.ɵɵadvance();
|
|
225
|
-
i0.ɵɵconditional(ctx_r0.testsLoaded && !ctx_r0.loadingTests && ctx_r0.suiteTests.length === 0 ?
|
|
404
|
+
i0.ɵɵconditional(ctx_r0.testsLoaded && !ctx_r0.loadingTests && ctx_r0.suiteTests.length === 0 ? 14 : -1);
|
|
226
405
|
} }
|
|
227
|
-
function
|
|
228
|
-
i0.ɵɵelementStart(0, "div",
|
|
229
|
-
i0.ɵɵelement(1, "div",
|
|
230
|
-
i0.ɵɵelementStart(2, "div",
|
|
231
|
-
i0.ɵɵelement(3, "div",
|
|
406
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_1_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
407
|
+
i0.ɵɵelementStart(0, "div", 103);
|
|
408
|
+
i0.ɵɵelement(1, "div", 105);
|
|
409
|
+
i0.ɵɵelementStart(2, "div", 106);
|
|
410
|
+
i0.ɵɵelement(3, "div", 107)(4, "div", 108);
|
|
232
411
|
i0.ɵɵelementEnd()();
|
|
233
412
|
} }
|
|
234
|
-
function
|
|
235
|
-
i0.ɵɵelementStart(0, "div",
|
|
236
|
-
i0.ɵɵrepeaterCreate(2,
|
|
413
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
414
|
+
i0.ɵɵelementStart(0, "div", 99)(1, "div", 102);
|
|
415
|
+
i0.ɵɵrepeaterCreate(2, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_1_For_3_Template, 5, 0, "div", 103, i0.ɵɵrepeaterTrackByIdentity);
|
|
237
416
|
i0.ɵɵelementEnd()();
|
|
238
417
|
} if (rf & 2) {
|
|
239
418
|
i0.ɵɵadvance(2);
|
|
240
419
|
i0.ɵɵrepeater(i0.ɵɵpureFunction0(0, _c2));
|
|
241
420
|
} }
|
|
242
|
-
function
|
|
421
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
243
422
|
i0.ɵɵelementStart(0, "span");
|
|
244
|
-
i0.ɵɵelement(1, "i",
|
|
423
|
+
i0.ɵɵelement(1, "i", 145);
|
|
245
424
|
i0.ɵɵtext(2);
|
|
246
425
|
i0.ɵɵelementEnd();
|
|
247
426
|
} if (rf & 2) {
|
|
248
|
-
const
|
|
427
|
+
const run_r16 = i0.ɵɵnextContext().$implicit;
|
|
249
428
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
250
429
|
i0.ɵɵadvance(2);
|
|
251
|
-
i0.ɵɵtextInterpolate3(" ",
|
|
430
|
+
i0.ɵɵtextInterpolate3(" ", run_r16.PassedTests, "/", run_r16.TotalTests, " (", ctx_r0.getPassRate(run_r16).toFixed(0), "%) ");
|
|
252
431
|
} }
|
|
253
|
-
function
|
|
254
|
-
i0.ɵɵelementStart(0, "span",
|
|
255
|
-
i0.ɵɵelement(1, "i",
|
|
432
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
433
|
+
i0.ɵɵelementStart(0, "span", 146);
|
|
434
|
+
i0.ɵɵelement(1, "i", 132);
|
|
256
435
|
i0.ɵɵelementEnd();
|
|
257
436
|
} if (rf & 2) {
|
|
258
|
-
const
|
|
259
|
-
i0.ɵɵclassMap("status-" +
|
|
437
|
+
const run_r16 = i0.ɵɵnextContext().$implicit;
|
|
438
|
+
i0.ɵɵclassMap("status-" + run_r16.Status.toLowerCase());
|
|
260
439
|
i0.ɵɵadvance();
|
|
261
|
-
i0.ɵɵclassProp("fa-circle-check",
|
|
440
|
+
i0.ɵɵclassProp("fa-circle-check", run_r16.Status === "Completed")("fa-circle-xmark", run_r16.Status === "Failed")("fa-spinner", run_r16.Status === "Running")("fa-clock", run_r16.Status === "Pending")("fa-ban", run_r16.Status === "Cancelled");
|
|
262
441
|
} }
|
|
263
|
-
function
|
|
264
|
-
i0.ɵɵelementStart(0, "span",
|
|
265
|
-
i0.ɵɵelement(1, "i",
|
|
266
|
-
i0.ɵɵelementStart(2, "span",
|
|
267
|
-
i0.ɵɵelement(3, "i",
|
|
442
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
443
|
+
i0.ɵɵelementStart(0, "span", 141);
|
|
444
|
+
i0.ɵɵelement(1, "i", 147);
|
|
445
|
+
i0.ɵɵelementStart(2, "span", 148);
|
|
446
|
+
i0.ɵɵelement(3, "i", 149);
|
|
268
447
|
i0.ɵɵelementEnd()();
|
|
269
448
|
} }
|
|
270
|
-
function
|
|
271
|
-
i0.ɵɵelementStart(0, "span",
|
|
272
|
-
i0.ɵɵelement(1, "i",
|
|
449
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
450
|
+
i0.ɵɵelementStart(0, "span", 150);
|
|
451
|
+
i0.ɵɵelement(1, "i", 151);
|
|
273
452
|
i0.ɵɵelementStart(2, "span");
|
|
274
453
|
i0.ɵɵtext(3);
|
|
275
454
|
i0.ɵɵelementEnd()();
|
|
276
455
|
} if (rf & 2) {
|
|
277
|
-
const
|
|
456
|
+
const run_r16 = i0.ɵɵnextContext().$implicit;
|
|
278
457
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
279
|
-
i0.ɵɵclassProp("high", ctx_r0.getPassRate(
|
|
458
|
+
i0.ɵɵclassProp("high", ctx_r0.getPassRate(run_r16) >= 80)("medium", ctx_r0.getPassRate(run_r16) >= 50 && ctx_r0.getPassRate(run_r16) < 80)("low", ctx_r0.getPassRate(run_r16) < 50);
|
|
280
459
|
i0.ɵɵadvance(3);
|
|
281
|
-
i0.ɵɵtextInterpolate1("", ctx_r0.getPassRate(
|
|
460
|
+
i0.ɵɵtextInterpolate1("", ctx_r0.getPassRate(run_r16).toFixed(0), "%");
|
|
282
461
|
} }
|
|
283
|
-
function
|
|
284
|
-
i0.ɵɵelementStart(0, "span",
|
|
462
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_18_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
463
|
+
i0.ɵɵelementStart(0, "span", 152);
|
|
285
464
|
i0.ɵɵtext(1);
|
|
286
465
|
i0.ɵɵelementEnd();
|
|
287
466
|
} if (rf & 2) {
|
|
288
|
-
const
|
|
467
|
+
const tag_r17 = ctx.$implicit;
|
|
289
468
|
i0.ɵɵadvance();
|
|
290
|
-
i0.ɵɵtextInterpolate(
|
|
469
|
+
i0.ɵɵtextInterpolate(tag_r17);
|
|
291
470
|
} }
|
|
292
|
-
function
|
|
293
|
-
i0.ɵɵelementStart(0, "div",
|
|
294
|
-
i0.ɵɵrepeaterCreate(1,
|
|
471
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
472
|
+
i0.ɵɵelementStart(0, "div", 143);
|
|
473
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_18_For_2_Template, 2, 1, "span", 152, i0.ɵɵrepeaterTrackByIdentity);
|
|
295
474
|
i0.ɵɵelementEnd();
|
|
296
475
|
} if (rf & 2) {
|
|
297
|
-
const
|
|
476
|
+
const run_r16 = i0.ɵɵnextContext().$implicit;
|
|
298
477
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
299
478
|
i0.ɵɵadvance();
|
|
300
|
-
i0.ɵɵrepeater(ctx_r0.getRunTags(
|
|
479
|
+
i0.ɵɵrepeater(ctx_r0.getRunTags(run_r16));
|
|
301
480
|
} }
|
|
302
|
-
function
|
|
303
|
-
const
|
|
304
|
-
i0.ɵɵelementStart(0, "div",
|
|
305
|
-
i0.ɵɵlistener("click", function
|
|
306
|
-
i0.ɵɵelementStart(1, "div",
|
|
307
|
-
i0.ɵɵelement(2, "i",
|
|
308
|
-
i0.ɵɵelementEnd();
|
|
309
|
-
i0.ɵɵelementStart(3, "div",
|
|
481
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
482
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
483
|
+
i0.ɵɵelementStart(0, "div", 130);
|
|
484
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Template_div_click_0_listener() { const run_r16 = i0.ɵɵrestoreView(_r15).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.openSuiteRun(run_r16.ID)); });
|
|
485
|
+
i0.ɵɵelementStart(1, "div", 131);
|
|
486
|
+
i0.ɵɵelement(2, "i", 132);
|
|
487
|
+
i0.ɵɵelementEnd();
|
|
488
|
+
i0.ɵɵelementStart(3, "div", 133)(4, "div", 134)(5, "span", 135);
|
|
310
489
|
i0.ɵɵtext(6);
|
|
311
490
|
i0.ɵɵelementEnd();
|
|
312
|
-
i0.ɵɵelementStart(7, "span",
|
|
491
|
+
i0.ɵɵelementStart(7, "span", 136);
|
|
313
492
|
i0.ɵɵtext(8);
|
|
314
493
|
i0.ɵɵelementEnd()();
|
|
315
|
-
i0.ɵɵelementStart(9, "div",
|
|
316
|
-
i0.ɵɵelement(11, "i",
|
|
494
|
+
i0.ɵɵelementStart(9, "div", 137)(10, "span");
|
|
495
|
+
i0.ɵɵelement(11, "i", 138);
|
|
317
496
|
i0.ɵɵtext(12);
|
|
318
497
|
i0.ɵɵelementEnd();
|
|
319
|
-
i0.ɵɵconditionalCreate(13,
|
|
498
|
+
i0.ɵɵconditionalCreate(13, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_13_Template, 3, 3, "span");
|
|
320
499
|
i0.ɵɵelementEnd();
|
|
321
|
-
i0.ɵɵelementStart(14, "div",
|
|
322
|
-
i0.ɵɵconditionalCreate(15,
|
|
323
|
-
i0.ɵɵconditionalCreate(16,
|
|
324
|
-
i0.ɵɵconditionalCreate(17,
|
|
500
|
+
i0.ɵɵelementStart(14, "div", 139);
|
|
501
|
+
i0.ɵɵconditionalCreate(15, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_15_Template, 2, 12, "span", 140);
|
|
502
|
+
i0.ɵɵconditionalCreate(16, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_16_Template, 4, 0, "span", 141);
|
|
503
|
+
i0.ɵɵconditionalCreate(17, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_17_Template, 4, 7, "span", 142);
|
|
325
504
|
i0.ɵɵelementEnd();
|
|
326
|
-
i0.ɵɵconditionalCreate(18,
|
|
505
|
+
i0.ɵɵconditionalCreate(18, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Conditional_18_Template, 3, 0, "div", 143);
|
|
327
506
|
i0.ɵɵelementEnd();
|
|
328
|
-
i0.ɵɵelement(19, "i",
|
|
507
|
+
i0.ɵɵelement(19, "i", 144);
|
|
329
508
|
i0.ɵɵelementEnd();
|
|
330
509
|
} if (rf & 2) {
|
|
331
|
-
const
|
|
510
|
+
const run_r16 = ctx.$implicit;
|
|
332
511
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
333
512
|
i0.ɵɵadvance();
|
|
334
|
-
i0.ɵɵstyleProp("background-color", ctx_r0.getRunStatusColor(
|
|
513
|
+
i0.ɵɵstyleProp("background-color", ctx_r0.getRunStatusColor(run_r16.Status));
|
|
335
514
|
i0.ɵɵadvance();
|
|
336
|
-
i0.ɵɵclassProp("fa-check",
|
|
515
|
+
i0.ɵɵclassProp("fa-check", run_r16.Status === "Completed")("fa-times", run_r16.Status === "Failed")("fa-spinner", run_r16.Status === "Running")("fa-clock", run_r16.Status === "Pending")("fa-ban", run_r16.Status === "Cancelled");
|
|
337
516
|
i0.ɵɵadvance(4);
|
|
338
|
-
i0.ɵɵtextInterpolate1("Run #",
|
|
517
|
+
i0.ɵɵtextInterpolate1("Run #", run_r16.ID.substring(0, 8));
|
|
339
518
|
i0.ɵɵadvance();
|
|
340
|
-
i0.ɵɵstyleProp("color", ctx_r0.getRunStatusColor(
|
|
519
|
+
i0.ɵɵstyleProp("color", ctx_r0.getRunStatusColor(run_r16.Status));
|
|
341
520
|
i0.ɵɵadvance();
|
|
342
|
-
i0.ɵɵtextInterpolate(
|
|
521
|
+
i0.ɵɵtextInterpolate(run_r16.Status);
|
|
343
522
|
i0.ɵɵadvance(4);
|
|
344
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r0.getRelativeTime(
|
|
523
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r0.getRelativeTime(run_r16.StartedAt));
|
|
345
524
|
i0.ɵɵadvance();
|
|
346
|
-
i0.ɵɵconditional(
|
|
525
|
+
i0.ɵɵconditional(run_r16.TotalTests ? 13 : -1);
|
|
347
526
|
i0.ɵɵadvance(2);
|
|
348
527
|
i0.ɵɵconditional(ctx_r0.evalPreferences.showExecution ? 15 : -1);
|
|
349
528
|
i0.ɵɵadvance();
|
|
350
529
|
i0.ɵɵconditional(ctx_r0.evalPreferences.showHuman ? 16 : -1);
|
|
351
530
|
i0.ɵɵadvance();
|
|
352
|
-
i0.ɵɵconditional(ctx_r0.evalPreferences.showAuto &&
|
|
531
|
+
i0.ɵɵconditional(ctx_r0.evalPreferences.showAuto && run_r16.TotalTests ? 17 : -1);
|
|
353
532
|
i0.ɵɵadvance();
|
|
354
|
-
i0.ɵɵconditional(ctx_r0.getRunTags(
|
|
533
|
+
i0.ɵɵconditional(ctx_r0.getRunTags(run_r16).length > 0 ? 18 : -1);
|
|
355
534
|
} }
|
|
356
|
-
function
|
|
357
|
-
i0.ɵɵelementStart(0, "div",
|
|
358
|
-
i0.ɵɵrepeaterCreate(1,
|
|
535
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
536
|
+
i0.ɵɵelementStart(0, "div", 128);
|
|
537
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Template, 20, 22, "div", 129, i0.ɵɵrepeaterTrackByIdentity);
|
|
359
538
|
i0.ɵɵelementEnd();
|
|
360
539
|
} if (rf & 2) {
|
|
361
540
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
362
541
|
i0.ɵɵadvance();
|
|
363
542
|
i0.ɵɵrepeater(ctx_r0.suiteRuns);
|
|
364
543
|
} }
|
|
365
|
-
function
|
|
366
|
-
const
|
|
367
|
-
i0.ɵɵelementStart(0, "div",
|
|
368
|
-
i0.ɵɵelement(2, "i",
|
|
544
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
545
|
+
const _r18 = i0.ɵɵgetCurrentView();
|
|
546
|
+
i0.ɵɵelementStart(0, "div", 101)(1, "div", 127);
|
|
547
|
+
i0.ɵɵelement(2, "i", 153);
|
|
369
548
|
i0.ɵɵelementEnd();
|
|
370
549
|
i0.ɵɵelementStart(3, "h4");
|
|
371
550
|
i0.ɵɵtext(4, "No Suite Runs Yet");
|
|
@@ -373,17 +552,17 @@ function MJTestSuiteFormComponentExtended_Conditional_60_Conditional_3_Template(
|
|
|
373
552
|
i0.ɵɵelementStart(5, "p");
|
|
374
553
|
i0.ɵɵtext(6, "Run this suite to see execution history and results here.");
|
|
375
554
|
i0.ɵɵelementEnd();
|
|
376
|
-
i0.ɵɵelementStart(7, "button",
|
|
377
|
-
i0.ɵɵlistener("click", function
|
|
378
|
-
i0.ɵɵelement(8, "i",
|
|
555
|
+
i0.ɵɵelementStart(7, "button", 25);
|
|
556
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_3_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r18); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.runSuite()); });
|
|
557
|
+
i0.ɵɵelement(8, "i", 26);
|
|
379
558
|
i0.ɵɵtext(9, " Run Suite Now ");
|
|
380
559
|
i0.ɵɵelementEnd()();
|
|
381
560
|
} }
|
|
382
|
-
function
|
|
383
|
-
i0.ɵɵelementStart(0, "div",
|
|
384
|
-
i0.ɵɵconditionalCreate(1,
|
|
385
|
-
i0.ɵɵconditionalCreate(2,
|
|
386
|
-
i0.ɵɵconditionalCreate(3,
|
|
561
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Template(rf, ctx) { if (rf & 1) {
|
|
562
|
+
i0.ɵɵelementStart(0, "div", 41);
|
|
563
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_1_Template, 4, 1, "div", 99);
|
|
564
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_Template, 3, 0, "div", 128);
|
|
565
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_3_Template, 10, 0, "div", 101);
|
|
387
566
|
i0.ɵɵelementEnd();
|
|
388
567
|
} if (rf & 2) {
|
|
389
568
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -394,12 +573,12 @@ function MJTestSuiteFormComponentExtended_Conditional_60_Template(rf, ctx) { if
|
|
|
394
573
|
i0.ɵɵadvance();
|
|
395
574
|
i0.ɵɵconditional(ctx_r0.runsLoaded && !ctx_r0.loadingRuns && ctx_r0.suiteRuns.length === 0 ? 3 : -1);
|
|
396
575
|
} }
|
|
397
|
-
function
|
|
398
|
-
i0.ɵɵelementStart(0, "div",
|
|
399
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
576
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
577
|
+
i0.ɵɵelementStart(0, "div", 99);
|
|
578
|
+
i0.ɵɵelement(1, "mj-loading", 154);
|
|
400
579
|
i0.ɵɵelementEnd();
|
|
401
580
|
} }
|
|
402
|
-
function
|
|
581
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_19_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
403
582
|
i0.ɵɵelementStart(0, "span");
|
|
404
583
|
i0.ɵɵtext(1);
|
|
405
584
|
i0.ɵɵelementEnd();
|
|
@@ -408,10 +587,10 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
408
587
|
i0.ɵɵadvance();
|
|
409
588
|
i0.ɵɵtextInterpolate1(" \u00B7 ", ctx_r0.selectedTags.length, " tags");
|
|
410
589
|
} }
|
|
411
|
-
function
|
|
412
|
-
i0.ɵɵelementStart(0, "span",
|
|
590
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
591
|
+
i0.ɵɵelementStart(0, "span", 165);
|
|
413
592
|
i0.ɵɵtext(1);
|
|
414
|
-
i0.ɵɵconditionalCreate(2,
|
|
593
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_19_Conditional_2_Template, 2, 1, "span");
|
|
415
594
|
i0.ɵɵelementEnd();
|
|
416
595
|
} if (rf & 2) {
|
|
417
596
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
@@ -420,8 +599,8 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
420
599
|
i0.ɵɵadvance();
|
|
421
600
|
i0.ɵɵconditional(ctx_r0.selectedTags.length > 0 ? 2 : -1);
|
|
422
601
|
} }
|
|
423
|
-
function
|
|
424
|
-
i0.ɵɵelementStart(0, "span",
|
|
602
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Conditional_13_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
603
|
+
i0.ɵɵelementStart(0, "span", 170);
|
|
425
604
|
i0.ɵɵtext(1);
|
|
426
605
|
i0.ɵɵelementEnd();
|
|
427
606
|
} if (rf & 2) {
|
|
@@ -429,37 +608,37 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
429
608
|
i0.ɵɵadvance();
|
|
430
609
|
i0.ɵɵtextInterpolate1("(", ctx_r0.selectedTags.length, " selected)");
|
|
431
610
|
} }
|
|
432
|
-
function
|
|
433
|
-
i0.ɵɵelement(0, "i",
|
|
611
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Conditional_13_For_9_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
612
|
+
i0.ɵɵelement(0, "i", 175);
|
|
434
613
|
} }
|
|
435
|
-
function
|
|
436
|
-
const
|
|
437
|
-
i0.ɵɵelementStart(0, "button",
|
|
438
|
-
i0.ɵɵlistener("click", function
|
|
439
|
-
i0.ɵɵconditionalCreate(1,
|
|
614
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Conditional_13_For_9_Template(rf, ctx) { if (rf & 1) {
|
|
615
|
+
const _r22 = i0.ɵɵgetCurrentView();
|
|
616
|
+
i0.ɵɵelementStart(0, "button", 174);
|
|
617
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Conditional_13_For_9_Template_button_click_0_listener() { const tag_r23 = i0.ɵɵrestoreView(_r22).$implicit; const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.toggleTagFilter(tag_r23)); });
|
|
618
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Conditional_13_For_9_Conditional_1_Template, 1, 0, "i", 175);
|
|
440
619
|
i0.ɵɵtext(2);
|
|
441
620
|
i0.ɵɵelementEnd();
|
|
442
621
|
} if (rf & 2) {
|
|
443
|
-
const
|
|
622
|
+
const tag_r23 = ctx.$implicit;
|
|
444
623
|
const ctx_r0 = i0.ɵɵnextContext(5);
|
|
445
|
-
i0.ɵɵclassProp("active", ctx_r0.isTagSelected(
|
|
624
|
+
i0.ɵɵclassProp("active", ctx_r0.isTagSelected(tag_r23));
|
|
446
625
|
i0.ɵɵadvance();
|
|
447
|
-
i0.ɵɵconditional(ctx_r0.isTagSelected(
|
|
626
|
+
i0.ɵɵconditional(ctx_r0.isTagSelected(tag_r23) ? 1 : -1);
|
|
448
627
|
i0.ɵɵadvance();
|
|
449
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
628
|
+
i0.ɵɵtextInterpolate1(" ", tag_r23, " ");
|
|
450
629
|
} }
|
|
451
|
-
function
|
|
452
|
-
const
|
|
453
|
-
i0.ɵɵelementStart(0, "div",
|
|
630
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
631
|
+
const _r21 = i0.ɵɵgetCurrentView();
|
|
632
|
+
i0.ɵɵelementStart(0, "div", 167)(1, "label");
|
|
454
633
|
i0.ɵɵtext(2, "Filter by Tag ");
|
|
455
|
-
i0.ɵɵconditionalCreate(3,
|
|
634
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Conditional_13_Conditional_3_Template, 2, 1, "span", 170);
|
|
456
635
|
i0.ɵɵelementEnd();
|
|
457
|
-
i0.ɵɵelementStart(4, "div",
|
|
458
|
-
i0.ɵɵlistener("click", function
|
|
459
|
-
i0.ɵɵelement(6, "i",
|
|
636
|
+
i0.ɵɵelementStart(4, "div", 171)(5, "button", 172);
|
|
637
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Conditional_13_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r21); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.toggleTagFilter(null)); });
|
|
638
|
+
i0.ɵɵelement(6, "i", 11);
|
|
460
639
|
i0.ɵɵtext(7, " All Tags ");
|
|
461
640
|
i0.ɵɵelementEnd();
|
|
462
|
-
i0.ɵɵrepeaterCreate(8,
|
|
641
|
+
i0.ɵɵrepeaterCreate(8, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Conditional_13_For_9_Template, 3, 4, "button", 173, i0.ɵɵrepeaterTrackByIdentity);
|
|
463
642
|
i0.ɵɵelementEnd()();
|
|
464
643
|
} if (rf & 2) {
|
|
465
644
|
const ctx_r0 = i0.ɵɵnextContext(4);
|
|
@@ -470,28 +649,28 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
470
649
|
i0.ɵɵadvance(3);
|
|
471
650
|
i0.ɵɵrepeater(ctx_r0.uniqueTags);
|
|
472
651
|
} }
|
|
473
|
-
function
|
|
474
|
-
const
|
|
475
|
-
i0.ɵɵelementStart(0, "div",
|
|
652
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
653
|
+
const _r20 = i0.ɵɵgetCurrentView();
|
|
654
|
+
i0.ɵɵelementStart(0, "div", 166)(1, "div", 167)(2, "label");
|
|
476
655
|
i0.ɵɵtext(3, "Time Range");
|
|
477
656
|
i0.ɵɵelementEnd();
|
|
478
|
-
i0.ɵɵelementStart(4, "div",
|
|
479
|
-
i0.ɵɵlistener("click", function
|
|
657
|
+
i0.ɵɵelementStart(4, "div", 168)(5, "button", 169);
|
|
658
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.setTimeRange("7d")); });
|
|
480
659
|
i0.ɵɵtext(6, "7 Days");
|
|
481
660
|
i0.ɵɵelementEnd();
|
|
482
|
-
i0.ɵɵelementStart(7, "button",
|
|
483
|
-
i0.ɵɵlistener("click", function
|
|
661
|
+
i0.ɵɵelementStart(7, "button", 169);
|
|
662
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.setTimeRange("30d")); });
|
|
484
663
|
i0.ɵɵtext(8, "30 Days");
|
|
485
664
|
i0.ɵɵelementEnd();
|
|
486
|
-
i0.ɵɵelementStart(9, "button",
|
|
487
|
-
i0.ɵɵlistener("click", function
|
|
665
|
+
i0.ɵɵelementStart(9, "button", 169);
|
|
666
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.setTimeRange("90d")); });
|
|
488
667
|
i0.ɵɵtext(10, "90 Days");
|
|
489
668
|
i0.ɵɵelementEnd();
|
|
490
|
-
i0.ɵɵelementStart(11, "button",
|
|
491
|
-
i0.ɵɵlistener("click", function
|
|
669
|
+
i0.ɵɵelementStart(11, "button", 169);
|
|
670
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.setTimeRange("all")); });
|
|
492
671
|
i0.ɵɵtext(12, "All Time");
|
|
493
672
|
i0.ɵɵelementEnd()()();
|
|
494
|
-
i0.ɵɵconditionalCreate(13,
|
|
673
|
+
i0.ɵɵconditionalCreate(13, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Conditional_13_Template, 10, 3, "div", 167);
|
|
495
674
|
i0.ɵɵelementEnd();
|
|
496
675
|
} if (rf & 2) {
|
|
497
676
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
@@ -506,37 +685,37 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
506
685
|
i0.ɵɵadvance(2);
|
|
507
686
|
i0.ɵɵconditional(ctx_r0.uniqueTags.length > 0 ? 13 : -1);
|
|
508
687
|
} }
|
|
509
|
-
function
|
|
510
|
-
i0.ɵɵelementStart(0, "span",
|
|
688
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_22_For_60_For_21_Template(rf, ctx) { if (rf & 1) {
|
|
689
|
+
i0.ɵɵelementStart(0, "span", 198);
|
|
511
690
|
i0.ɵɵtext(1);
|
|
512
691
|
i0.ɵɵelementEnd();
|
|
513
692
|
} if (rf & 2) {
|
|
514
|
-
const
|
|
693
|
+
const tag_r26 = ctx.$implicit;
|
|
515
694
|
i0.ɵɵadvance();
|
|
516
|
-
i0.ɵɵtextInterpolate(
|
|
695
|
+
i0.ɵɵtextInterpolate(tag_r26);
|
|
517
696
|
} }
|
|
518
|
-
function
|
|
519
|
-
i0.ɵɵelementStart(0, "span",
|
|
697
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_22_For_60_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
698
|
+
i0.ɵɵelementStart(0, "span", 199);
|
|
520
699
|
i0.ɵɵtext(1);
|
|
521
700
|
i0.ɵɵelementEnd();
|
|
522
701
|
} if (rf & 2) {
|
|
523
|
-
const
|
|
702
|
+
const dp_r25 = i0.ɵɵnextContext().$implicit;
|
|
524
703
|
i0.ɵɵadvance();
|
|
525
|
-
i0.ɵɵtextInterpolate1("+",
|
|
704
|
+
i0.ɵɵtextInterpolate1("+", dp_r25.tags.length - 2);
|
|
526
705
|
} }
|
|
527
|
-
function
|
|
528
|
-
const
|
|
529
|
-
i0.ɵɵelementStart(0, "tr",
|
|
530
|
-
i0.ɵɵlistener("click", function
|
|
706
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_22_For_60_Template(rf, ctx) { if (rf & 1) {
|
|
707
|
+
const _r24 = i0.ɵɵgetCurrentView();
|
|
708
|
+
i0.ɵɵelementStart(0, "tr", 193);
|
|
709
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_22_For_60_Template_tr_click_0_listener() { const dp_r25 = i0.ɵɵrestoreView(_r24).$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.openSuiteRun(dp_r25.runId)); });
|
|
531
710
|
i0.ɵɵelementStart(1, "td");
|
|
532
711
|
i0.ɵɵtext(2);
|
|
533
712
|
i0.ɵɵpipe(3, "date");
|
|
534
713
|
i0.ɵɵelementEnd();
|
|
535
|
-
i0.ɵɵelementStart(4, "td")(5, "span",
|
|
714
|
+
i0.ɵɵelementStart(4, "td")(5, "span", 194);
|
|
536
715
|
i0.ɵɵtext(6);
|
|
537
716
|
i0.ɵɵelementEnd()();
|
|
538
|
-
i0.ɵɵelementStart(7, "td")(8, "div",
|
|
539
|
-
i0.ɵɵelement(9, "div",
|
|
717
|
+
i0.ɵɵelementStart(7, "td")(8, "div", 195);
|
|
718
|
+
i0.ɵɵelement(9, "div", 196);
|
|
540
719
|
i0.ɵɵelementStart(10, "span");
|
|
541
720
|
i0.ɵɵtext(11);
|
|
542
721
|
i0.ɵɵelementEnd()()();
|
|
@@ -549,86 +728,86 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
549
728
|
i0.ɵɵelementStart(16, "td");
|
|
550
729
|
i0.ɵɵtext(17);
|
|
551
730
|
i0.ɵɵelementEnd();
|
|
552
|
-
i0.ɵɵelementStart(18, "td")(19, "div",
|
|
553
|
-
i0.ɵɵrepeaterCreate(20,
|
|
554
|
-
i0.ɵɵconditionalCreate(22,
|
|
731
|
+
i0.ɵɵelementStart(18, "td")(19, "div", 197);
|
|
732
|
+
i0.ɵɵrepeaterCreate(20, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_22_For_60_For_21_Template, 2, 1, "span", 198, i0.ɵɵrepeaterTrackByIdentity);
|
|
733
|
+
i0.ɵɵconditionalCreate(22, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_22_For_60_Conditional_22_Template, 2, 1, "span", 199);
|
|
555
734
|
i0.ɵɵelementEnd()()();
|
|
556
735
|
} if (rf & 2) {
|
|
557
|
-
const
|
|
736
|
+
const dp_r25 = ctx.$implicit;
|
|
558
737
|
const ctx_r0 = i0.ɵɵnextContext(4);
|
|
559
738
|
i0.ɵɵadvance(2);
|
|
560
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(3, 12,
|
|
739
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(3, 12, dp_r25.date, "short"));
|
|
561
740
|
i0.ɵɵadvance(3);
|
|
562
|
-
i0.ɵɵproperty("ngClass", "status-" +
|
|
741
|
+
i0.ɵɵproperty("ngClass", "status-" + dp_r25.status.toLowerCase());
|
|
563
742
|
i0.ɵɵadvance();
|
|
564
|
-
i0.ɵɵtextInterpolate(
|
|
743
|
+
i0.ɵɵtextInterpolate(dp_r25.status);
|
|
565
744
|
i0.ɵɵadvance(3);
|
|
566
|
-
i0.ɵɵstyleProp("width",
|
|
567
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction3(15, _c5,
|
|
745
|
+
i0.ɵɵstyleProp("width", dp_r25.passRate, "%");
|
|
746
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction3(15, _c5, dp_r25.passRate >= 80, dp_r25.passRate >= 50 && dp_r25.passRate < 80, dp_r25.passRate < 50));
|
|
568
747
|
i0.ɵɵadvance(2);
|
|
569
|
-
i0.ɵɵtextInterpolate1("",
|
|
748
|
+
i0.ɵɵtextInterpolate1("", dp_r25.passRate.toFixed(0), "%");
|
|
570
749
|
i0.ɵɵadvance(2);
|
|
571
|
-
i0.ɵɵtextInterpolate2("",
|
|
750
|
+
i0.ɵɵtextInterpolate2("", dp_r25.passedTests, "/", dp_r25.totalTests);
|
|
572
751
|
i0.ɵɵadvance(2);
|
|
573
|
-
i0.ɵɵtextInterpolate(ctx_r0.formatDuration(
|
|
752
|
+
i0.ɵɵtextInterpolate(ctx_r0.formatDuration(dp_r25.duration));
|
|
574
753
|
i0.ɵɵadvance(2);
|
|
575
|
-
i0.ɵɵtextInterpolate(ctx_r0.formatCost(
|
|
754
|
+
i0.ɵɵtextInterpolate(ctx_r0.formatCost(dp_r25.cost));
|
|
576
755
|
i0.ɵɵadvance(3);
|
|
577
|
-
i0.ɵɵrepeater(
|
|
756
|
+
i0.ɵɵrepeater(dp_r25.tags.slice(0, 2));
|
|
578
757
|
i0.ɵɵadvance(2);
|
|
579
|
-
i0.ɵɵconditional(
|
|
758
|
+
i0.ɵɵconditional(dp_r25.tags.length > 2 ? 22 : -1);
|
|
580
759
|
} }
|
|
581
|
-
function
|
|
582
|
-
i0.ɵɵelementStart(0, "div",
|
|
760
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_22_Conditional_61_Template(rf, ctx) { if (rf & 1) {
|
|
761
|
+
i0.ɵɵelementStart(0, "div", 192)(1, "p");
|
|
583
762
|
i0.ɵɵtext(2, "No runs match the current filters.");
|
|
584
763
|
i0.ɵɵelementEnd()();
|
|
585
764
|
} }
|
|
586
|
-
function
|
|
587
|
-
i0.ɵɵelementStart(0, "div",
|
|
588
|
-
i0.ɵɵelement(3, "i",
|
|
765
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
766
|
+
i0.ɵɵelementStart(0, "div", 176)(1, "div", 177)(2, "div", 178);
|
|
767
|
+
i0.ɵɵelement(3, "i", 153);
|
|
589
768
|
i0.ɵɵelementEnd();
|
|
590
|
-
i0.ɵɵelementStart(4, "div",
|
|
769
|
+
i0.ɵɵelementStart(4, "div", 179)(5, "div", 180);
|
|
591
770
|
i0.ɵɵtext(6);
|
|
592
771
|
i0.ɵɵelementEnd();
|
|
593
|
-
i0.ɵɵelementStart(7, "div",
|
|
772
|
+
i0.ɵɵelementStart(7, "div", 181);
|
|
594
773
|
i0.ɵɵtext(8, "Total Runs");
|
|
595
774
|
i0.ɵɵelementEnd()()();
|
|
596
|
-
i0.ɵɵelementStart(9, "div",
|
|
597
|
-
i0.ɵɵelement(11, "i",
|
|
775
|
+
i0.ɵɵelementStart(9, "div", 177)(10, "div", 182);
|
|
776
|
+
i0.ɵɵelement(11, "i", 145);
|
|
598
777
|
i0.ɵɵelementEnd();
|
|
599
|
-
i0.ɵɵelementStart(12, "div",
|
|
778
|
+
i0.ɵɵelementStart(12, "div", 179)(13, "div", 180);
|
|
600
779
|
i0.ɵɵtext(14);
|
|
601
780
|
i0.ɵɵelementEnd();
|
|
602
|
-
i0.ɵɵelementStart(15, "div",
|
|
781
|
+
i0.ɵɵelementStart(15, "div", 181);
|
|
603
782
|
i0.ɵɵtext(16, "Avg Pass Rate");
|
|
604
783
|
i0.ɵɵelementEnd();
|
|
605
|
-
i0.ɵɵelementStart(17, "div",
|
|
606
|
-
i0.ɵɵelement(18, "i",
|
|
784
|
+
i0.ɵɵelementStart(17, "div", 183);
|
|
785
|
+
i0.ɵɵelement(18, "i", 19);
|
|
607
786
|
i0.ɵɵtext(19);
|
|
608
787
|
i0.ɵɵelementEnd()()();
|
|
609
|
-
i0.ɵɵelementStart(20, "div",
|
|
610
|
-
i0.ɵɵelement(22, "i",
|
|
788
|
+
i0.ɵɵelementStart(20, "div", 177)(21, "div", 184);
|
|
789
|
+
i0.ɵɵelement(22, "i", 149);
|
|
611
790
|
i0.ɵɵelementEnd();
|
|
612
|
-
i0.ɵɵelementStart(23, "div",
|
|
791
|
+
i0.ɵɵelementStart(23, "div", 179)(24, "div", 180);
|
|
613
792
|
i0.ɵɵtext(25);
|
|
614
793
|
i0.ɵɵelementEnd();
|
|
615
|
-
i0.ɵɵelementStart(26, "div",
|
|
794
|
+
i0.ɵɵelementStart(26, "div", 181);
|
|
616
795
|
i0.ɵɵtext(27, "Avg Duration");
|
|
617
796
|
i0.ɵɵelementEnd()()();
|
|
618
|
-
i0.ɵɵelementStart(28, "div",
|
|
619
|
-
i0.ɵɵelement(30, "i",
|
|
797
|
+
i0.ɵɵelementStart(28, "div", 177)(29, "div", 185);
|
|
798
|
+
i0.ɵɵelement(30, "i", 186);
|
|
620
799
|
i0.ɵɵelementEnd();
|
|
621
|
-
i0.ɵɵelementStart(31, "div",
|
|
800
|
+
i0.ɵɵelementStart(31, "div", 179)(32, "div", 180);
|
|
622
801
|
i0.ɵɵtext(33);
|
|
623
802
|
i0.ɵɵelementEnd();
|
|
624
|
-
i0.ɵɵelementStart(34, "div",
|
|
803
|
+
i0.ɵɵelementStart(34, "div", 181);
|
|
625
804
|
i0.ɵɵtext(35, "Total Cost");
|
|
626
805
|
i0.ɵɵelementEnd()()()();
|
|
627
|
-
i0.ɵɵelementStart(36, "div",
|
|
628
|
-
i0.ɵɵelement(38, "i",
|
|
806
|
+
i0.ɵɵelementStart(36, "div", 187)(37, "h3");
|
|
807
|
+
i0.ɵɵelement(38, "i", 188);
|
|
629
808
|
i0.ɵɵtext(39, " Run History");
|
|
630
809
|
i0.ɵɵelementEnd();
|
|
631
|
-
i0.ɵɵelementStart(40, "div",
|
|
810
|
+
i0.ɵɵelementStart(40, "div", 189)(41, "table", 190)(42, "thead")(43, "tr")(44, "th");
|
|
632
811
|
i0.ɵɵtext(45, "Date");
|
|
633
812
|
i0.ɵɵelementEnd();
|
|
634
813
|
i0.ɵɵelementStart(46, "th");
|
|
@@ -650,9 +829,9 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
650
829
|
i0.ɵɵtext(57, "Tags");
|
|
651
830
|
i0.ɵɵelementEnd()()();
|
|
652
831
|
i0.ɵɵelementStart(58, "tbody");
|
|
653
|
-
i0.ɵɵrepeaterCreate(59,
|
|
832
|
+
i0.ɵɵrepeaterCreate(59, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_22_For_60_Template, 23, 19, "tr", 191, i0.ɵɵrepeaterTrackByIdentity);
|
|
654
833
|
i0.ɵɵelementEnd()()();
|
|
655
|
-
i0.ɵɵconditionalCreate(61,
|
|
834
|
+
i0.ɵɵconditionalCreate(61, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_22_Conditional_61_Template, 3, 0, "div", 192);
|
|
656
835
|
i0.ɵɵelementEnd();
|
|
657
836
|
} if (rf & 2) {
|
|
658
837
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
@@ -675,260 +854,260 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
675
854
|
i0.ɵɵadvance(2);
|
|
676
855
|
i0.ɵɵconditional(ctx_r0.getFilteredAnalyticsData().length === 0 ? 61 : -1);
|
|
677
856
|
} }
|
|
678
|
-
function
|
|
679
|
-
i0.ɵɵelementStart(0, "div",
|
|
680
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
857
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
858
|
+
i0.ɵɵelementStart(0, "div", 99);
|
|
859
|
+
i0.ɵɵelement(1, "mj-loading", 201);
|
|
681
860
|
i0.ɵɵelementEnd();
|
|
682
861
|
} }
|
|
683
|
-
function
|
|
684
|
-
const
|
|
685
|
-
i0.ɵɵelementStart(0, "button",
|
|
686
|
-
i0.ɵɵlistener("click", function
|
|
687
|
-
i0.ɵɵelement(1, "i",
|
|
862
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
863
|
+
const _r28 = i0.ɵɵgetCurrentView();
|
|
864
|
+
i0.ɵɵelementStart(0, "button", 223);
|
|
865
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_Conditional_9_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r28); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.clearMatrixFilter()); });
|
|
866
|
+
i0.ɵɵelement(1, "i", 91);
|
|
688
867
|
i0.ɵɵelementEnd();
|
|
689
868
|
} }
|
|
690
|
-
function
|
|
691
|
-
i0.ɵɵelementStart(0, "span",
|
|
869
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_26_Conditional_3_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
870
|
+
i0.ɵɵelementStart(0, "span", 229);
|
|
692
871
|
i0.ɵɵtext(1);
|
|
693
872
|
i0.ɵɵelementEnd();
|
|
694
873
|
} if (rf & 2) {
|
|
695
|
-
const
|
|
874
|
+
const tag_r31 = ctx.$implicit;
|
|
696
875
|
i0.ɵɵadvance();
|
|
697
|
-
i0.ɵɵtextInterpolate(
|
|
876
|
+
i0.ɵɵtextInterpolate(tag_r31);
|
|
698
877
|
} }
|
|
699
|
-
function
|
|
700
|
-
i0.ɵɵelementStart(0, "span",
|
|
878
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_26_Conditional_3_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
879
|
+
i0.ɵɵelementStart(0, "span", 230);
|
|
701
880
|
i0.ɵɵtext(1);
|
|
702
881
|
i0.ɵɵelementEnd();
|
|
703
882
|
} if (rf & 2) {
|
|
704
|
-
const
|
|
883
|
+
const run_r30 = i0.ɵɵnextContext(2).$implicit;
|
|
705
884
|
i0.ɵɵadvance();
|
|
706
|
-
i0.ɵɵtextInterpolate1("+",
|
|
885
|
+
i0.ɵɵtextInterpolate1("+", run_r30.tags.length - 2);
|
|
707
886
|
} }
|
|
708
|
-
function
|
|
709
|
-
i0.ɵɵelementStart(0, "div",
|
|
710
|
-
i0.ɵɵrepeaterCreate(1,
|
|
711
|
-
i0.ɵɵconditionalCreate(3,
|
|
887
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_26_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
888
|
+
i0.ɵɵelementStart(0, "div", 226);
|
|
889
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_26_Conditional_3_For_2_Template, 2, 1, "span", 229, i0.ɵɵrepeaterTrackByIdentity);
|
|
890
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_26_Conditional_3_Conditional_3_Template, 2, 1, "span", 230);
|
|
712
891
|
i0.ɵɵelementEnd();
|
|
713
892
|
} if (rf & 2) {
|
|
714
|
-
const
|
|
893
|
+
const run_r30 = i0.ɵɵnextContext().$implicit;
|
|
715
894
|
i0.ɵɵadvance();
|
|
716
|
-
i0.ɵɵrepeater(
|
|
895
|
+
i0.ɵɵrepeater(run_r30.tags.slice(0, 2));
|
|
717
896
|
i0.ɵɵadvance(2);
|
|
718
|
-
i0.ɵɵconditional(
|
|
897
|
+
i0.ɵɵconditional(run_r30.tags.length > 2 ? 3 : -1);
|
|
719
898
|
} }
|
|
720
|
-
function
|
|
721
|
-
const
|
|
722
|
-
i0.ɵɵelementStart(0, "th",
|
|
899
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_26_Template(rf, ctx) { if (rf & 1) {
|
|
900
|
+
const _r29 = i0.ɵɵgetCurrentView();
|
|
901
|
+
i0.ɵɵelementStart(0, "th", 224);
|
|
723
902
|
i0.ɵɵpipe(1, "date");
|
|
724
|
-
i0.ɵɵlistener("click", function
|
|
725
|
-
i0.ɵɵelementStart(2, "div",
|
|
726
|
-
i0.ɵɵconditionalCreate(3,
|
|
727
|
-
i0.ɵɵelementStart(4, "div",
|
|
903
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_26_Template_th_click_0_listener() { const run_r30 = i0.ɵɵrestoreView(_r29).$implicit; const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.openSuiteRun(run_r30.runId)); });
|
|
904
|
+
i0.ɵɵelementStart(2, "div", 225);
|
|
905
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_26_Conditional_3_Template, 4, 1, "div", 226);
|
|
906
|
+
i0.ɵɵelementStart(4, "div", 227);
|
|
728
907
|
i0.ɵɵtext(5);
|
|
729
908
|
i0.ɵɵelementEnd();
|
|
730
|
-
i0.ɵɵelementStart(6, "div",
|
|
909
|
+
i0.ɵɵelementStart(6, "div", 228);
|
|
731
910
|
i0.ɵɵtext(7);
|
|
732
911
|
i0.ɵɵelementEnd()()();
|
|
733
912
|
} if (rf & 2) {
|
|
734
|
-
const
|
|
913
|
+
const run_r30 = ctx.$implicit;
|
|
735
914
|
const ctx_r0 = i0.ɵɵnextContext(5);
|
|
736
|
-
i0.ɵɵproperty("title", "Click to view suite run - " + i0.ɵɵpipeBind2(1, 5,
|
|
915
|
+
i0.ɵɵproperty("title", "Click to view suite run - " + i0.ɵɵpipeBind2(1, 5, run_r30.date, "medium"));
|
|
737
916
|
i0.ɵɵadvance(3);
|
|
738
|
-
i0.ɵɵconditional(
|
|
917
|
+
i0.ɵɵconditional(run_r30.tags.length > 0 ? 3 : -1);
|
|
739
918
|
i0.ɵɵadvance(2);
|
|
740
|
-
i0.ɵɵtextInterpolate(ctx_r0.getRelativeTime(
|
|
919
|
+
i0.ɵɵtextInterpolate(ctx_r0.getRelativeTime(run_r30.date));
|
|
741
920
|
i0.ɵɵadvance();
|
|
742
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction3(8, _c5,
|
|
921
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction3(8, _c5, run_r30.passRate >= 80, run_r30.passRate >= 50 && run_r30.passRate < 80, run_r30.passRate < 50));
|
|
743
922
|
i0.ɵɵadvance();
|
|
744
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
923
|
+
i0.ɵɵtextInterpolate1(" ", run_r30.passRate.toFixed(0), "% ");
|
|
745
924
|
} }
|
|
746
|
-
function
|
|
747
|
-
i0.ɵɵelementStart(0, "span",
|
|
748
|
-
i0.ɵɵelement(1, "i",
|
|
925
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
926
|
+
i0.ɵɵelementStart(0, "span", 244);
|
|
927
|
+
i0.ɵɵelement(1, "i", 132);
|
|
749
928
|
i0.ɵɵelementEnd();
|
|
750
929
|
} if (rf & 2) {
|
|
751
|
-
const
|
|
930
|
+
const result_r36 = i0.ɵɵnextContext();
|
|
752
931
|
const ctx_r0 = i0.ɵɵnextContext(7);
|
|
753
|
-
i0.ɵɵclassProp("cell-skipped-status",
|
|
754
|
-
i0.ɵɵproperty("ngClass", "status-" +
|
|
932
|
+
i0.ɵɵclassProp("cell-skipped-status", result_r36.status === "Skipped" || result_r36.status === "Pending");
|
|
933
|
+
i0.ɵɵproperty("ngClass", "status-" + result_r36.status.toLowerCase())("title", ctx_r0.getStatusTooltip(result_r36.status));
|
|
755
934
|
i0.ɵɵadvance();
|
|
756
|
-
i0.ɵɵclassProp("fa-check",
|
|
935
|
+
i0.ɵɵclassProp("fa-check", result_r36.status === "Passed")("fa-times", result_r36.status === "Failed")("fa-exclamation", result_r36.status === "Error")("fa-hourglass-end", result_r36.status === "Timeout")("fa-forward", result_r36.status === "Skipped")("fa-spinner", result_r36.status === "Running")("fa-clock", result_r36.status === "Pending");
|
|
757
936
|
} }
|
|
758
|
-
function
|
|
759
|
-
i0.ɵɵelementStart(0, "span",
|
|
760
|
-
i0.ɵɵelement(1, "i",
|
|
937
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
938
|
+
i0.ɵɵelementStart(0, "span", 240);
|
|
939
|
+
i0.ɵɵelement(1, "i", 245);
|
|
761
940
|
i0.ɵɵelementEnd();
|
|
762
941
|
} }
|
|
763
|
-
function
|
|
764
|
-
i0.ɵɵelementStart(0, "span",
|
|
765
|
-
i0.ɵɵelement(1, "i",
|
|
766
|
-
i0.ɵɵelementStart(2, "span",
|
|
942
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
943
|
+
i0.ɵɵelementStart(0, "span", 246);
|
|
944
|
+
i0.ɵɵelement(1, "i", 147);
|
|
945
|
+
i0.ɵɵelementStart(2, "span", 247);
|
|
767
946
|
i0.ɵɵtext(3);
|
|
768
947
|
i0.ɵɵelementEnd()();
|
|
769
948
|
} if (rf & 2) {
|
|
770
|
-
const
|
|
949
|
+
const result_r36 = i0.ɵɵnextContext();
|
|
771
950
|
const ctx_r0 = i0.ɵɵnextContext(7);
|
|
772
|
-
i0.ɵɵclassProp("rating-low",
|
|
773
|
-
i0.ɵɵproperty("title", ctx_r0.getHumanTooltip(
|
|
951
|
+
i0.ɵɵclassProp("rating-low", result_r36.humanRating <= 4)("rating-medium", result_r36.humanRating >= 5 && result_r36.humanRating <= 6)("rating-good", result_r36.humanRating >= 7 && result_r36.humanRating <= 8)("rating-excellent", result_r36.humanRating >= 9);
|
|
952
|
+
i0.ɵɵproperty("title", ctx_r0.getHumanTooltip(result_r36.humanRating, result_r36.humanComments));
|
|
774
953
|
i0.ɵɵadvance(3);
|
|
775
|
-
i0.ɵɵtextInterpolate(
|
|
954
|
+
i0.ɵɵtextInterpolate(result_r36.humanRating);
|
|
776
955
|
} }
|
|
777
|
-
function
|
|
778
|
-
i0.ɵɵelementStart(0, "span",
|
|
779
|
-
i0.ɵɵelement(1, "i",
|
|
780
|
-
i0.ɵɵelementStart(2, "span",
|
|
956
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
957
|
+
i0.ɵɵelementStart(0, "span", 248);
|
|
958
|
+
i0.ɵɵelement(1, "i", 151);
|
|
959
|
+
i0.ɵɵelementStart(2, "span", 249);
|
|
781
960
|
i0.ɵɵtext(3);
|
|
782
961
|
i0.ɵɵelementEnd()();
|
|
783
962
|
} if (rf & 2) {
|
|
784
|
-
const
|
|
785
|
-
i0.ɵɵclassProp("score-low",
|
|
786
|
-
i0.ɵɵproperty("title", "Auto Score: " + (
|
|
963
|
+
const result_r36 = i0.ɵɵnextContext();
|
|
964
|
+
i0.ɵɵclassProp("score-low", result_r36.score < 0.5)("score-medium", result_r36.score >= 0.5 && result_r36.score < 0.7)("score-good", result_r36.score >= 0.7 && result_r36.score < 0.85)("score-excellent", result_r36.score >= 0.85);
|
|
965
|
+
i0.ɵɵproperty("title", "Auto Score: " + (result_r36.score * 100).toFixed(0) + "% automated evaluation");
|
|
787
966
|
i0.ɵɵadvance(3);
|
|
788
|
-
i0.ɵɵtextInterpolate((
|
|
967
|
+
i0.ɵɵtextInterpolate((result_r36.score * 100).toFixed(0));
|
|
789
968
|
} }
|
|
790
|
-
function
|
|
791
|
-
i0.ɵɵelementStart(0, "span",
|
|
792
|
-
i0.ɵɵelement(1, "i",
|
|
969
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
970
|
+
i0.ɵɵelementStart(0, "span", 243);
|
|
971
|
+
i0.ɵɵelement(1, "i", 151);
|
|
793
972
|
i0.ɵɵelementEnd();
|
|
794
973
|
} }
|
|
795
|
-
function
|
|
796
|
-
i0.ɵɵelementStart(0, "div",
|
|
797
|
-
i0.ɵɵconditionalCreate(1,
|
|
798
|
-
i0.ɵɵconditionalCreate(2,
|
|
799
|
-
i0.ɵɵconditionalCreate(3,
|
|
800
|
-
i0.ɵɵconditionalCreate(4,
|
|
801
|
-
i0.ɵɵconditionalCreate(5,
|
|
974
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
975
|
+
i0.ɵɵelementStart(0, "div", 237);
|
|
976
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Conditional_1_Template, 2, 18, "span", 239);
|
|
977
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Conditional_2_Template, 2, 0, "span", 240);
|
|
978
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Conditional_3_Template, 4, 10, "span", 241);
|
|
979
|
+
i0.ɵɵconditionalCreate(4, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Conditional_4_Template, 4, 10, "span", 242);
|
|
980
|
+
i0.ɵɵconditionalCreate(5, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Conditional_5_Template, 2, 0, "span", 243);
|
|
802
981
|
i0.ɵɵelementEnd();
|
|
803
982
|
} if (rf & 2) {
|
|
804
|
-
const
|
|
983
|
+
const result_r36 = ctx;
|
|
805
984
|
const ctx_r0 = i0.ɵɵnextContext(7);
|
|
806
985
|
i0.ɵɵadvance();
|
|
807
986
|
i0.ɵɵconditional(ctx_r0.evalPreferences.showExecution ? 1 : -1);
|
|
808
987
|
i0.ɵɵadvance();
|
|
809
|
-
i0.ɵɵconditional(ctx_r0.evalPreferences.showHuman && !
|
|
988
|
+
i0.ɵɵconditional(ctx_r0.evalPreferences.showHuman && !result_r36.humanRating ? 2 : -1);
|
|
810
989
|
i0.ɵɵadvance();
|
|
811
|
-
i0.ɵɵconditional(ctx_r0.evalPreferences.showHuman &&
|
|
990
|
+
i0.ɵɵconditional(ctx_r0.evalPreferences.showHuman && result_r36.humanRating ? 3 : -1);
|
|
812
991
|
i0.ɵɵadvance();
|
|
813
|
-
i0.ɵɵconditional(ctx_r0.evalPreferences.showAuto &&
|
|
992
|
+
i0.ɵɵconditional(ctx_r0.evalPreferences.showAuto && result_r36.score != null ? 4 : -1);
|
|
814
993
|
i0.ɵɵadvance();
|
|
815
|
-
i0.ɵɵconditional(ctx_r0.evalPreferences.showAuto &&
|
|
994
|
+
i0.ɵɵconditional(ctx_r0.evalPreferences.showAuto && result_r36.score == null ? 5 : -1);
|
|
816
995
|
} }
|
|
817
|
-
function
|
|
818
|
-
i0.ɵɵelementStart(0, "span",
|
|
819
|
-
i0.ɵɵelement(1, "i",
|
|
996
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
997
|
+
i0.ɵɵelementStart(0, "span", 238);
|
|
998
|
+
i0.ɵɵelement(1, "i", 250);
|
|
820
999
|
i0.ɵɵelementEnd();
|
|
821
1000
|
} }
|
|
822
|
-
function
|
|
823
|
-
const
|
|
824
|
-
i0.ɵɵelementStart(0, "td",
|
|
825
|
-
i0.ɵɵlistener("click", function
|
|
826
|
-
i0.ɵɵconditionalCreate(1,
|
|
827
|
-
i0.ɵɵconditionalCreate(2,
|
|
1001
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Template(rf, ctx) { if (rf & 1) {
|
|
1002
|
+
const _r34 = i0.ɵɵgetCurrentView();
|
|
1003
|
+
i0.ɵɵelementStart(0, "td", 236);
|
|
1004
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Template_td_click_0_listener($event) { const run_r35 = i0.ɵɵrestoreView(_r34).$implicit; const test_r33 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.onMatrixCellClick(ctx_r0.getTestResultForRun(run_r35.runId, test_r33.testId), $event)); });
|
|
1005
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_1_Template, 6, 5, "div", 237);
|
|
1006
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Conditional_2_Template, 2, 0, "span", 238);
|
|
828
1007
|
i0.ɵɵelementEnd();
|
|
829
1008
|
} if (rf & 2) {
|
|
830
1009
|
let tmp_27_0;
|
|
831
1010
|
let tmp_28_0;
|
|
832
|
-
const
|
|
833
|
-
const
|
|
1011
|
+
const run_r35 = ctx.$implicit;
|
|
1012
|
+
const test_r33 = i0.ɵɵnextContext().$implicit;
|
|
834
1013
|
const ctx_r0 = i0.ɵɵnextContext(5);
|
|
835
|
-
i0.ɵɵclassProp("clickable", ctx_r0.getTestResultForRun(
|
|
836
|
-
i0.ɵɵproperty("ngClass", ctx_r0.getMatrixCellClass(ctx_r0.getTestResultForRun(
|
|
1014
|
+
i0.ɵɵclassProp("clickable", ctx_r0.getTestResultForRun(run_r35.runId, test_r33.testId))("cell-not-run", !ctx_r0.getTestResultForRun(run_r35.runId, test_r33.testId));
|
|
1015
|
+
i0.ɵɵproperty("ngClass", ctx_r0.getMatrixCellClass(ctx_r0.getTestResultForRun(run_r35.runId, test_r33.testId)))("title", ((tmp_27_0 = ctx_r0.getTestResultForRun(run_r35.runId, test_r33.testId)) == null ? null : tmp_27_0.status) + " - Click to view test run" || "Not Run");
|
|
837
1016
|
i0.ɵɵadvance();
|
|
838
|
-
i0.ɵɵconditional((tmp_28_0 = ctx_r0.getTestResultForRun(
|
|
1017
|
+
i0.ɵɵconditional((tmp_28_0 = ctx_r0.getTestResultForRun(run_r35.runId, test_r33.testId)) ? 1 : -1, tmp_28_0);
|
|
839
1018
|
i0.ɵɵadvance();
|
|
840
|
-
i0.ɵɵconditional(!ctx_r0.getTestResultForRun(
|
|
1019
|
+
i0.ɵɵconditional(!ctx_r0.getTestResultForRun(run_r35.runId, test_r33.testId) ? 2 : -1);
|
|
841
1020
|
} }
|
|
842
|
-
function
|
|
843
|
-
const
|
|
844
|
-
i0.ɵɵelementStart(0, "tr",
|
|
845
|
-
i0.ɵɵlistener("click", function
|
|
846
|
-
i0.ɵɵelementStart(1, "td",
|
|
1021
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_Template(rf, ctx) { if (rf & 1) {
|
|
1022
|
+
const _r32 = i0.ɵɵgetCurrentView();
|
|
1023
|
+
i0.ɵɵelementStart(0, "tr", 231);
|
|
1024
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_Template_tr_click_0_listener() { const test_r33 = i0.ɵɵrestoreView(_r32).$implicit; const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.selectMatrixRow(test_r33.testId)); });
|
|
1025
|
+
i0.ɵɵelementStart(1, "td", 232);
|
|
847
1026
|
i0.ɵɵtext(2);
|
|
848
1027
|
i0.ɵɵelementEnd();
|
|
849
|
-
i0.ɵɵelementStart(3, "td",
|
|
1028
|
+
i0.ɵɵelementStart(3, "td", 233)(4, "span", 234);
|
|
850
1029
|
i0.ɵɵtext(5);
|
|
851
1030
|
i0.ɵɵelementEnd()();
|
|
852
|
-
i0.ɵɵrepeaterCreate(6,
|
|
853
|
-
i0.ɵɵelement(8, "td",
|
|
1031
|
+
i0.ɵɵrepeaterCreate(6, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_For_7_Template, 3, 8, "td", 235, i0.ɵɵrepeaterTrackByIdentity);
|
|
1032
|
+
i0.ɵɵelement(8, "td", 222);
|
|
854
1033
|
i0.ɵɵelementEnd();
|
|
855
1034
|
} if (rf & 2) {
|
|
856
|
-
const
|
|
1035
|
+
const test_r33 = ctx.$implicit;
|
|
857
1036
|
const ctx_r0 = i0.ɵɵnextContext(5);
|
|
858
|
-
i0.ɵɵclassProp("row-selected", ctx_r0.selectedMatrixTestId ===
|
|
1037
|
+
i0.ɵɵclassProp("row-selected", ctx_r0.selectedMatrixTestId === test_r33.testId);
|
|
859
1038
|
i0.ɵɵadvance(2);
|
|
860
|
-
i0.ɵɵtextInterpolate(
|
|
1039
|
+
i0.ɵɵtextInterpolate(test_r33.sequence);
|
|
861
1040
|
i0.ɵɵadvance(2);
|
|
862
|
-
i0.ɵɵproperty("title",
|
|
1041
|
+
i0.ɵɵproperty("title", test_r33.testName);
|
|
863
1042
|
i0.ɵɵadvance();
|
|
864
|
-
i0.ɵɵtextInterpolate(
|
|
1043
|
+
i0.ɵɵtextInterpolate(test_r33.testName);
|
|
865
1044
|
i0.ɵɵadvance();
|
|
866
1045
|
i0.ɵɵrepeater(ctx_r0.matrixData);
|
|
867
1046
|
} }
|
|
868
|
-
function
|
|
869
|
-
i0.ɵɵelementStart(0, "span",
|
|
1047
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1048
|
+
i0.ɵɵelementStart(0, "span", 252)(1, "span", 255);
|
|
870
1049
|
i0.ɵɵtext(2);
|
|
871
1050
|
i0.ɵɵelementEnd()();
|
|
872
1051
|
} if (rf & 2) {
|
|
873
|
-
const
|
|
1052
|
+
const run_r37 = i0.ɵɵnextContext().$implicit;
|
|
874
1053
|
const ctx_r0 = i0.ɵɵnextContext(5);
|
|
875
1054
|
i0.ɵɵadvance(2);
|
|
876
|
-
i0.ɵɵtextInterpolate2("", ctx_r0.getRunPassedCount(
|
|
1055
|
+
i0.ɵɵtextInterpolate2("", ctx_r0.getRunPassedCount(run_r37), "/", ctx_r0.getRunTotalCount(run_r37));
|
|
877
1056
|
} }
|
|
878
|
-
function
|
|
879
|
-
i0.ɵɵelementStart(0, "span",
|
|
1057
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Conditional_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1058
|
+
i0.ɵɵelementStart(0, "span", 256);
|
|
880
1059
|
i0.ɵɵtext(1);
|
|
881
1060
|
i0.ɵɵelementEnd();
|
|
882
1061
|
} if (rf & 2) {
|
|
883
1062
|
let tmp_16_0;
|
|
884
|
-
const
|
|
1063
|
+
const run_r37 = i0.ɵɵnextContext(2).$implicit;
|
|
885
1064
|
const ctx_r0 = i0.ɵɵnextContext(5);
|
|
886
1065
|
i0.ɵɵadvance();
|
|
887
|
-
i0.ɵɵtextInterpolate((tmp_16_0 = ctx_r0.getRunHumanAvg(
|
|
1066
|
+
i0.ɵɵtextInterpolate((tmp_16_0 = ctx_r0.getRunHumanAvg(run_r37)) == null ? null : tmp_16_0.toFixed(1));
|
|
888
1067
|
} }
|
|
889
|
-
function
|
|
890
|
-
i0.ɵɵelementStart(0, "span",
|
|
891
|
-
i0.ɵɵconditionalCreate(1,
|
|
892
|
-
i0.ɵɵelementStart(2, "span",
|
|
1068
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
1069
|
+
i0.ɵɵelementStart(0, "span", 253);
|
|
1070
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Conditional_3_Conditional_1_Template, 2, 1, "span", 256);
|
|
1071
|
+
i0.ɵɵelementStart(2, "span", 257);
|
|
893
1072
|
i0.ɵɵtext(3);
|
|
894
1073
|
i0.ɵɵelementEnd()();
|
|
895
1074
|
} if (rf & 2) {
|
|
896
|
-
const
|
|
1075
|
+
const run_r37 = i0.ɵɵnextContext().$implicit;
|
|
897
1076
|
const ctx_r0 = i0.ɵɵnextContext(5);
|
|
898
1077
|
i0.ɵɵadvance();
|
|
899
|
-
i0.ɵɵconditional(ctx_r0.getRunHumanAvg(
|
|
1078
|
+
i0.ɵɵconditional(ctx_r0.getRunHumanAvg(run_r37) != null ? 1 : -1);
|
|
900
1079
|
i0.ɵɵadvance(2);
|
|
901
|
-
i0.ɵɵtextInterpolate1("(", ctx_r0.getRunHumanCount(
|
|
1080
|
+
i0.ɵɵtextInterpolate1("(", ctx_r0.getRunHumanCount(run_r37), ")");
|
|
902
1081
|
} }
|
|
903
|
-
function
|
|
904
|
-
i0.ɵɵelementStart(0, "span",
|
|
1082
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Conditional_4_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1083
|
+
i0.ɵɵelementStart(0, "span", 256);
|
|
905
1084
|
i0.ɵɵtext(1);
|
|
906
1085
|
i0.ɵɵelementEnd();
|
|
907
1086
|
} if (rf & 2) {
|
|
908
|
-
const
|
|
1087
|
+
const run_r37 = i0.ɵɵnextContext(2).$implicit;
|
|
909
1088
|
const ctx_r0 = i0.ɵɵnextContext(5);
|
|
910
1089
|
i0.ɵɵadvance();
|
|
911
|
-
i0.ɵɵtextInterpolate1("", (ctx_r0.getRunAutoAvg(
|
|
1090
|
+
i0.ɵɵtextInterpolate1("", (ctx_r0.getRunAutoAvg(run_r37) * 100).toFixed(0), "%");
|
|
912
1091
|
} }
|
|
913
|
-
function
|
|
914
|
-
i0.ɵɵelementStart(0, "span",
|
|
915
|
-
i0.ɵɵconditionalCreate(1,
|
|
916
|
-
i0.ɵɵelementStart(2, "span",
|
|
1092
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
1093
|
+
i0.ɵɵelementStart(0, "span", 254);
|
|
1094
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Conditional_4_Conditional_1_Template, 2, 1, "span", 256);
|
|
1095
|
+
i0.ɵɵelementStart(2, "span", 257);
|
|
917
1096
|
i0.ɵɵtext(3);
|
|
918
1097
|
i0.ɵɵelementEnd()();
|
|
919
1098
|
} if (rf & 2) {
|
|
920
|
-
const
|
|
1099
|
+
const run_r37 = i0.ɵɵnextContext().$implicit;
|
|
921
1100
|
const ctx_r0 = i0.ɵɵnextContext(5);
|
|
922
1101
|
i0.ɵɵadvance();
|
|
923
|
-
i0.ɵɵconditional(ctx_r0.getRunAutoAvg(
|
|
1102
|
+
i0.ɵɵconditional(ctx_r0.getRunAutoAvg(run_r37) != null ? 1 : -1);
|
|
924
1103
|
i0.ɵɵadvance(2);
|
|
925
|
-
i0.ɵɵtextInterpolate1("(", ctx_r0.getRunAutoCount(
|
|
1104
|
+
i0.ɵɵtextInterpolate1("(", ctx_r0.getRunAutoCount(run_r37), ")");
|
|
926
1105
|
} }
|
|
927
|
-
function
|
|
928
|
-
i0.ɵɵelementStart(0, "td",
|
|
929
|
-
i0.ɵɵconditionalCreate(2,
|
|
930
|
-
i0.ɵɵconditionalCreate(3,
|
|
931
|
-
i0.ɵɵconditionalCreate(4,
|
|
1106
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Template(rf, ctx) { if (rf & 1) {
|
|
1107
|
+
i0.ɵɵelementStart(0, "td", 221)(1, "div", 251);
|
|
1108
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Conditional_2_Template, 3, 2, "span", 252);
|
|
1109
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Conditional_3_Template, 4, 2, "span", 253);
|
|
1110
|
+
i0.ɵɵconditionalCreate(4, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Conditional_4_Template, 4, 2, "span", 254);
|
|
932
1111
|
i0.ɵɵelementEnd()();
|
|
933
1112
|
} if (rf & 2) {
|
|
934
1113
|
const ctx_r0 = i0.ɵɵnextContext(5);
|
|
@@ -939,50 +1118,50 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
939
1118
|
i0.ɵɵadvance();
|
|
940
1119
|
i0.ɵɵconditional(ctx_r0.evalPreferences.showAuto ? 4 : -1);
|
|
941
1120
|
} }
|
|
942
|
-
function
|
|
943
|
-
const
|
|
944
|
-
i0.ɵɵelementStart(0, "div",
|
|
945
|
-
i0.ɵɵelement(3, "i",
|
|
1121
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1122
|
+
const _r27 = i0.ɵɵgetCurrentView();
|
|
1123
|
+
i0.ɵɵelementStart(0, "div", 200)(1, "div", 202)(2, "h3");
|
|
1124
|
+
i0.ɵɵelement(3, "i", 159);
|
|
946
1125
|
i0.ɵɵtext(4, " Test Results Matrix");
|
|
947
1126
|
i0.ɵɵelementEnd();
|
|
948
|
-
i0.ɵɵelementStart(5, "div",
|
|
949
|
-
i0.ɵɵelement(7, "i",
|
|
950
|
-
i0.ɵɵelementStart(8, "input",
|
|
951
|
-
i0.ɵɵlistener("input", function
|
|
1127
|
+
i0.ɵɵelementStart(5, "div", 203)(6, "div", 204);
|
|
1128
|
+
i0.ɵɵelement(7, "i", 205);
|
|
1129
|
+
i0.ɵɵelementStart(8, "input", 206);
|
|
1130
|
+
i0.ɵɵlistener("input", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_Template_input_input_8_listener($event) { i0.ɵɵrestoreView(_r27); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.onMatrixFilterInput($event)); });
|
|
952
1131
|
i0.ɵɵelementEnd();
|
|
953
|
-
i0.ɵɵconditionalCreate(9,
|
|
1132
|
+
i0.ɵɵconditionalCreate(9, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_Conditional_9_Template, 2, 0, "button", 207);
|
|
954
1133
|
i0.ɵɵelementEnd();
|
|
955
|
-
i0.ɵɵelementStart(10, "span",
|
|
1134
|
+
i0.ɵɵelementStart(10, "span", 208);
|
|
956
1135
|
i0.ɵɵtext(11);
|
|
957
1136
|
i0.ɵɵelementEnd();
|
|
958
|
-
i0.ɵɵelementStart(12, "button",
|
|
959
|
-
i0.ɵɵlistener("click", function
|
|
960
|
-
i0.ɵɵelement(13, "i",
|
|
1137
|
+
i0.ɵɵelementStart(12, "button", 209);
|
|
1138
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r27); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.exportMatrixToCSV()); });
|
|
1139
|
+
i0.ɵɵelement(13, "i", 210);
|
|
961
1140
|
i0.ɵɵtext(14, " Export ");
|
|
962
1141
|
i0.ɵɵelementEnd()()();
|
|
963
|
-
i0.ɵɵelementStart(15, "div",
|
|
964
|
-
i0.ɵɵlistener("click", function
|
|
1142
|
+
i0.ɵɵelementStart(15, "div", 211)(16, "table", 212)(17, "thead")(18, "tr")(19, "th", 213);
|
|
1143
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_Template_th_click_19_listener() { i0.ɵɵrestoreView(_r27); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.toggleMatrixSort("sequence")); });
|
|
965
1144
|
i0.ɵɵtext(20, " # ");
|
|
966
|
-
i0.ɵɵelement(21, "i",
|
|
1145
|
+
i0.ɵɵelement(21, "i", 19);
|
|
967
1146
|
i0.ɵɵelementEnd();
|
|
968
|
-
i0.ɵɵelementStart(22, "th",
|
|
969
|
-
i0.ɵɵlistener("click", function
|
|
1147
|
+
i0.ɵɵelementStart(22, "th", 214);
|
|
1148
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_Template_th_click_22_listener() { i0.ɵɵrestoreView(_r27); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.toggleMatrixSort("name")); });
|
|
970
1149
|
i0.ɵɵtext(23, " Test ");
|
|
971
|
-
i0.ɵɵelement(24, "i",
|
|
1150
|
+
i0.ɵɵelement(24, "i", 19);
|
|
972
1151
|
i0.ɵɵelementEnd();
|
|
973
|
-
i0.ɵɵrepeaterCreate(25,
|
|
974
|
-
i0.ɵɵelement(27, "th",
|
|
1152
|
+
i0.ɵɵrepeaterCreate(25, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_26_Template, 8, 12, "th", 215, i0.ɵɵrepeaterTrackByIdentity);
|
|
1153
|
+
i0.ɵɵelement(27, "th", 216);
|
|
975
1154
|
i0.ɵɵelementEnd()();
|
|
976
1155
|
i0.ɵɵelementStart(28, "tbody");
|
|
977
|
-
i0.ɵɵrepeaterCreate(29,
|
|
1156
|
+
i0.ɵɵrepeaterCreate(29, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_30_Template, 9, 5, "tr", 217, i0.ɵɵrepeaterTrackByIdentity);
|
|
978
1157
|
i0.ɵɵelementEnd();
|
|
979
|
-
i0.ɵɵelementStart(31, "tfoot")(32, "tr",
|
|
980
|
-
i0.ɵɵelement(33, "td",
|
|
981
|
-
i0.ɵɵelementStart(34, "td",
|
|
1158
|
+
i0.ɵɵelementStart(31, "tfoot")(32, "tr", 218);
|
|
1159
|
+
i0.ɵɵelement(33, "td", 219);
|
|
1160
|
+
i0.ɵɵelementStart(34, "td", 220)(35, "strong");
|
|
982
1161
|
i0.ɵɵtext(36, "Totals");
|
|
983
1162
|
i0.ɵɵelementEnd()();
|
|
984
|
-
i0.ɵɵrepeaterCreate(37,
|
|
985
|
-
i0.ɵɵelement(39, "td",
|
|
1163
|
+
i0.ɵɵrepeaterCreate(37, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_For_38_Template, 5, 3, "td", 221, i0.ɵɵrepeaterTrackByIdentity);
|
|
1164
|
+
i0.ɵɵelement(39, "td", 222);
|
|
986
1165
|
i0.ɵɵelementEnd()()()()();
|
|
987
1166
|
} if (rf & 2) {
|
|
988
1167
|
const ctx_r0 = i0.ɵɵnextContext(4);
|
|
@@ -1005,9 +1184,9 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
1005
1184
|
i0.ɵɵadvance(8);
|
|
1006
1185
|
i0.ɵɵrepeater(ctx_r0.matrixData);
|
|
1007
1186
|
} }
|
|
1008
|
-
function
|
|
1009
|
-
i0.ɵɵelementStart(0, "div",
|
|
1010
|
-
i0.ɵɵelement(2, "i",
|
|
1187
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1188
|
+
i0.ɵɵelementStart(0, "div", 101)(1, "div", 127);
|
|
1189
|
+
i0.ɵɵelement(2, "i", 159);
|
|
1011
1190
|
i0.ɵɵelementEnd();
|
|
1012
1191
|
i0.ɵɵelementStart(3, "h4");
|
|
1013
1192
|
i0.ɵɵtext(4, "No Matrix Data");
|
|
@@ -1016,10 +1195,10 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
1016
1195
|
i0.ɵɵtext(6, "No suite runs match the current filters.");
|
|
1017
1196
|
i0.ɵɵelementEnd()();
|
|
1018
1197
|
} }
|
|
1019
|
-
function
|
|
1020
|
-
i0.ɵɵconditionalCreate(0,
|
|
1021
|
-
i0.ɵɵconditionalCreate(1,
|
|
1022
|
-
i0.ɵɵconditionalCreate(2,
|
|
1198
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
1199
|
+
i0.ɵɵconditionalCreate(0, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_0_Template, 2, 0, "div", 99);
|
|
1200
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_1_Template, 40, 7, "div", 200);
|
|
1201
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Conditional_2_Template, 7, 0, "div", 101);
|
|
1023
1202
|
} if (rf & 2) {
|
|
1024
1203
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1025
1204
|
i0.ɵɵconditional(ctx_r0.loadingMatrix ? 0 : -1);
|
|
@@ -1028,37 +1207,37 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
1028
1207
|
i0.ɵɵadvance();
|
|
1029
1208
|
i0.ɵɵconditional(!ctx_r0.loadingMatrix && ctx_r0.matrixLoaded && ctx_r0.matrixData.length === 0 ? 2 : -1);
|
|
1030
1209
|
} }
|
|
1031
|
-
function
|
|
1032
|
-
i0.ɵɵelementStart(0, "div",
|
|
1033
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
1210
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_24_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
1211
|
+
i0.ɵɵelementStart(0, "div", 99);
|
|
1212
|
+
i0.ɵɵelement(1, "mj-loading", 259);
|
|
1034
1213
|
i0.ɵɵelementEnd();
|
|
1035
1214
|
} }
|
|
1036
|
-
function
|
|
1037
|
-
i0.ɵɵelementStart(0, "div",
|
|
1038
|
-
i0.ɵɵelement(3, "i",
|
|
1215
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_24_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1216
|
+
i0.ɵɵelementStart(0, "div", 258)(1, "div", 260)(2, "h3");
|
|
1217
|
+
i0.ɵɵelement(3, "i", 160);
|
|
1039
1218
|
i0.ɵɵtext(4, " Test Results Flow");
|
|
1040
1219
|
i0.ɵɵelementEnd();
|
|
1041
|
-
i0.ɵɵelementStart(5, "div",
|
|
1042
|
-
i0.ɵɵelement(7, "i",
|
|
1220
|
+
i0.ɵɵelementStart(5, "div", 261)(6, "span", 262);
|
|
1221
|
+
i0.ɵɵelement(7, "i", 175);
|
|
1043
1222
|
i0.ɵɵtext(8, " Passed");
|
|
1044
1223
|
i0.ɵɵelementEnd();
|
|
1045
|
-
i0.ɵɵelementStart(9, "span",
|
|
1046
|
-
i0.ɵɵelement(10, "i",
|
|
1224
|
+
i0.ɵɵelementStart(9, "span", 263);
|
|
1225
|
+
i0.ɵɵelement(10, "i", 91);
|
|
1047
1226
|
i0.ɵɵtext(11, " Failed");
|
|
1048
1227
|
i0.ɵɵelementEnd();
|
|
1049
|
-
i0.ɵɵelementStart(12, "span",
|
|
1050
|
-
i0.ɵɵelement(13, "i",
|
|
1228
|
+
i0.ɵɵelementStart(12, "span", 264);
|
|
1229
|
+
i0.ɵɵelement(13, "i", 265);
|
|
1051
1230
|
i0.ɵɵtext(14, " Error");
|
|
1052
1231
|
i0.ɵɵelementEnd();
|
|
1053
|
-
i0.ɵɵelementStart(15, "span",
|
|
1054
|
-
i0.ɵɵelement(16, "i",
|
|
1232
|
+
i0.ɵɵelementStart(15, "span", 266);
|
|
1233
|
+
i0.ɵɵelement(16, "i", 267);
|
|
1055
1234
|
i0.ɵɵtext(17, " Skipped");
|
|
1056
1235
|
i0.ɵɵelementEnd()()();
|
|
1057
|
-
i0.ɵɵelementStart(18, "div",
|
|
1058
|
-
i0.ɵɵelement(19, "div",
|
|
1236
|
+
i0.ɵɵelementStart(18, "div", 268);
|
|
1237
|
+
i0.ɵɵelement(19, "div", 269, 1);
|
|
1059
1238
|
i0.ɵɵelementEnd();
|
|
1060
|
-
i0.ɵɵelementStart(21, "div",
|
|
1061
|
-
i0.ɵɵelement(22, "i",
|
|
1239
|
+
i0.ɵɵelementStart(21, "div", 270);
|
|
1240
|
+
i0.ɵɵelement(22, "i", 119);
|
|
1062
1241
|
i0.ɵɵtext(23);
|
|
1063
1242
|
i0.ɵɵelementEnd()();
|
|
1064
1243
|
} if (rf & 2) {
|
|
@@ -1066,9 +1245,9 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
1066
1245
|
i0.ɵɵadvance(23);
|
|
1067
1246
|
i0.ɵɵtextInterpolate1(" Interactive visualization showing test results across ", ctx_r0.matrixData.length, " runs. Hover over elements for details, click nodes to navigate. ");
|
|
1068
1247
|
} }
|
|
1069
|
-
function
|
|
1070
|
-
i0.ɵɵelementStart(0, "div",
|
|
1071
|
-
i0.ɵɵelement(2, "i",
|
|
1248
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_24_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1249
|
+
i0.ɵɵelementStart(0, "div", 101)(1, "div", 127);
|
|
1250
|
+
i0.ɵɵelement(2, "i", 160);
|
|
1072
1251
|
i0.ɵɵelementEnd();
|
|
1073
1252
|
i0.ɵɵelementStart(3, "h4");
|
|
1074
1253
|
i0.ɵɵtext(4, "No Chart Data");
|
|
@@ -1077,10 +1256,10 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
1077
1256
|
i0.ɵɵtext(6, "No suite runs match the current filters.");
|
|
1078
1257
|
i0.ɵɵelementEnd()();
|
|
1079
1258
|
} }
|
|
1080
|
-
function
|
|
1081
|
-
i0.ɵɵconditionalCreate(0,
|
|
1082
|
-
i0.ɵɵconditionalCreate(1,
|
|
1083
|
-
i0.ɵɵconditionalCreate(2,
|
|
1259
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_24_Template(rf, ctx) { if (rf & 1) {
|
|
1260
|
+
i0.ɵɵconditionalCreate(0, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_24_Conditional_0_Template, 2, 0, "div", 99);
|
|
1261
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_24_Conditional_1_Template, 24, 1, "div", 258);
|
|
1262
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_24_Conditional_2_Template, 7, 0, "div", 101);
|
|
1084
1263
|
} if (rf & 2) {
|
|
1085
1264
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1086
1265
|
i0.ɵɵconditional(ctx_r0.loadingMatrix ? 0 : -1);
|
|
@@ -1089,40 +1268,40 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Condition
|
|
|
1089
1268
|
i0.ɵɵadvance();
|
|
1090
1269
|
i0.ɵɵconditional(!ctx_r0.loadingMatrix && ctx_r0.matrixLoaded && ctx_r0.matrixData.length === 0 ? 2 : -1);
|
|
1091
1270
|
} }
|
|
1092
|
-
function
|
|
1093
|
-
const
|
|
1094
|
-
i0.ɵɵelementStart(0, "div",
|
|
1095
|
-
i0.ɵɵlistener("click", function
|
|
1096
|
-
i0.ɵɵelement(3, "i",
|
|
1271
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1272
|
+
const _r19 = i0.ɵɵgetCurrentView();
|
|
1273
|
+
i0.ɵɵelementStart(0, "div", 155)(1, "div", 156)(2, "button", 157);
|
|
1274
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r19); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.setAnalyticsView("summary")); });
|
|
1275
|
+
i0.ɵɵelement(3, "i", 158);
|
|
1097
1276
|
i0.ɵɵelementStart(4, "span");
|
|
1098
1277
|
i0.ɵɵtext(5, "Summary");
|
|
1099
1278
|
i0.ɵɵelementEnd()();
|
|
1100
|
-
i0.ɵɵelementStart(6, "button",
|
|
1101
|
-
i0.ɵɵlistener("click", function
|
|
1102
|
-
i0.ɵɵelement(7, "i",
|
|
1279
|
+
i0.ɵɵelementStart(6, "button", 157);
|
|
1280
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r19); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.setAnalyticsView("matrix")); });
|
|
1281
|
+
i0.ɵɵelement(7, "i", 159);
|
|
1103
1282
|
i0.ɵɵelementStart(8, "span");
|
|
1104
1283
|
i0.ɵɵtext(9, "Matrix");
|
|
1105
1284
|
i0.ɵɵelementEnd()();
|
|
1106
|
-
i0.ɵɵelementStart(10, "button",
|
|
1107
|
-
i0.ɵɵlistener("click", function
|
|
1108
|
-
i0.ɵɵelement(11, "i",
|
|
1285
|
+
i0.ɵɵelementStart(10, "button", 157);
|
|
1286
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r19); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.setAnalyticsView("chart")); });
|
|
1287
|
+
i0.ɵɵelement(11, "i", 160);
|
|
1109
1288
|
i0.ɵɵelementStart(12, "span");
|
|
1110
1289
|
i0.ɵɵtext(13, "Chart");
|
|
1111
1290
|
i0.ɵɵelementEnd()()()();
|
|
1112
|
-
i0.ɵɵelementStart(14, "div",
|
|
1113
|
-
i0.ɵɵlistener("click", function
|
|
1114
|
-
i0.ɵɵelementStart(16, "span",
|
|
1115
|
-
i0.ɵɵelement(17, "i",
|
|
1291
|
+
i0.ɵɵelementStart(14, "div", 161)(15, "div", 162);
|
|
1292
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Template_div_click_15_listener() { i0.ɵɵrestoreView(_r19); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.toggleFilters()); });
|
|
1293
|
+
i0.ɵɵelementStart(16, "span", 163);
|
|
1294
|
+
i0.ɵɵelement(17, "i", 164);
|
|
1116
1295
|
i0.ɵɵtext(18, " Filters ");
|
|
1117
|
-
i0.ɵɵconditionalCreate(19,
|
|
1296
|
+
i0.ɵɵconditionalCreate(19, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_19_Template, 3, 2, "span", 165);
|
|
1118
1297
|
i0.ɵɵelementEnd();
|
|
1119
|
-
i0.ɵɵelement(20, "i",
|
|
1298
|
+
i0.ɵɵelement(20, "i", 19);
|
|
1120
1299
|
i0.ɵɵelementEnd();
|
|
1121
|
-
i0.ɵɵconditionalCreate(21,
|
|
1300
|
+
i0.ɵɵconditionalCreate(21, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_21_Template, 14, 9, "div", 166);
|
|
1122
1301
|
i0.ɵɵelementEnd();
|
|
1123
|
-
i0.ɵɵconditionalCreate(22,
|
|
1124
|
-
i0.ɵɵconditionalCreate(23,
|
|
1125
|
-
i0.ɵɵconditionalCreate(24,
|
|
1302
|
+
i0.ɵɵconditionalCreate(22, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_22_Template, 62, 15);
|
|
1303
|
+
i0.ɵɵconditionalCreate(23, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_23_Template, 3, 3);
|
|
1304
|
+
i0.ɵɵconditionalCreate(24, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Conditional_24_Template, 3, 3);
|
|
1126
1305
|
} if (rf & 2) {
|
|
1127
1306
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1128
1307
|
i0.ɵɵadvance(2);
|
|
@@ -1146,10 +1325,10 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_2_Template(
|
|
|
1146
1325
|
i0.ɵɵadvance();
|
|
1147
1326
|
i0.ɵɵconditional(ctx_r0.analyticsView === "chart" ? 24 : -1);
|
|
1148
1327
|
} }
|
|
1149
|
-
function
|
|
1150
|
-
const
|
|
1151
|
-
i0.ɵɵelementStart(0, "div",
|
|
1152
|
-
i0.ɵɵelement(2, "i",
|
|
1328
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
1329
|
+
const _r38 = i0.ɵɵgetCurrentView();
|
|
1330
|
+
i0.ɵɵelementStart(0, "div", 101)(1, "div", 127);
|
|
1331
|
+
i0.ɵɵelement(2, "i", 36);
|
|
1153
1332
|
i0.ɵɵelementEnd();
|
|
1154
1333
|
i0.ɵɵelementStart(3, "h4");
|
|
1155
1334
|
i0.ɵɵtext(4, "No Analytics Data");
|
|
@@ -1157,17 +1336,17 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_3_Template(
|
|
|
1157
1336
|
i0.ɵɵelementStart(5, "p");
|
|
1158
1337
|
i0.ɵɵtext(6, "Run this suite to start collecting analytics data.");
|
|
1159
1338
|
i0.ɵɵelementEnd();
|
|
1160
|
-
i0.ɵɵelementStart(7, "button",
|
|
1161
|
-
i0.ɵɵlistener("click", function
|
|
1162
|
-
i0.ɵɵelement(8, "i",
|
|
1339
|
+
i0.ɵɵelementStart(7, "button", 25);
|
|
1340
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_3_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r38); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.runSuite()); });
|
|
1341
|
+
i0.ɵɵelement(8, "i", 26);
|
|
1163
1342
|
i0.ɵɵtext(9, " Run Suite Now ");
|
|
1164
1343
|
i0.ɵɵelementEnd()();
|
|
1165
1344
|
} }
|
|
1166
|
-
function
|
|
1167
|
-
i0.ɵɵelementStart(0, "div",
|
|
1168
|
-
i0.ɵɵconditionalCreate(1,
|
|
1169
|
-
i0.ɵɵconditionalCreate(2,
|
|
1170
|
-
i0.ɵɵconditionalCreate(3,
|
|
1345
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Template(rf, ctx) { if (rf & 1) {
|
|
1346
|
+
i0.ɵɵelementStart(0, "div", 42);
|
|
1347
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_1_Template, 2, 0, "div", 99);
|
|
1348
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Template, 25, 14);
|
|
1349
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_3_Template, 10, 0, "div", 101);
|
|
1171
1350
|
i0.ɵɵelementEnd();
|
|
1172
1351
|
} if (rf & 2) {
|
|
1173
1352
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -1178,75 +1357,75 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Template(rf, ctx) { if
|
|
|
1178
1357
|
i0.ɵɵadvance();
|
|
1179
1358
|
i0.ɵɵconditional(!ctx_r0.loadingAnalytics && ctx_r0.analyticsLoaded && ctx_r0.analyticsData.length === 0 ? 3 : -1);
|
|
1180
1359
|
} }
|
|
1181
|
-
function
|
|
1182
|
-
i0.ɵɵelementStart(0, "span",
|
|
1360
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_For_2_Conditional_8_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1361
|
+
i0.ɵɵelementStart(0, "span", 286);
|
|
1183
1362
|
i0.ɵɵtext(1);
|
|
1184
1363
|
i0.ɵɵelementEnd();
|
|
1185
1364
|
} if (rf & 2) {
|
|
1186
|
-
const
|
|
1365
|
+
const tag_r41 = ctx.$implicit;
|
|
1187
1366
|
i0.ɵɵadvance();
|
|
1188
|
-
i0.ɵɵtextInterpolate(
|
|
1367
|
+
i0.ɵɵtextInterpolate(tag_r41);
|
|
1189
1368
|
} }
|
|
1190
|
-
function
|
|
1191
|
-
i0.ɵɵelementStart(0, "div",
|
|
1192
|
-
i0.ɵɵrepeaterCreate(1,
|
|
1369
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_For_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
1370
|
+
i0.ɵɵelementStart(0, "div", 285);
|
|
1371
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_For_2_Conditional_8_For_2_Template, 2, 1, "span", 286, i0.ɵɵrepeaterTrackByIdentity);
|
|
1193
1372
|
i0.ɵɵelementEnd();
|
|
1194
1373
|
} if (rf & 2) {
|
|
1195
|
-
const
|
|
1374
|
+
const run_r40 = i0.ɵɵnextContext().$implicit;
|
|
1196
1375
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1197
1376
|
i0.ɵɵadvance();
|
|
1198
|
-
i0.ɵɵrepeater(ctx_r0.getRunTags(
|
|
1377
|
+
i0.ɵɵrepeater(ctx_r0.getRunTags(run_r40).slice(0, 2));
|
|
1199
1378
|
} }
|
|
1200
|
-
function
|
|
1201
|
-
const
|
|
1202
|
-
i0.ɵɵelementStart(0, "div",
|
|
1203
|
-
i0.ɵɵlistener("click", function
|
|
1204
|
-
i0.ɵɵelement(1, "div",
|
|
1205
|
-
i0.ɵɵelementStart(2, "div",
|
|
1379
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1380
|
+
const _r39 = i0.ɵɵgetCurrentView();
|
|
1381
|
+
i0.ɵɵelementStart(0, "div", 280);
|
|
1382
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_For_2_Template_div_click_0_listener() { const run_r40 = i0.ɵɵrestoreView(_r39).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.selectCompareRunA(run_r40)); });
|
|
1383
|
+
i0.ɵɵelement(1, "div", 281);
|
|
1384
|
+
i0.ɵɵelementStart(2, "div", 282)(3, "div", 283);
|
|
1206
1385
|
i0.ɵɵtext(4);
|
|
1207
1386
|
i0.ɵɵpipe(5, "date");
|
|
1208
1387
|
i0.ɵɵelementEnd();
|
|
1209
|
-
i0.ɵɵelementStart(6, "div",
|
|
1388
|
+
i0.ɵɵelementStart(6, "div", 284);
|
|
1210
1389
|
i0.ɵɵtext(7);
|
|
1211
1390
|
i0.ɵɵelementEnd()();
|
|
1212
|
-
i0.ɵɵconditionalCreate(8,
|
|
1391
|
+
i0.ɵɵconditionalCreate(8, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_For_2_Conditional_8_Template, 3, 0, "div", 285);
|
|
1213
1392
|
i0.ɵɵelementEnd();
|
|
1214
1393
|
} if (rf & 2) {
|
|
1215
|
-
const
|
|
1394
|
+
const run_r40 = ctx.$implicit;
|
|
1216
1395
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1217
|
-
i0.ɵɵclassProp("selected", ctx_r0.IsCompareRunA(
|
|
1396
|
+
i0.ɵɵclassProp("selected", ctx_r0.IsCompareRunA(run_r40));
|
|
1218
1397
|
i0.ɵɵadvance();
|
|
1219
|
-
i0.ɵɵstyleProp("background-color", ctx_r0.getRunStatusColor(
|
|
1398
|
+
i0.ɵɵstyleProp("background-color", ctx_r0.getRunStatusColor(run_r40.Status));
|
|
1220
1399
|
i0.ɵɵadvance(3);
|
|
1221
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(5, 7,
|
|
1400
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(5, 7, run_r40.StartedAt, "short"));
|
|
1222
1401
|
i0.ɵɵadvance(3);
|
|
1223
|
-
i0.ɵɵtextInterpolate1("", ctx_r0.getPassRate(
|
|
1402
|
+
i0.ɵɵtextInterpolate1("", ctx_r0.getPassRate(run_r40).toFixed(0), "% pass");
|
|
1224
1403
|
i0.ɵɵadvance();
|
|
1225
|
-
i0.ɵɵconditional(ctx_r0.getRunTags(
|
|
1404
|
+
i0.ɵɵconditional(ctx_r0.getRunTags(run_r40).length > 0 ? 8 : -1);
|
|
1226
1405
|
} }
|
|
1227
|
-
function
|
|
1228
|
-
i0.ɵɵelementStart(0, "div",
|
|
1229
|
-
i0.ɵɵrepeaterCreate(1,
|
|
1406
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
1407
|
+
i0.ɵɵelementStart(0, "div", 273);
|
|
1408
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_For_2_Template, 9, 10, "div", 279, i0.ɵɵrepeaterTrackByIdentity);
|
|
1230
1409
|
i0.ɵɵelementEnd();
|
|
1231
1410
|
} if (rf & 2) {
|
|
1232
1411
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1233
1412
|
i0.ɵɵadvance();
|
|
1234
1413
|
i0.ɵɵrepeater(ctx_r0.suiteRuns);
|
|
1235
1414
|
} }
|
|
1236
|
-
function
|
|
1237
|
-
const
|
|
1238
|
-
i0.ɵɵelementStart(0, "div",
|
|
1415
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
1416
|
+
const _r42 = i0.ɵɵgetCurrentView();
|
|
1417
|
+
i0.ɵɵelementStart(0, "div", 274)(1, "div", 287)(2, "span", 288);
|
|
1239
1418
|
i0.ɵɵtext(3, "Selected:");
|
|
1240
1419
|
i0.ɵɵelementEnd();
|
|
1241
|
-
i0.ɵɵelementStart(4, "button",
|
|
1242
|
-
i0.ɵɵlistener("click", function
|
|
1420
|
+
i0.ɵɵelementStart(4, "button", 289);
|
|
1421
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_6_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r42); const ctx_r0 = i0.ɵɵnextContext(2); ctx_r0.compareRunA = null; return i0.ɵɵresetView(ctx_r0.compareResults = []); });
|
|
1243
1422
|
i0.ɵɵtext(5, "Clear");
|
|
1244
1423
|
i0.ɵɵelementEnd()();
|
|
1245
|
-
i0.ɵɵelementStart(6, "div",
|
|
1424
|
+
i0.ɵɵelementStart(6, "div", 290)(7, "span");
|
|
1246
1425
|
i0.ɵɵtext(8);
|
|
1247
1426
|
i0.ɵɵpipe(9, "date");
|
|
1248
1427
|
i0.ɵɵelementEnd();
|
|
1249
|
-
i0.ɵɵelementStart(10, "span",
|
|
1428
|
+
i0.ɵɵelementStart(10, "span", 291);
|
|
1250
1429
|
i0.ɵɵtext(11);
|
|
1251
1430
|
i0.ɵɵelementEnd()()();
|
|
1252
1431
|
} if (rf & 2) {
|
|
@@ -1256,75 +1435,75 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_6_Template(
|
|
|
1256
1435
|
i0.ɵɵadvance(3);
|
|
1257
1436
|
i0.ɵɵtextInterpolate1("", ctx_r0.getPassRate(ctx_r0.compareRunA).toFixed(1), "%");
|
|
1258
1437
|
} }
|
|
1259
|
-
function
|
|
1260
|
-
i0.ɵɵelementStart(0, "span",
|
|
1438
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_For_2_Conditional_8_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1439
|
+
i0.ɵɵelementStart(0, "span", 286);
|
|
1261
1440
|
i0.ɵɵtext(1);
|
|
1262
1441
|
i0.ɵɵelementEnd();
|
|
1263
1442
|
} if (rf & 2) {
|
|
1264
|
-
const
|
|
1443
|
+
const tag_r45 = ctx.$implicit;
|
|
1265
1444
|
i0.ɵɵadvance();
|
|
1266
|
-
i0.ɵɵtextInterpolate(
|
|
1445
|
+
i0.ɵɵtextInterpolate(tag_r45);
|
|
1267
1446
|
} }
|
|
1268
|
-
function
|
|
1269
|
-
i0.ɵɵelementStart(0, "div",
|
|
1270
|
-
i0.ɵɵrepeaterCreate(1,
|
|
1447
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_For_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
1448
|
+
i0.ɵɵelementStart(0, "div", 285);
|
|
1449
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_For_2_Conditional_8_For_2_Template, 2, 1, "span", 286, i0.ɵɵrepeaterTrackByIdentity);
|
|
1271
1450
|
i0.ɵɵelementEnd();
|
|
1272
1451
|
} if (rf & 2) {
|
|
1273
|
-
const
|
|
1452
|
+
const run_r44 = i0.ɵɵnextContext().$implicit;
|
|
1274
1453
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1275
1454
|
i0.ɵɵadvance();
|
|
1276
|
-
i0.ɵɵrepeater(ctx_r0.getRunTags(
|
|
1455
|
+
i0.ɵɵrepeater(ctx_r0.getRunTags(run_r44).slice(0, 2));
|
|
1277
1456
|
} }
|
|
1278
|
-
function
|
|
1279
|
-
const
|
|
1280
|
-
i0.ɵɵelementStart(0, "div",
|
|
1281
|
-
i0.ɵɵlistener("click", function
|
|
1282
|
-
i0.ɵɵelement(1, "div",
|
|
1283
|
-
i0.ɵɵelementStart(2, "div",
|
|
1457
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1458
|
+
const _r43 = i0.ɵɵgetCurrentView();
|
|
1459
|
+
i0.ɵɵelementStart(0, "div", 280);
|
|
1460
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_For_2_Template_div_click_0_listener() { const run_r44 = i0.ɵɵrestoreView(_r43).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(!ctx_r0.IsCompareRunA(run_r44) && ctx_r0.selectCompareRunB(run_r44)); });
|
|
1461
|
+
i0.ɵɵelement(1, "div", 281);
|
|
1462
|
+
i0.ɵɵelementStart(2, "div", 282)(3, "div", 283);
|
|
1284
1463
|
i0.ɵɵtext(4);
|
|
1285
1464
|
i0.ɵɵpipe(5, "date");
|
|
1286
1465
|
i0.ɵɵelementEnd();
|
|
1287
|
-
i0.ɵɵelementStart(6, "div",
|
|
1466
|
+
i0.ɵɵelementStart(6, "div", 284);
|
|
1288
1467
|
i0.ɵɵtext(7);
|
|
1289
1468
|
i0.ɵɵelementEnd()();
|
|
1290
|
-
i0.ɵɵconditionalCreate(8,
|
|
1469
|
+
i0.ɵɵconditionalCreate(8, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_For_2_Conditional_8_Template, 3, 0, "div", 285);
|
|
1291
1470
|
i0.ɵɵelementEnd();
|
|
1292
1471
|
} if (rf & 2) {
|
|
1293
|
-
const
|
|
1472
|
+
const run_r44 = ctx.$implicit;
|
|
1294
1473
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1295
|
-
i0.ɵɵclassProp("selected", ctx_r0.IsCompareRunB(
|
|
1474
|
+
i0.ɵɵclassProp("selected", ctx_r0.IsCompareRunB(run_r44))("disabled", ctx_r0.IsCompareRunA(run_r44));
|
|
1296
1475
|
i0.ɵɵadvance();
|
|
1297
|
-
i0.ɵɵstyleProp("background-color", ctx_r0.getRunStatusColor(
|
|
1476
|
+
i0.ɵɵstyleProp("background-color", ctx_r0.getRunStatusColor(run_r44.Status));
|
|
1298
1477
|
i0.ɵɵadvance(3);
|
|
1299
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(5, 9,
|
|
1478
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(5, 9, run_r44.StartedAt, "short"));
|
|
1300
1479
|
i0.ɵɵadvance(3);
|
|
1301
|
-
i0.ɵɵtextInterpolate1("", ctx_r0.getPassRate(
|
|
1480
|
+
i0.ɵɵtextInterpolate1("", ctx_r0.getPassRate(run_r44).toFixed(0), "% pass");
|
|
1302
1481
|
i0.ɵɵadvance();
|
|
1303
|
-
i0.ɵɵconditional(ctx_r0.getRunTags(
|
|
1482
|
+
i0.ɵɵconditional(ctx_r0.getRunTags(run_r44).length > 0 ? 8 : -1);
|
|
1304
1483
|
} }
|
|
1305
|
-
function
|
|
1306
|
-
i0.ɵɵelementStart(0, "div",
|
|
1307
|
-
i0.ɵɵrepeaterCreate(1,
|
|
1484
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
1485
|
+
i0.ɵɵelementStart(0, "div", 273);
|
|
1486
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_For_2_Template, 9, 12, "div", 292, i0.ɵɵrepeaterTrackByIdentity);
|
|
1308
1487
|
i0.ɵɵelementEnd();
|
|
1309
1488
|
} if (rf & 2) {
|
|
1310
1489
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1311
1490
|
i0.ɵɵadvance();
|
|
1312
1491
|
i0.ɵɵrepeater(ctx_r0.suiteRuns);
|
|
1313
1492
|
} }
|
|
1314
|
-
function
|
|
1315
|
-
const
|
|
1316
|
-
i0.ɵɵelementStart(0, "div",
|
|
1493
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
1494
|
+
const _r46 = i0.ɵɵgetCurrentView();
|
|
1495
|
+
i0.ɵɵelementStart(0, "div", 274)(1, "div", 287)(2, "span", 288);
|
|
1317
1496
|
i0.ɵɵtext(3, "Selected:");
|
|
1318
1497
|
i0.ɵɵelementEnd();
|
|
1319
|
-
i0.ɵɵelementStart(4, "button",
|
|
1320
|
-
i0.ɵɵlistener("click", function
|
|
1498
|
+
i0.ɵɵelementStart(4, "button", 289);
|
|
1499
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_13_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r46); const ctx_r0 = i0.ɵɵnextContext(2); ctx_r0.compareRunB = null; return i0.ɵɵresetView(ctx_r0.compareResults = []); });
|
|
1321
1500
|
i0.ɵɵtext(5, "Clear");
|
|
1322
1501
|
i0.ɵɵelementEnd()();
|
|
1323
|
-
i0.ɵɵelementStart(6, "div",
|
|
1502
|
+
i0.ɵɵelementStart(6, "div", 290)(7, "span");
|
|
1324
1503
|
i0.ɵɵtext(8);
|
|
1325
1504
|
i0.ɵɵpipe(9, "date");
|
|
1326
1505
|
i0.ɵɵelementEnd();
|
|
1327
|
-
i0.ɵɵelementStart(10, "span",
|
|
1506
|
+
i0.ɵɵelementStart(10, "span", 291);
|
|
1328
1507
|
i0.ɵɵtext(11);
|
|
1329
1508
|
i0.ɵɵelementEnd()()();
|
|
1330
1509
|
} if (rf & 2) {
|
|
@@ -1334,168 +1513,168 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_Template
|
|
|
1334
1513
|
i0.ɵɵadvance(3);
|
|
1335
1514
|
i0.ɵɵtextInterpolate1("", ctx_r0.getPassRate(ctx_r0.compareRunB).toFixed(1), "%");
|
|
1336
1515
|
} }
|
|
1337
|
-
function
|
|
1338
|
-
i0.ɵɵelementStart(0, "span",
|
|
1516
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
1517
|
+
i0.ɵɵelementStart(0, "span", 194);
|
|
1339
1518
|
i0.ɵɵtext(1);
|
|
1340
1519
|
i0.ɵɵelementEnd();
|
|
1341
1520
|
} if (rf & 2) {
|
|
1342
|
-
const
|
|
1343
|
-
i0.ɵɵproperty("ngClass", "status-" +
|
|
1521
|
+
const result_r47 = i0.ɵɵnextContext().$implicit;
|
|
1522
|
+
i0.ɵɵproperty("ngClass", "status-" + result_r47.runA.status.toLowerCase());
|
|
1344
1523
|
i0.ɵɵadvance();
|
|
1345
|
-
i0.ɵɵtextInterpolate(
|
|
1524
|
+
i0.ɵɵtextInterpolate(result_r47.runA.status);
|
|
1346
1525
|
} }
|
|
1347
|
-
function
|
|
1348
|
-
i0.ɵɵelementStart(0, "span",
|
|
1526
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
1527
|
+
i0.ɵɵelementStart(0, "span", 305);
|
|
1349
1528
|
i0.ɵɵtext(1, "N/A");
|
|
1350
1529
|
i0.ɵɵelementEnd();
|
|
1351
1530
|
} }
|
|
1352
|
-
function
|
|
1353
|
-
i0.ɵɵelementStart(0, "span",
|
|
1531
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
1532
|
+
i0.ɵɵelementStart(0, "span", 194);
|
|
1354
1533
|
i0.ɵɵtext(1);
|
|
1355
1534
|
i0.ɵɵelementEnd();
|
|
1356
1535
|
} if (rf & 2) {
|
|
1357
|
-
const
|
|
1358
|
-
i0.ɵɵproperty("ngClass", "status-" +
|
|
1536
|
+
const result_r47 = i0.ɵɵnextContext().$implicit;
|
|
1537
|
+
i0.ɵɵproperty("ngClass", "status-" + result_r47.runB.status.toLowerCase());
|
|
1359
1538
|
i0.ɵɵadvance();
|
|
1360
|
-
i0.ɵɵtextInterpolate(
|
|
1539
|
+
i0.ɵɵtextInterpolate(result_r47.runB.status);
|
|
1361
1540
|
} }
|
|
1362
|
-
function
|
|
1363
|
-
i0.ɵɵelementStart(0, "span",
|
|
1541
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
1542
|
+
i0.ɵɵelementStart(0, "span", 305);
|
|
1364
1543
|
i0.ɵɵtext(1, "N/A");
|
|
1365
1544
|
i0.ɵɵelementEnd();
|
|
1366
1545
|
} }
|
|
1367
|
-
function
|
|
1368
|
-
i0.ɵɵelementStart(0, "span",
|
|
1546
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
1547
|
+
i0.ɵɵelementStart(0, "span", 304);
|
|
1369
1548
|
i0.ɵɵtext(1);
|
|
1370
1549
|
i0.ɵɵelementEnd();
|
|
1371
1550
|
} if (rf & 2) {
|
|
1372
|
-
const
|
|
1373
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(3, _c6,
|
|
1551
|
+
const result_r47 = i0.ɵɵnextContext().$implicit;
|
|
1552
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(3, _c6, result_r47.scoreDiff > 0, result_r47.scoreDiff < 0));
|
|
1374
1553
|
i0.ɵɵadvance();
|
|
1375
|
-
i0.ɵɵtextInterpolate2(" ",
|
|
1554
|
+
i0.ɵɵtextInterpolate2(" ", result_r47.scoreDiff > 0 ? "+" : "", "", (result_r47.scoreDiff * 100).toFixed(1), "% ");
|
|
1376
1555
|
} }
|
|
1377
|
-
function
|
|
1378
|
-
i0.ɵɵelementStart(0, "span",
|
|
1556
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
1557
|
+
i0.ɵɵelementStart(0, "span", 306);
|
|
1379
1558
|
i0.ɵɵtext(1, "-");
|
|
1380
1559
|
i0.ɵɵelementEnd();
|
|
1381
1560
|
} }
|
|
1382
|
-
function
|
|
1383
|
-
i0.ɵɵelementStart(0, "span",
|
|
1561
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
1562
|
+
i0.ɵɵelementStart(0, "span", 304);
|
|
1384
1563
|
i0.ɵɵtext(1);
|
|
1385
1564
|
i0.ɵɵelementEnd();
|
|
1386
1565
|
} if (rf & 2) {
|
|
1387
|
-
const
|
|
1388
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(3, _c6,
|
|
1566
|
+
const result_r47 = i0.ɵɵnextContext().$implicit;
|
|
1567
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(3, _c6, result_r47.durationDiff < 0, result_r47.durationDiff > 0));
|
|
1389
1568
|
i0.ɵɵadvance();
|
|
1390
|
-
i0.ɵɵtextInterpolate2(" ",
|
|
1569
|
+
i0.ɵɵtextInterpolate2(" ", result_r47.durationDiff > 0 ? "+" : "", "", result_r47.durationDiff.toFixed(1), "s ");
|
|
1391
1570
|
} }
|
|
1392
|
-
function
|
|
1393
|
-
i0.ɵɵelementStart(0, "span",
|
|
1571
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
1572
|
+
i0.ɵɵelementStart(0, "span", 306);
|
|
1394
1573
|
i0.ɵɵtext(1, "-");
|
|
1395
1574
|
i0.ɵɵelementEnd();
|
|
1396
1575
|
} }
|
|
1397
|
-
function
|
|
1398
|
-
i0.ɵɵelementStart(0, "span",
|
|
1399
|
-
i0.ɵɵelement(1, "i",
|
|
1576
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
1577
|
+
i0.ɵɵelementStart(0, "span", 307);
|
|
1578
|
+
i0.ɵɵelement(1, "i", 310);
|
|
1400
1579
|
i0.ɵɵtext(2, " Fixed ");
|
|
1401
1580
|
i0.ɵɵelementEnd();
|
|
1402
1581
|
} }
|
|
1403
|
-
function
|
|
1404
|
-
i0.ɵɵelementStart(0, "span",
|
|
1405
|
-
i0.ɵɵelement(1, "i",
|
|
1582
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
1583
|
+
i0.ɵɵelementStart(0, "span", 308);
|
|
1584
|
+
i0.ɵɵelement(1, "i", 311);
|
|
1406
1585
|
i0.ɵɵtext(2, " Broke ");
|
|
1407
1586
|
i0.ɵɵelementEnd();
|
|
1408
1587
|
} }
|
|
1409
|
-
function
|
|
1410
|
-
i0.ɵɵelementStart(0, "span",
|
|
1411
|
-
i0.ɵɵelement(1, "i",
|
|
1588
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
1589
|
+
i0.ɵɵelementStart(0, "span", 309);
|
|
1590
|
+
i0.ɵɵelement(1, "i", 250);
|
|
1412
1591
|
i0.ɵɵelementEnd();
|
|
1413
1592
|
} }
|
|
1414
|
-
function
|
|
1415
|
-
i0.ɵɵelementStart(0, "tr",
|
|
1593
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Template(rf, ctx) { if (rf & 1) {
|
|
1594
|
+
i0.ɵɵelementStart(0, "tr", 304)(1, "td", 233);
|
|
1416
1595
|
i0.ɵɵtext(2);
|
|
1417
1596
|
i0.ɵɵelementEnd();
|
|
1418
1597
|
i0.ɵɵelementStart(3, "td");
|
|
1419
|
-
i0.ɵɵconditionalCreate(4,
|
|
1420
|
-
i0.ɵɵconditionalCreate(5,
|
|
1598
|
+
i0.ɵɵconditionalCreate(4, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_4_Template, 2, 2, "span", 194);
|
|
1599
|
+
i0.ɵɵconditionalCreate(5, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_5_Template, 2, 0, "span", 305);
|
|
1421
1600
|
i0.ɵɵelementEnd();
|
|
1422
1601
|
i0.ɵɵelementStart(6, "td");
|
|
1423
|
-
i0.ɵɵconditionalCreate(7,
|
|
1424
|
-
i0.ɵɵconditionalCreate(8,
|
|
1602
|
+
i0.ɵɵconditionalCreate(7, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_7_Template, 2, 2, "span", 194);
|
|
1603
|
+
i0.ɵɵconditionalCreate(8, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_8_Template, 2, 0, "span", 305);
|
|
1425
1604
|
i0.ɵɵelementEnd();
|
|
1426
1605
|
i0.ɵɵelementStart(9, "td");
|
|
1427
|
-
i0.ɵɵconditionalCreate(10,
|
|
1428
|
-
i0.ɵɵconditionalCreate(11,
|
|
1606
|
+
i0.ɵɵconditionalCreate(10, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_10_Template, 2, 6, "span", 304);
|
|
1607
|
+
i0.ɵɵconditionalCreate(11, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_11_Template, 2, 0, "span", 306);
|
|
1429
1608
|
i0.ɵɵelementEnd();
|
|
1430
1609
|
i0.ɵɵelementStart(12, "td");
|
|
1431
|
-
i0.ɵɵconditionalCreate(13,
|
|
1432
|
-
i0.ɵɵconditionalCreate(14,
|
|
1610
|
+
i0.ɵɵconditionalCreate(13, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_13_Template, 2, 6, "span", 304);
|
|
1611
|
+
i0.ɵɵconditionalCreate(14, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_14_Template, 2, 0, "span", 306);
|
|
1433
1612
|
i0.ɵɵelementEnd();
|
|
1434
1613
|
i0.ɵɵelementStart(15, "td");
|
|
1435
|
-
i0.ɵɵconditionalCreate(16,
|
|
1436
|
-
i0.ɵɵconditionalCreate(17,
|
|
1437
|
-
i0.ɵɵconditionalCreate(18,
|
|
1614
|
+
i0.ɵɵconditionalCreate(16, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_16_Template, 3, 0, "span", 307);
|
|
1615
|
+
i0.ɵɵconditionalCreate(17, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_17_Template, 3, 0, "span", 308);
|
|
1616
|
+
i0.ɵɵconditionalCreate(18, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Conditional_18_Template, 2, 0, "span", 309);
|
|
1438
1617
|
i0.ɵɵelementEnd()();
|
|
1439
1618
|
} if (rf & 2) {
|
|
1440
|
-
const
|
|
1441
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(13, _c8,
|
|
1619
|
+
const result_r47 = ctx.$implicit;
|
|
1620
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(13, _c8, result_r47.runA && result_r47.runB && result_r47.runA.status !== "Passed" && result_r47.runB.status === "Passed", result_r47.runA && result_r47.runB && result_r47.runA.status === "Passed" && result_r47.runB.status !== "Passed"));
|
|
1442
1621
|
i0.ɵɵadvance(2);
|
|
1443
|
-
i0.ɵɵtextInterpolate(
|
|
1622
|
+
i0.ɵɵtextInterpolate(result_r47.testName);
|
|
1444
1623
|
i0.ɵɵadvance(2);
|
|
1445
|
-
i0.ɵɵconditional(
|
|
1624
|
+
i0.ɵɵconditional(result_r47.runA ? 4 : -1);
|
|
1446
1625
|
i0.ɵɵadvance();
|
|
1447
|
-
i0.ɵɵconditional(!
|
|
1626
|
+
i0.ɵɵconditional(!result_r47.runA ? 5 : -1);
|
|
1448
1627
|
i0.ɵɵadvance(2);
|
|
1449
|
-
i0.ɵɵconditional(
|
|
1628
|
+
i0.ɵɵconditional(result_r47.runB ? 7 : -1);
|
|
1450
1629
|
i0.ɵɵadvance();
|
|
1451
|
-
i0.ɵɵconditional(!
|
|
1630
|
+
i0.ɵɵconditional(!result_r47.runB ? 8 : -1);
|
|
1452
1631
|
i0.ɵɵadvance(2);
|
|
1453
|
-
i0.ɵɵconditional(
|
|
1632
|
+
i0.ɵɵconditional(result_r47.scoreDiff != null ? 10 : -1);
|
|
1454
1633
|
i0.ɵɵadvance();
|
|
1455
|
-
i0.ɵɵconditional(
|
|
1634
|
+
i0.ɵɵconditional(result_r47.scoreDiff == null ? 11 : -1);
|
|
1456
1635
|
i0.ɵɵadvance(2);
|
|
1457
|
-
i0.ɵɵconditional(
|
|
1636
|
+
i0.ɵɵconditional(result_r47.durationDiff != null ? 13 : -1);
|
|
1458
1637
|
i0.ɵɵadvance();
|
|
1459
|
-
i0.ɵɵconditional(
|
|
1638
|
+
i0.ɵɵconditional(result_r47.durationDiff == null ? 14 : -1);
|
|
1460
1639
|
i0.ɵɵadvance(2);
|
|
1461
|
-
i0.ɵɵconditional(
|
|
1640
|
+
i0.ɵɵconditional(result_r47.runA && result_r47.runB && result_r47.runA.status !== "Passed" && result_r47.runB.status === "Passed" ? 16 : -1);
|
|
1462
1641
|
i0.ɵɵadvance();
|
|
1463
|
-
i0.ɵɵconditional(
|
|
1642
|
+
i0.ɵɵconditional(result_r47.runA && result_r47.runB && result_r47.runA.status === "Passed" && result_r47.runB.status !== "Passed" ? 17 : -1);
|
|
1464
1643
|
i0.ɵɵadvance();
|
|
1465
|
-
i0.ɵɵconditional(!
|
|
1644
|
+
i0.ɵɵconditional(!result_r47.statusChanged ? 18 : -1);
|
|
1466
1645
|
} }
|
|
1467
|
-
function
|
|
1468
|
-
i0.ɵɵelementStart(0, "div",
|
|
1646
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
1647
|
+
i0.ɵɵelementStart(0, "div", 277)(1, "div", 293)(2, "div", 294)(3, "div", 295);
|
|
1469
1648
|
i0.ɵɵtext(4, "Pass Rate Change");
|
|
1470
1649
|
i0.ɵɵelementEnd();
|
|
1471
|
-
i0.ɵɵelementStart(5, "div",
|
|
1472
|
-
i0.ɵɵelement(6, "i",
|
|
1650
|
+
i0.ɵɵelementStart(5, "div", 296);
|
|
1651
|
+
i0.ɵɵelement(6, "i", 19);
|
|
1473
1652
|
i0.ɵɵtext(7);
|
|
1474
1653
|
i0.ɵɵelementEnd()();
|
|
1475
|
-
i0.ɵɵelementStart(8, "div",
|
|
1654
|
+
i0.ɵɵelementStart(8, "div", 294)(9, "div", 295);
|
|
1476
1655
|
i0.ɵɵtext(10, "Duration Change");
|
|
1477
1656
|
i0.ɵɵelementEnd();
|
|
1478
|
-
i0.ɵɵelementStart(11, "div",
|
|
1479
|
-
i0.ɵɵelement(12, "i",
|
|
1657
|
+
i0.ɵɵelementStart(11, "div", 296);
|
|
1658
|
+
i0.ɵɵelement(12, "i", 19);
|
|
1480
1659
|
i0.ɵɵtext(13);
|
|
1481
1660
|
i0.ɵɵelementEnd()();
|
|
1482
|
-
i0.ɵɵelementStart(14, "div",
|
|
1661
|
+
i0.ɵɵelementStart(14, "div", 297)(15, "div", 295);
|
|
1483
1662
|
i0.ɵɵtext(16, "Improved");
|
|
1484
1663
|
i0.ɵɵelementEnd();
|
|
1485
|
-
i0.ɵɵelementStart(17, "div",
|
|
1664
|
+
i0.ɵɵelementStart(17, "div", 298);
|
|
1486
1665
|
i0.ɵɵtext(18);
|
|
1487
1666
|
i0.ɵɵelementEnd()();
|
|
1488
|
-
i0.ɵɵelementStart(19, "div",
|
|
1667
|
+
i0.ɵɵelementStart(19, "div", 299)(20, "div", 295);
|
|
1489
1668
|
i0.ɵɵtext(21, "Regressed");
|
|
1490
1669
|
i0.ɵɵelementEnd();
|
|
1491
|
-
i0.ɵɵelementStart(22, "div",
|
|
1670
|
+
i0.ɵɵelementStart(22, "div", 298);
|
|
1492
1671
|
i0.ɵɵtext(23);
|
|
1493
1672
|
i0.ɵɵelementEnd()()();
|
|
1494
|
-
i0.ɵɵelementStart(24, "div",
|
|
1495
|
-
i0.ɵɵelement(26, "i",
|
|
1673
|
+
i0.ɵɵelementStart(24, "div", 300)(25, "h3");
|
|
1674
|
+
i0.ɵɵelement(26, "i", 301);
|
|
1496
1675
|
i0.ɵɵtext(27, " Test-by-Test Comparison");
|
|
1497
1676
|
i0.ɵɵelementEnd();
|
|
1498
|
-
i0.ɵɵelementStart(28, "div",
|
|
1677
|
+
i0.ɵɵelementStart(28, "div", 302)(29, "table", 303)(30, "thead")(31, "tr")(32, "th");
|
|
1499
1678
|
i0.ɵɵtext(33, "Test");
|
|
1500
1679
|
i0.ɵɵelementEnd();
|
|
1501
1680
|
i0.ɵɵelementStart(34, "th");
|
|
@@ -1514,7 +1693,7 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_14_Template
|
|
|
1514
1693
|
i0.ɵɵtext(43, "Change");
|
|
1515
1694
|
i0.ɵɵelementEnd()()();
|
|
1516
1695
|
i0.ɵɵelementStart(44, "tbody");
|
|
1517
|
-
i0.ɵɵrepeaterCreate(45,
|
|
1696
|
+
i0.ɵɵrepeaterCreate(45, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_Template, 19, 16, "tr", 304, i0.ɵɵrepeaterTrackByIdentity);
|
|
1518
1697
|
i0.ɵɵelementEnd()()()()();
|
|
1519
1698
|
} if (rf & 2) {
|
|
1520
1699
|
let tmp_4_0;
|
|
@@ -1538,14 +1717,14 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_14_Template
|
|
|
1538
1717
|
i0.ɵɵadvance(22);
|
|
1539
1718
|
i0.ɵɵrepeater(ctx_r0.compareResults);
|
|
1540
1719
|
} }
|
|
1541
|
-
function
|
|
1542
|
-
i0.ɵɵelementStart(0, "div",
|
|
1543
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
1720
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
1721
|
+
i0.ɵɵelementStart(0, "div", 99);
|
|
1722
|
+
i0.ɵɵelement(1, "mj-loading", 312);
|
|
1544
1723
|
i0.ɵɵelementEnd();
|
|
1545
1724
|
} }
|
|
1546
|
-
function
|
|
1547
|
-
i0.ɵɵelementStart(0, "div",
|
|
1548
|
-
i0.ɵɵelement(2, "i",
|
|
1725
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
1726
|
+
i0.ɵɵelementStart(0, "div", 278)(1, "div", 313);
|
|
1727
|
+
i0.ɵɵelement(2, "i", 37);
|
|
1549
1728
|
i0.ɵɵelementEnd();
|
|
1550
1729
|
i0.ɵɵelementStart(3, "h4");
|
|
1551
1730
|
i0.ɵɵtext(4, "Select Two Runs to Compare");
|
|
@@ -1554,10 +1733,10 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_16_Template
|
|
|
1554
1733
|
i0.ɵɵtext(6, "Choose a baseline run (A) and a comparison run (B) from the lists above to see a detailed side-by-side comparison.");
|
|
1555
1734
|
i0.ɵɵelementEnd()();
|
|
1556
1735
|
} }
|
|
1557
|
-
function
|
|
1558
|
-
const
|
|
1559
|
-
i0.ɵɵelementStart(0, "div",
|
|
1560
|
-
i0.ɵɵelement(2, "i",
|
|
1736
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
1737
|
+
const _r48 = i0.ɵɵgetCurrentView();
|
|
1738
|
+
i0.ɵɵelementStart(0, "div", 101)(1, "div", 127);
|
|
1739
|
+
i0.ɵɵelement(2, "i", 37);
|
|
1561
1740
|
i0.ɵɵelementEnd();
|
|
1562
1741
|
i0.ɵɵelementStart(3, "h4");
|
|
1563
1742
|
i0.ɵɵtext(4, "Not Enough Runs to Compare");
|
|
@@ -1565,32 +1744,32 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_17_Template
|
|
|
1565
1744
|
i0.ɵɵelementStart(5, "p");
|
|
1566
1745
|
i0.ɵɵtext(6, "You need at least 2 suite runs to use the comparison feature.");
|
|
1567
1746
|
i0.ɵɵelementEnd();
|
|
1568
|
-
i0.ɵɵelementStart(7, "button",
|
|
1569
|
-
i0.ɵɵlistener("click", function
|
|
1570
|
-
i0.ɵɵelement(8, "i",
|
|
1747
|
+
i0.ɵɵelementStart(7, "button", 25);
|
|
1748
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_17_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r48); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.runSuite()); });
|
|
1749
|
+
i0.ɵɵelement(8, "i", 26);
|
|
1571
1750
|
i0.ɵɵtext(9, " Run Suite Now ");
|
|
1572
1751
|
i0.ɵɵelementEnd()();
|
|
1573
1752
|
} }
|
|
1574
|
-
function
|
|
1575
|
-
i0.ɵɵelementStart(0, "div",
|
|
1753
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Template(rf, ctx) { if (rf & 1) {
|
|
1754
|
+
i0.ɵɵelementStart(0, "div", 43)(1, "div", 271)(2, "div", 272)(3, "h4");
|
|
1576
1755
|
i0.ɵɵtext(4, "Run A (Baseline)");
|
|
1577
1756
|
i0.ɵɵelementEnd();
|
|
1578
|
-
i0.ɵɵconditionalCreate(5,
|
|
1579
|
-
i0.ɵɵconditionalCreate(6,
|
|
1757
|
+
i0.ɵɵconditionalCreate(5, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_Template, 3, 0, "div", 273);
|
|
1758
|
+
i0.ɵɵconditionalCreate(6, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_6_Template, 12, 5, "div", 274);
|
|
1580
1759
|
i0.ɵɵelementEnd();
|
|
1581
|
-
i0.ɵɵelementStart(7, "div",
|
|
1582
|
-
i0.ɵɵelement(8, "i",
|
|
1760
|
+
i0.ɵɵelementStart(7, "div", 275);
|
|
1761
|
+
i0.ɵɵelement(8, "i", 276);
|
|
1583
1762
|
i0.ɵɵelementEnd();
|
|
1584
|
-
i0.ɵɵelementStart(9, "div",
|
|
1763
|
+
i0.ɵɵelementStart(9, "div", 272)(10, "h4");
|
|
1585
1764
|
i0.ɵɵtext(11, "Run B (Compare)");
|
|
1586
1765
|
i0.ɵɵelementEnd();
|
|
1587
|
-
i0.ɵɵconditionalCreate(12,
|
|
1588
|
-
i0.ɵɵconditionalCreate(13,
|
|
1766
|
+
i0.ɵɵconditionalCreate(12, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_Template, 3, 0, "div", 273);
|
|
1767
|
+
i0.ɵɵconditionalCreate(13, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_13_Template, 12, 5, "div", 274);
|
|
1589
1768
|
i0.ɵɵelementEnd()();
|
|
1590
|
-
i0.ɵɵconditionalCreate(14,
|
|
1591
|
-
i0.ɵɵconditionalCreate(15,
|
|
1592
|
-
i0.ɵɵconditionalCreate(16,
|
|
1593
|
-
i0.ɵɵconditionalCreate(17,
|
|
1769
|
+
i0.ɵɵconditionalCreate(14, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_Template, 47, 23, "div", 277);
|
|
1770
|
+
i0.ɵɵconditionalCreate(15, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_15_Template, 2, 0, "div", 99);
|
|
1771
|
+
i0.ɵɵconditionalCreate(16, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_16_Template, 7, 0, "div", 278);
|
|
1772
|
+
i0.ɵɵconditionalCreate(17, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_17_Template, 10, 0, "div", 101);
|
|
1594
1773
|
i0.ɵɵelementEnd();
|
|
1595
1774
|
} if (rf & 2) {
|
|
1596
1775
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -1611,50 +1790,59 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Template(rf, ctx) { if
|
|
|
1611
1790
|
i0.ɵɵadvance();
|
|
1612
1791
|
i0.ɵɵconditional(ctx_r0.runsLoaded && ctx_r0.suiteRuns.length < 2 ? 17 : -1);
|
|
1613
1792
|
} }
|
|
1614
|
-
function
|
|
1615
|
-
const
|
|
1616
|
-
i0.ɵɵelementStart(0, "div",
|
|
1617
|
-
i0.ɵɵelement(2, "i",
|
|
1793
|
+
function MJTestSuiteFormComponentExtended_Conditional_67_Template(rf, ctx) { if (rf & 1) {
|
|
1794
|
+
const _r49 = i0.ɵɵgetCurrentView();
|
|
1795
|
+
i0.ɵɵelementStart(0, "div", 46)(1, "div", 314);
|
|
1796
|
+
i0.ɵɵelement(2, "i", 45);
|
|
1618
1797
|
i0.ɵɵtext(3, " Shortcuts ");
|
|
1619
|
-
i0.ɵɵelementStart(4, "button",
|
|
1620
|
-
i0.ɵɵlistener("click", function
|
|
1621
|
-
i0.ɵɵelement(5, "i",
|
|
1798
|
+
i0.ɵɵelementStart(4, "button", 315);
|
|
1799
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_67_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r49); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.toggleShortcuts()); });
|
|
1800
|
+
i0.ɵɵelement(5, "i", 91);
|
|
1622
1801
|
i0.ɵɵelementEnd()();
|
|
1623
|
-
i0.ɵɵelementStart(6, "div",
|
|
1624
|
-
i0.ɵɵtext(9, "
|
|
1802
|
+
i0.ɵɵelementStart(6, "div", 316)(7, "div", 317)(8, "span");
|
|
1803
|
+
i0.ɵɵtext(9, "Save changes");
|
|
1625
1804
|
i0.ɵɵelementEnd();
|
|
1626
|
-
i0.ɵɵelementStart(10, "span",
|
|
1805
|
+
i0.ɵɵelementStart(10, "span", 318)(11, "kbd");
|
|
1627
1806
|
i0.ɵɵtext(12, "Cmd");
|
|
1628
1807
|
i0.ɵɵelementEnd();
|
|
1629
1808
|
i0.ɵɵelementStart(13, "kbd");
|
|
1630
|
-
i0.ɵɵtext(14, "
|
|
1809
|
+
i0.ɵɵtext(14, "S");
|
|
1631
1810
|
i0.ɵɵelementEnd()()();
|
|
1632
|
-
i0.ɵɵelementStart(15, "div",
|
|
1633
|
-
i0.ɵɵtext(17, "
|
|
1811
|
+
i0.ɵɵelementStart(15, "div", 317)(16, "span");
|
|
1812
|
+
i0.ɵɵtext(17, "Refresh");
|
|
1634
1813
|
i0.ɵɵelementEnd();
|
|
1635
|
-
i0.ɵɵelementStart(18, "span",
|
|
1814
|
+
i0.ɵɵelementStart(18, "span", 318)(19, "kbd");
|
|
1636
1815
|
i0.ɵɵtext(20, "Cmd");
|
|
1637
1816
|
i0.ɵɵelementEnd();
|
|
1638
1817
|
i0.ɵɵelementStart(21, "kbd");
|
|
1639
|
-
i0.ɵɵtext(22, "
|
|
1818
|
+
i0.ɵɵtext(22, "R");
|
|
1819
|
+
i0.ɵɵelementEnd()()();
|
|
1820
|
+
i0.ɵɵelementStart(23, "div", 317)(24, "span");
|
|
1821
|
+
i0.ɵɵtext(25, "Run Suite");
|
|
1822
|
+
i0.ɵɵelementEnd();
|
|
1823
|
+
i0.ɵɵelementStart(26, "span", 318)(27, "kbd");
|
|
1824
|
+
i0.ɵɵtext(28, "Cmd");
|
|
1825
|
+
i0.ɵɵelementEnd();
|
|
1826
|
+
i0.ɵɵelementStart(29, "kbd");
|
|
1827
|
+
i0.ɵɵtext(30, "Enter");
|
|
1640
1828
|
i0.ɵɵelementEnd()()();
|
|
1641
|
-
i0.ɵɵelementStart(
|
|
1642
|
-
i0.ɵɵtext(
|
|
1829
|
+
i0.ɵɵelementStart(31, "div", 317)(32, "span");
|
|
1830
|
+
i0.ɵɵtext(33, "Switch Tabs");
|
|
1643
1831
|
i0.ɵɵelementEnd();
|
|
1644
|
-
i0.ɵɵelementStart(
|
|
1645
|
-
i0.ɵɵtext(
|
|
1832
|
+
i0.ɵɵelementStart(34, "span", 318)(35, "kbd");
|
|
1833
|
+
i0.ɵɵtext(36, "1");
|
|
1646
1834
|
i0.ɵɵelementEnd();
|
|
1647
|
-
i0.ɵɵtext(
|
|
1648
|
-
i0.ɵɵelementStart(
|
|
1649
|
-
i0.ɵɵtext(
|
|
1835
|
+
i0.ɵɵtext(37, "-");
|
|
1836
|
+
i0.ɵɵelementStart(38, "kbd");
|
|
1837
|
+
i0.ɵɵtext(39, "5");
|
|
1650
1838
|
i0.ɵɵelementEnd()()()()();
|
|
1651
1839
|
} }
|
|
1652
|
-
function
|
|
1653
|
-
const
|
|
1654
|
-
i0.ɵɵelementStart(0, "mj-slide-panel",
|
|
1655
|
-
i0.ɵɵlistener("Closed", function
|
|
1656
|
-
i0.ɵɵelementStart(1, "app-test-run-dialog",
|
|
1657
|
-
i0.ɵɵlistener("PanelClose", function
|
|
1840
|
+
function MJTestSuiteFormComponentExtended_Conditional_68_Template(rf, ctx) { if (rf & 1) {
|
|
1841
|
+
const _r50 = i0.ɵɵgetCurrentView();
|
|
1842
|
+
i0.ɵɵelementStart(0, "mj-slide-panel", 319);
|
|
1843
|
+
i0.ɵɵlistener("Closed", function MJTestSuiteFormComponentExtended_Conditional_68_Template_mj_slide_panel_Closed_0_listener() { i0.ɵɵrestoreView(_r50); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnPanelClosed()); });
|
|
1844
|
+
i0.ɵɵelementStart(1, "app-test-run-dialog", 320);
|
|
1845
|
+
i0.ɵɵlistener("PanelClose", function MJTestSuiteFormComponentExtended_Conditional_68_Template_app_test_run_dialog_PanelClose_1_listener() { i0.ɵɵrestoreView(_r50); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnPanelClosed()); });
|
|
1658
1846
|
i0.ɵɵelementEnd()();
|
|
1659
1847
|
} if (rf & 2) {
|
|
1660
1848
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -1662,6 +1850,247 @@ function MJTestSuiteFormComponentExtended_Conditional_66_Template(rf, ctx) { if
|
|
|
1662
1850
|
i0.ɵɵadvance();
|
|
1663
1851
|
i0.ɵɵproperty("PanelMode", true)("selectedTestId", (ctx_r0.testingDialogService.PanelOptions == null ? null : ctx_r0.testingDialogService.PanelOptions.testId) ?? null)("selectedSuiteId", (ctx_r0.testingDialogService.PanelOptions == null ? null : ctx_r0.testingDialogService.PanelOptions.suiteId) ?? null)("runMode", (ctx_r0.testingDialogService.PanelOptions == null ? null : ctx_r0.testingDialogService.PanelOptions.mode) ?? "suite");
|
|
1664
1852
|
} }
|
|
1853
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
1854
|
+
const _r52 = i0.ɵɵgetCurrentView();
|
|
1855
|
+
i0.ɵɵelementStart(0, "button", 342);
|
|
1856
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_12_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r52); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.addTestsSearch = ""); });
|
|
1857
|
+
i0.ɵɵelement(1, "i", 91);
|
|
1858
|
+
i0.ɵɵelementEnd();
|
|
1859
|
+
} }
|
|
1860
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
1861
|
+
i0.ɵɵelementStart(0, "strong");
|
|
1862
|
+
i0.ɵɵtext(1);
|
|
1863
|
+
i0.ɵɵelementEnd();
|
|
1864
|
+
i0.ɵɵtext(2, " selected ");
|
|
1865
|
+
} if (rf & 2) {
|
|
1866
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1867
|
+
i0.ɵɵadvance();
|
|
1868
|
+
i0.ɵɵtextInterpolate(ctx_r0.selectedTestIdsToAdd.size);
|
|
1869
|
+
} }
|
|
1870
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
1871
|
+
i0.ɵɵtext(0);
|
|
1872
|
+
} if (rf & 2) {
|
|
1873
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1874
|
+
i0.ɵɵtextInterpolate2(" ", ctx_r0.filteredAvailableTests.length, " test", ctx_r0.filteredAvailableTests.length === 1 ? "" : "s", " available ");
|
|
1875
|
+
} }
|
|
1876
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
1877
|
+
i0.ɵɵelementStart(0, "div", 336);
|
|
1878
|
+
i0.ɵɵelement(1, "mj-loading", 343);
|
|
1879
|
+
i0.ɵɵelementEnd();
|
|
1880
|
+
} }
|
|
1881
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_24_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1882
|
+
i0.ɵɵelement(0, "i", 145);
|
|
1883
|
+
i0.ɵɵelementStart(1, "h4");
|
|
1884
|
+
i0.ɵɵtext(2, "Everything's already in the suite");
|
|
1885
|
+
i0.ɵɵelementEnd();
|
|
1886
|
+
i0.ɵɵelementStart(3, "p");
|
|
1887
|
+
i0.ɵɵtext(4, "This suite contains every available test. Create a new test first to add more.");
|
|
1888
|
+
i0.ɵɵelementEnd();
|
|
1889
|
+
} }
|
|
1890
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_24_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1891
|
+
i0.ɵɵelement(0, "i", 205);
|
|
1892
|
+
i0.ɵɵelementStart(1, "h4");
|
|
1893
|
+
i0.ɵɵtext(2, "No matches");
|
|
1894
|
+
i0.ɵɵelementEnd();
|
|
1895
|
+
i0.ɵɵelementStart(3, "p");
|
|
1896
|
+
i0.ɵɵtext(4);
|
|
1897
|
+
i0.ɵɵelementEnd();
|
|
1898
|
+
} if (rf & 2) {
|
|
1899
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1900
|
+
i0.ɵɵadvance(4);
|
|
1901
|
+
i0.ɵɵtextInterpolate1("No tests match \"", ctx_r0.addTestsSearch, "\".");
|
|
1902
|
+
} }
|
|
1903
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_24_Template(rf, ctx) { if (rf & 1) {
|
|
1904
|
+
i0.ɵɵelementStart(0, "div", 337);
|
|
1905
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_24_Conditional_1_Template, 5, 0)(2, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_24_Conditional_2_Template, 5, 1);
|
|
1906
|
+
i0.ɵɵelementEnd();
|
|
1907
|
+
} if (rf & 2) {
|
|
1908
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1909
|
+
i0.ɵɵadvance();
|
|
1910
|
+
i0.ɵɵconditional(ctx_r0.availableTests.length === 0 ? 1 : 2);
|
|
1911
|
+
} }
|
|
1912
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1913
|
+
i0.ɵɵelement(0, "i", 175);
|
|
1914
|
+
} }
|
|
1915
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
1916
|
+
i0.ɵɵelementStart(0, "div", 349);
|
|
1917
|
+
i0.ɵɵtext(1);
|
|
1918
|
+
i0.ɵɵelementEnd();
|
|
1919
|
+
} if (rf & 2) {
|
|
1920
|
+
const t_r54 = i0.ɵɵnextContext().$implicit;
|
|
1921
|
+
i0.ɵɵadvance();
|
|
1922
|
+
i0.ɵɵtextInterpolate(t_r54.Description);
|
|
1923
|
+
} }
|
|
1924
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
1925
|
+
i0.ɵɵelementStart(0, "span", 351);
|
|
1926
|
+
i0.ɵɵtext(1);
|
|
1927
|
+
i0.ɵɵelementEnd();
|
|
1928
|
+
} if (rf & 2) {
|
|
1929
|
+
const t_r54 = i0.ɵɵnextContext().$implicit;
|
|
1930
|
+
i0.ɵɵadvance();
|
|
1931
|
+
i0.ɵɵtextInterpolate(t_r54.Type);
|
|
1932
|
+
} }
|
|
1933
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1934
|
+
const _r53 = i0.ɵɵgetCurrentView();
|
|
1935
|
+
i0.ɵɵelementStart(0, "li", 345);
|
|
1936
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Template_li_click_0_listener() { const t_r54 = i0.ɵɵrestoreView(_r53).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.toggleAddSelection(t_r54.ID)); });
|
|
1937
|
+
i0.ɵɵelementStart(1, "span", 346);
|
|
1938
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Conditional_2_Template, 1, 0, "i", 175);
|
|
1939
|
+
i0.ɵɵelementEnd();
|
|
1940
|
+
i0.ɵɵelementStart(3, "div", 347)(4, "div", 348);
|
|
1941
|
+
i0.ɵɵtext(5);
|
|
1942
|
+
i0.ɵɵelementEnd();
|
|
1943
|
+
i0.ɵɵconditionalCreate(6, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Conditional_6_Template, 2, 1, "div", 349);
|
|
1944
|
+
i0.ɵɵelementEnd();
|
|
1945
|
+
i0.ɵɵelementStart(7, "div", 350);
|
|
1946
|
+
i0.ɵɵconditionalCreate(8, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Conditional_8_Template, 2, 1, "span", 351);
|
|
1947
|
+
i0.ɵɵelementStart(9, "span", 352);
|
|
1948
|
+
i0.ɵɵtext(10);
|
|
1949
|
+
i0.ɵɵelementEnd()()();
|
|
1950
|
+
} if (rf & 2) {
|
|
1951
|
+
const t_r54 = ctx.$implicit;
|
|
1952
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1953
|
+
i0.ɵɵclassProp("picker-row--selected", ctx_r0.isAddSelected(t_r54.ID));
|
|
1954
|
+
i0.ɵɵattribute("aria-checked", ctx_r0.isAddSelected(t_r54.ID));
|
|
1955
|
+
i0.ɵɵadvance(2);
|
|
1956
|
+
i0.ɵɵconditional(ctx_r0.isAddSelected(t_r54.ID) ? 2 : -1);
|
|
1957
|
+
i0.ɵɵadvance(3);
|
|
1958
|
+
i0.ɵɵtextInterpolate(t_r54.Name);
|
|
1959
|
+
i0.ɵɵadvance();
|
|
1960
|
+
i0.ɵɵconditional(t_r54.Description ? 6 : -1);
|
|
1961
|
+
i0.ɵɵadvance(2);
|
|
1962
|
+
i0.ɵɵconditional(t_r54.Type ? 8 : -1);
|
|
1963
|
+
i0.ɵɵadvance();
|
|
1964
|
+
i0.ɵɵattribute("data-status", t_r54.Status == null ? null : t_r54.Status.toLowerCase());
|
|
1965
|
+
i0.ɵɵadvance();
|
|
1966
|
+
i0.ɵɵtextInterpolate(t_r54.Status);
|
|
1967
|
+
} }
|
|
1968
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
1969
|
+
i0.ɵɵelementStart(0, "ul", 338);
|
|
1970
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Template, 11, 9, "li", 344, _forTrack0);
|
|
1971
|
+
i0.ɵɵelementEnd();
|
|
1972
|
+
} if (rf & 2) {
|
|
1973
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1974
|
+
i0.ɵɵadvance();
|
|
1975
|
+
i0.ɵɵrepeater(ctx_r0.filteredAvailableTests);
|
|
1976
|
+
} }
|
|
1977
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_28_Template(rf, ctx) { if (rf & 1) {
|
|
1978
|
+
i0.ɵɵelement(0, "i", 123);
|
|
1979
|
+
i0.ɵɵtext(1, " Adding\u2026 ");
|
|
1980
|
+
} }
|
|
1981
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_29_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1982
|
+
i0.ɵɵtext(0, " Add tests ");
|
|
1983
|
+
} }
|
|
1984
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_29_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1985
|
+
i0.ɵɵtext(0, " Add 1 test ");
|
|
1986
|
+
} }
|
|
1987
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_29_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
1988
|
+
i0.ɵɵtext(0);
|
|
1989
|
+
} if (rf & 2) {
|
|
1990
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1991
|
+
i0.ɵɵtextInterpolate1(" Add ", ctx_r0.selectedTestIdsToAdd.size, " tests ");
|
|
1992
|
+
} }
|
|
1993
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_29_Template(rf, ctx) { if (rf & 1) {
|
|
1994
|
+
i0.ɵɵelement(0, "i", 175);
|
|
1995
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_29_Conditional_1_Template, 1, 0)(2, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_29_Conditional_2_Template, 1, 0)(3, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_29_Conditional_3_Template, 1, 1);
|
|
1996
|
+
} if (rf & 2) {
|
|
1997
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1998
|
+
i0.ɵɵadvance();
|
|
1999
|
+
i0.ɵɵconditional(ctx_r0.selectedTestIdsToAdd.size === 0 ? 1 : ctx_r0.selectedTestIdsToAdd.size === 1 ? 2 : 3);
|
|
2000
|
+
} }
|
|
2001
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Template(rf, ctx) { if (rf & 1) {
|
|
2002
|
+
const _r51 = i0.ɵɵgetCurrentView();
|
|
2003
|
+
i0.ɵɵelementStart(0, "div", 321);
|
|
2004
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_69_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r51); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeAddTestsDialog()); });
|
|
2005
|
+
i0.ɵɵelementEnd();
|
|
2006
|
+
i0.ɵɵelementStart(1, "div", 322);
|
|
2007
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_69_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r51); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
2008
|
+
i0.ɵɵelementStart(2, "div", 323)(3, "h2", 324);
|
|
2009
|
+
i0.ɵɵelement(4, "i", 325);
|
|
2010
|
+
i0.ɵɵtext(5, " Add tests to suite ");
|
|
2011
|
+
i0.ɵɵelementEnd();
|
|
2012
|
+
i0.ɵɵelementStart(6, "button", 326);
|
|
2013
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_69_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r51); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeAddTestsDialog()); });
|
|
2014
|
+
i0.ɵɵelement(7, "i", 91);
|
|
2015
|
+
i0.ɵɵelementEnd()();
|
|
2016
|
+
i0.ɵɵelementStart(8, "div", 327);
|
|
2017
|
+
i0.ɵɵelement(9, "i", 328);
|
|
2018
|
+
i0.ɵɵelementStart(10, "input", 329, 2);
|
|
2019
|
+
i0.ɵɵtwoWayListener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_69_Template_input_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r51); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.addTestsSearch, $event) || (ctx_r0.addTestsSearch = $event); return i0.ɵɵresetView($event); });
|
|
2020
|
+
i0.ɵɵelementEnd();
|
|
2021
|
+
i0.ɵɵconditionalCreate(12, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_12_Template, 2, 0, "button", 330);
|
|
2022
|
+
i0.ɵɵelementEnd();
|
|
2023
|
+
i0.ɵɵelementStart(13, "div", 331)(14, "span", 332);
|
|
2024
|
+
i0.ɵɵconditionalCreate(15, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_15_Template, 3, 1)(16, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_16_Template, 1, 2);
|
|
2025
|
+
i0.ɵɵelementEnd();
|
|
2026
|
+
i0.ɵɵelementStart(17, "div", 333)(18, "button", 334);
|
|
2027
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_69_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r51); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.selectAllFiltered()); });
|
|
2028
|
+
i0.ɵɵtext(19, " Select all ");
|
|
2029
|
+
i0.ɵɵelementEnd();
|
|
2030
|
+
i0.ɵɵelementStart(20, "button", 334);
|
|
2031
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_69_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r51); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.clearAddSelection()); });
|
|
2032
|
+
i0.ɵɵtext(21, " Clear ");
|
|
2033
|
+
i0.ɵɵelementEnd()()();
|
|
2034
|
+
i0.ɵɵelementStart(22, "div", 335);
|
|
2035
|
+
i0.ɵɵconditionalCreate(23, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_23_Template, 2, 0, "div", 336)(24, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_24_Template, 3, 1, "div", 337)(25, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_Template, 3, 0, "ul", 338);
|
|
2036
|
+
i0.ɵɵelementEnd();
|
|
2037
|
+
i0.ɵɵelementStart(26, "div", 339)(27, "button", 340);
|
|
2038
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_69_Template_button_click_27_listener() { i0.ɵɵrestoreView(_r51); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.confirmAddTests()); });
|
|
2039
|
+
i0.ɵɵconditionalCreate(28, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_28_Template, 2, 0)(29, MJTestSuiteFormComponentExtended_Conditional_69_Conditional_29_Template, 4, 1);
|
|
2040
|
+
i0.ɵɵelementEnd();
|
|
2041
|
+
i0.ɵɵelementStart(30, "button", 341);
|
|
2042
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_69_Template_button_click_30_listener() { i0.ɵɵrestoreView(_r51); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeAddTestsDialog()); });
|
|
2043
|
+
i0.ɵɵtext(31, " Cancel ");
|
|
2044
|
+
i0.ɵɵelementEnd()()();
|
|
2045
|
+
} if (rf & 2) {
|
|
2046
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
2047
|
+
i0.ɵɵadvance(6);
|
|
2048
|
+
i0.ɵɵproperty("disabled", ctx_r0.isAddingTests);
|
|
2049
|
+
i0.ɵɵadvance(4);
|
|
2050
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r0.addTestsSearch);
|
|
2051
|
+
i0.ɵɵadvance(2);
|
|
2052
|
+
i0.ɵɵconditional(ctx_r0.addTestsSearch ? 12 : -1);
|
|
2053
|
+
i0.ɵɵadvance(3);
|
|
2054
|
+
i0.ɵɵconditional(ctx_r0.selectedTestIdsToAdd.size > 0 ? 15 : !ctx_r0.loadingAvailableTests ? 16 : -1);
|
|
2055
|
+
i0.ɵɵadvance(3);
|
|
2056
|
+
i0.ɵɵproperty("disabled", ctx_r0.loadingAvailableTests || ctx_r0.filteredAvailableTests.length === 0);
|
|
2057
|
+
i0.ɵɵadvance(2);
|
|
2058
|
+
i0.ɵɵproperty("disabled", ctx_r0.selectedTestIdsToAdd.size === 0);
|
|
2059
|
+
i0.ɵɵadvance(3);
|
|
2060
|
+
i0.ɵɵconditional(ctx_r0.loadingAvailableTests ? 23 : ctx_r0.filteredAvailableTests.length === 0 ? 24 : 25);
|
|
2061
|
+
i0.ɵɵadvance(4);
|
|
2062
|
+
i0.ɵɵproperty("disabled", ctx_r0.selectedTestIdsToAdd.size === 0 || ctx_r0.isAddingTests);
|
|
2063
|
+
i0.ɵɵadvance();
|
|
2064
|
+
i0.ɵɵconditional(ctx_r0.isAddingTests ? 28 : 29);
|
|
2065
|
+
i0.ɵɵadvance(2);
|
|
2066
|
+
i0.ɵɵproperty("disabled", ctx_r0.isAddingTests);
|
|
2067
|
+
} }
|
|
2068
|
+
function MJTestSuiteFormComponentExtended_Conditional_78_Template(rf, ctx) { if (rf & 1) {
|
|
2069
|
+
i0.ɵɵtext(0);
|
|
2070
|
+
} if (rf & 2) {
|
|
2071
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
2072
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r0.dirtyFieldNames[0], " edited ");
|
|
2073
|
+
} }
|
|
2074
|
+
function MJTestSuiteFormComponentExtended_Conditional_79_Template(rf, ctx) { if (rf & 1) {
|
|
2075
|
+
i0.ɵɵtext(0);
|
|
2076
|
+
} if (rf & 2) {
|
|
2077
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
2078
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r0.dirtyFieldNames.length, " fields edited ");
|
|
2079
|
+
} }
|
|
2080
|
+
function MJTestSuiteFormComponentExtended_Conditional_82_Template(rf, ctx) { if (rf & 1) {
|
|
2081
|
+
i0.ɵɵelement(0, "i", 123);
|
|
2082
|
+
i0.ɵɵtext(1, " Saving\u2026 ");
|
|
2083
|
+
} }
|
|
2084
|
+
function MJTestSuiteFormComponentExtended_Conditional_83_Template(rf, ctx) { if (rf & 1) {
|
|
2085
|
+
i0.ɵɵelement(0, "i", 175);
|
|
2086
|
+
i0.ɵɵtext(1, " Save changes ");
|
|
2087
|
+
i0.ɵɵelementStart(2, "span", 353)(3, "kbd");
|
|
2088
|
+
i0.ɵɵtext(4, "\u2318");
|
|
2089
|
+
i0.ɵɵelementEnd();
|
|
2090
|
+
i0.ɵɵelementStart(5, "kbd");
|
|
2091
|
+
i0.ɵɵtext(6, "S");
|
|
2092
|
+
i0.ɵɵelementEnd()();
|
|
2093
|
+
} }
|
|
1665
2094
|
/** Settings key for keyboard shortcuts visibility */
|
|
1666
2095
|
const SHORTCUTS_SETTINGS_KEY = '__mj.Testing.ShowKeyboardShortcuts';
|
|
1667
2096
|
let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended extends MJTestSuiteFormComponent {
|
|
@@ -1715,6 +2144,23 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
1715
2144
|
// Matrix test name filter
|
|
1716
2145
|
this.matrixTestFilter = '';
|
|
1717
2146
|
this.matrixFilterSubject$ = new Subject();
|
|
2147
|
+
// Edit state
|
|
2148
|
+
this.isSaving = false;
|
|
2149
|
+
this.parentSuiteOptions = [];
|
|
2150
|
+
this.tagDraft = '';
|
|
2151
|
+
this.statusOptions = ['Active', 'Pending', 'Disabled'];
|
|
2152
|
+
// Add Tests picker state
|
|
2153
|
+
this.showAddTestsDialog = false;
|
|
2154
|
+
this.availableTests = [];
|
|
2155
|
+
this.loadingAvailableTests = false;
|
|
2156
|
+
this.selectedTestIdsToAdd = new Set();
|
|
2157
|
+
this.addTestsSearch = '';
|
|
2158
|
+
this.isAddingTests = false;
|
|
2159
|
+
// Remove-confirm state (per-row inline confirm)
|
|
2160
|
+
this.confirmingRemoveSuiteTestId = null;
|
|
2161
|
+
this.isRemovingTest = false;
|
|
2162
|
+
// Reorder state
|
|
2163
|
+
this.isReorderingTests = false;
|
|
1718
2164
|
// Service injections
|
|
1719
2165
|
this.navigationService = inject(NavigationService);
|
|
1720
2166
|
this.testingDialogService = inject(TestingDialogService);
|
|
@@ -1726,6 +2172,8 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
1726
2172
|
async ngOnInit() {
|
|
1727
2173
|
await super.ngOnInit();
|
|
1728
2174
|
this.loadShortcutsSetting();
|
|
2175
|
+
// Fire-and-forget: parent suite list for the edit form
|
|
2176
|
+
this.loadParentSuiteOptions();
|
|
1729
2177
|
// Subscribe to evaluation preferences
|
|
1730
2178
|
this.evalPrefsService.preferences$
|
|
1731
2179
|
.pipe(takeUntil(this.destroy$))
|
|
@@ -1762,6 +2210,14 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
1762
2210
|
handleKeyboardShortcut(event) {
|
|
1763
2211
|
if (!this.keyboardShortcutsEnabled)
|
|
1764
2212
|
return;
|
|
2213
|
+
// Cmd/Ctrl + S: Save (if dirty)
|
|
2214
|
+
if ((event.metaKey || event.ctrlKey) && event.key === 's' && !event.shiftKey) {
|
|
2215
|
+
if (this.isDirty) {
|
|
2216
|
+
event.preventDefault();
|
|
2217
|
+
this.saveChanges();
|
|
2218
|
+
}
|
|
2219
|
+
return;
|
|
2220
|
+
}
|
|
1765
2221
|
// Cmd/Ctrl + R: Refresh
|
|
1766
2222
|
if ((event.metaKey || event.ctrlKey) && event.key === 'r' && !event.shiftKey) {
|
|
1767
2223
|
event.preventDefault();
|
|
@@ -1774,8 +2230,8 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
1774
2230
|
this.runSuite();
|
|
1775
2231
|
return;
|
|
1776
2232
|
}
|
|
1777
|
-
// Number keys for tabs (1-5)
|
|
1778
|
-
if (!event.metaKey && !event.ctrlKey && !event.altKey) {
|
|
2233
|
+
// Number keys for tabs (1-5) — skip when typing into form inputs
|
|
2234
|
+
if (!event.metaKey && !event.ctrlKey && !event.altKey && !this.isTextInputFocused()) {
|
|
1779
2235
|
switch (event.key) {
|
|
1780
2236
|
case '1':
|
|
1781
2237
|
this.changeTab('overview');
|
|
@@ -1795,6 +2251,20 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
1795
2251
|
}
|
|
1796
2252
|
}
|
|
1797
2253
|
}
|
|
2254
|
+
// Warn before tab close / hard navigation when there are unsaved changes
|
|
2255
|
+
handleBeforeUnload(event) {
|
|
2256
|
+
if (this.isDirty) {
|
|
2257
|
+
event.preventDefault();
|
|
2258
|
+
event.returnValue = '';
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
isTextInputFocused() {
|
|
2262
|
+
const el = document.activeElement;
|
|
2263
|
+
if (!el)
|
|
2264
|
+
return false;
|
|
2265
|
+
const tag = el.tagName;
|
|
2266
|
+
return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable;
|
|
2267
|
+
}
|
|
1798
2268
|
changeTab(tab) {
|
|
1799
2269
|
this.activeTab = tab;
|
|
1800
2270
|
if (tab === 'tests' && !this.testsLoaded)
|
|
@@ -3376,6 +3846,351 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
3376
3846
|
IsCompareRunB(run) {
|
|
3377
3847
|
return UUIDsEqual(this.compareRunB?.ID, run.ID);
|
|
3378
3848
|
}
|
|
3849
|
+
// ==========================================
|
|
3850
|
+
// Edit / Save Methods
|
|
3851
|
+
// ==========================================
|
|
3852
|
+
/** True if the suite record has any unsaved field changes. */
|
|
3853
|
+
get isDirty() {
|
|
3854
|
+
return this.record?.Dirty === true;
|
|
3855
|
+
}
|
|
3856
|
+
/** Names of fields with pending edits, used by the save bar. */
|
|
3857
|
+
get dirtyFieldNames() {
|
|
3858
|
+
if (!this.record?.Fields)
|
|
3859
|
+
return [];
|
|
3860
|
+
return this.record.Fields.filter(f => f.Dirty).map(f => f.Name);
|
|
3861
|
+
}
|
|
3862
|
+
/** Parsed tags as a plain array — derived from record.Tags JSON. */
|
|
3863
|
+
get tags() {
|
|
3864
|
+
return TagsHelper.parseTags(this.record?.Tags);
|
|
3865
|
+
}
|
|
3866
|
+
/**
|
|
3867
|
+
* Load all suites for the Parent Suite dropdown. Excludes the current
|
|
3868
|
+
* suite (a suite cannot be its own parent).
|
|
3869
|
+
*/
|
|
3870
|
+
async loadParentSuiteOptions() {
|
|
3871
|
+
try {
|
|
3872
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
3873
|
+
const result = await rv.RunView({
|
|
3874
|
+
EntityName: 'MJ: Test Suites',
|
|
3875
|
+
ExtraFilter: this.record?.ID ? `ID <> '${this.record.ID}'` : '',
|
|
3876
|
+
OrderBy: 'Name',
|
|
3877
|
+
ResultType: 'entity_object'
|
|
3878
|
+
});
|
|
3879
|
+
if (result.Success) {
|
|
3880
|
+
this.parentSuiteOptions = result.Results || [];
|
|
3881
|
+
this.cdr.markForCheck();
|
|
3882
|
+
}
|
|
3883
|
+
}
|
|
3884
|
+
catch (error) {
|
|
3885
|
+
console.warn('Failed to load parent suite options:', error);
|
|
3886
|
+
}
|
|
3887
|
+
}
|
|
3888
|
+
/** Save all pending changes on the suite record. */
|
|
3889
|
+
async saveChanges() {
|
|
3890
|
+
if (!this.isDirty || this.isSaving)
|
|
3891
|
+
return;
|
|
3892
|
+
this.isSaving = true;
|
|
3893
|
+
this.cdr.markForCheck();
|
|
3894
|
+
try {
|
|
3895
|
+
const ok = await this.SaveRecord(false);
|
|
3896
|
+
if (ok) {
|
|
3897
|
+
SharedService.Instance.CreateSimpleNotification('Suite saved', 'success', 2000);
|
|
3898
|
+
}
|
|
3899
|
+
else {
|
|
3900
|
+
const detail = this.record?.LatestResult?.CompleteMessage || this.record?.LatestResult?.Message || 'Save failed';
|
|
3901
|
+
SharedService.Instance.CreateSimpleNotification(detail, 'error', 4000);
|
|
3902
|
+
}
|
|
3903
|
+
}
|
|
3904
|
+
catch (err) {
|
|
3905
|
+
const msg = err instanceof Error ? err.message : 'Save failed';
|
|
3906
|
+
SharedService.Instance.CreateSimpleNotification(msg, 'error', 4000);
|
|
3907
|
+
}
|
|
3908
|
+
finally {
|
|
3909
|
+
this.isSaving = false;
|
|
3910
|
+
this.cdr.markForCheck();
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
/** Discard all pending field changes on the suite. */
|
|
3914
|
+
discardChanges() {
|
|
3915
|
+
if (!this.isDirty)
|
|
3916
|
+
return;
|
|
3917
|
+
if (!confirm('Discard your unsaved changes?'))
|
|
3918
|
+
return;
|
|
3919
|
+
this.record.Revert();
|
|
3920
|
+
this.tagDraft = '';
|
|
3921
|
+
this.cdr.markForCheck();
|
|
3922
|
+
}
|
|
3923
|
+
/** Add a tag from tagDraft (called on Enter / comma / blur). */
|
|
3924
|
+
addTagFromDraft() {
|
|
3925
|
+
const raw = this.tagDraft.trim();
|
|
3926
|
+
if (!raw)
|
|
3927
|
+
return;
|
|
3928
|
+
// Allow comma-separated entry: "alpha, beta" → two tags
|
|
3929
|
+
const incoming = raw.split(',').map(t => t.trim()).filter(t => t.length > 0);
|
|
3930
|
+
const existing = this.tags;
|
|
3931
|
+
const merged = [...existing];
|
|
3932
|
+
for (const t of incoming) {
|
|
3933
|
+
if (!merged.includes(t))
|
|
3934
|
+
merged.push(t);
|
|
3935
|
+
}
|
|
3936
|
+
this.record.Tags = TagsHelper.toJson(merged);
|
|
3937
|
+
this.tagDraft = '';
|
|
3938
|
+
this.cdr.markForCheck();
|
|
3939
|
+
}
|
|
3940
|
+
/** Remove a single tag. */
|
|
3941
|
+
removeTag(tag) {
|
|
3942
|
+
this.record.Tags = TagsHelper.removeTag(this.record.Tags, tag);
|
|
3943
|
+
this.cdr.markForCheck();
|
|
3944
|
+
}
|
|
3945
|
+
/** Handle Enter / comma in the tag input to commit the draft tag. */
|
|
3946
|
+
onTagInputKeydown(event) {
|
|
3947
|
+
if (event.key === 'Enter' || event.key === ',') {
|
|
3948
|
+
event.preventDefault();
|
|
3949
|
+
this.addTagFromDraft();
|
|
3950
|
+
return;
|
|
3951
|
+
}
|
|
3952
|
+
// Backspace on an empty draft pops the last chip
|
|
3953
|
+
if (event.key === 'Backspace' && !this.tagDraft) {
|
|
3954
|
+
const all = this.tags;
|
|
3955
|
+
if (all.length > 0) {
|
|
3956
|
+
event.preventDefault();
|
|
3957
|
+
this.removeTag(all[all.length - 1]);
|
|
3958
|
+
}
|
|
3959
|
+
}
|
|
3960
|
+
}
|
|
3961
|
+
// ==========================================
|
|
3962
|
+
// Suite Membership: Add / Remove / Reorder Tests
|
|
3963
|
+
// ==========================================
|
|
3964
|
+
/** Open the picker dialog and load tests not yet in this suite. */
|
|
3965
|
+
async openAddTestsDialog() {
|
|
3966
|
+
this.showAddTestsDialog = true;
|
|
3967
|
+
this.selectedTestIdsToAdd = new Set();
|
|
3968
|
+
this.addTestsSearch = '';
|
|
3969
|
+
this.loadingAvailableTests = true;
|
|
3970
|
+
this.cdr.markForCheck();
|
|
3971
|
+
try {
|
|
3972
|
+
if (!this.testsLoaded) {
|
|
3973
|
+
await this.loadTests();
|
|
3974
|
+
}
|
|
3975
|
+
const existingTestIds = new Set(this.suiteTests.map(st => st.TestID));
|
|
3976
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
3977
|
+
const result = await rv.RunView({
|
|
3978
|
+
EntityName: 'MJ: Tests',
|
|
3979
|
+
OrderBy: 'Name',
|
|
3980
|
+
ResultType: 'entity_object'
|
|
3981
|
+
});
|
|
3982
|
+
if (result.Success) {
|
|
3983
|
+
this.availableTests = (result.Results || []).filter(t => !existingTestIds.has(t.ID));
|
|
3984
|
+
}
|
|
3985
|
+
else {
|
|
3986
|
+
SharedService.Instance.CreateSimpleNotification('Failed to load tests', 'error', 3000);
|
|
3987
|
+
}
|
|
3988
|
+
}
|
|
3989
|
+
catch (err) {
|
|
3990
|
+
console.error('Error loading available tests:', err);
|
|
3991
|
+
SharedService.Instance.CreateSimpleNotification('Failed to load tests', 'error', 3000);
|
|
3992
|
+
}
|
|
3993
|
+
finally {
|
|
3994
|
+
this.loadingAvailableTests = false;
|
|
3995
|
+
this.cdr.markForCheck();
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
closeAddTestsDialog() {
|
|
3999
|
+
if (this.isAddingTests)
|
|
4000
|
+
return;
|
|
4001
|
+
this.showAddTestsDialog = false;
|
|
4002
|
+
this.selectedTestIdsToAdd = new Set();
|
|
4003
|
+
this.addTestsSearch = '';
|
|
4004
|
+
this.cdr.markForCheck();
|
|
4005
|
+
}
|
|
4006
|
+
toggleAddSelection(testId) {
|
|
4007
|
+
if (this.selectedTestIdsToAdd.has(testId)) {
|
|
4008
|
+
this.selectedTestIdsToAdd.delete(testId);
|
|
4009
|
+
}
|
|
4010
|
+
else {
|
|
4011
|
+
this.selectedTestIdsToAdd.add(testId);
|
|
4012
|
+
}
|
|
4013
|
+
// Set mutation alone doesn't trigger OnPush — assign a new reference
|
|
4014
|
+
this.selectedTestIdsToAdd = new Set(this.selectedTestIdsToAdd);
|
|
4015
|
+
this.cdr.markForCheck();
|
|
4016
|
+
}
|
|
4017
|
+
isAddSelected(testId) {
|
|
4018
|
+
return this.selectedTestIdsToAdd.has(testId);
|
|
4019
|
+
}
|
|
4020
|
+
/** Tests that match the picker search filter. */
|
|
4021
|
+
get filteredAvailableTests() {
|
|
4022
|
+
const q = this.addTestsSearch.trim().toLowerCase();
|
|
4023
|
+
if (!q)
|
|
4024
|
+
return this.availableTests;
|
|
4025
|
+
return this.availableTests.filter(t => (t.Name || '').toLowerCase().includes(q) ||
|
|
4026
|
+
(t.Description || '').toLowerCase().includes(q) ||
|
|
4027
|
+
(t.Type || '').toLowerCase().includes(q));
|
|
4028
|
+
}
|
|
4029
|
+
selectAllFiltered() {
|
|
4030
|
+
for (const t of this.filteredAvailableTests) {
|
|
4031
|
+
this.selectedTestIdsToAdd.add(t.ID);
|
|
4032
|
+
}
|
|
4033
|
+
this.selectedTestIdsToAdd = new Set(this.selectedTestIdsToAdd);
|
|
4034
|
+
this.cdr.markForCheck();
|
|
4035
|
+
}
|
|
4036
|
+
clearAddSelection() {
|
|
4037
|
+
this.selectedTestIdsToAdd = new Set();
|
|
4038
|
+
this.cdr.markForCheck();
|
|
4039
|
+
}
|
|
4040
|
+
/** Create suite-test rows for every selected test, appended after existing ones. */
|
|
4041
|
+
async confirmAddTests() {
|
|
4042
|
+
if (this.selectedTestIdsToAdd.size === 0 || this.isAddingTests)
|
|
4043
|
+
return;
|
|
4044
|
+
this.isAddingTests = true;
|
|
4045
|
+
this.cdr.markForCheck();
|
|
4046
|
+
const provider = this.ProviderToUse;
|
|
4047
|
+
const startSequence = this.suiteTests.reduce((max, st) => Math.max(max, st.Sequence ?? 0), 0);
|
|
4048
|
+
const idsToAdd = Array.from(this.selectedTestIdsToAdd);
|
|
4049
|
+
// Snapshot test names from the picker so we can hydrate the joined "Test"
|
|
4050
|
+
// column on the optimistic rows (BaseEntity's joined view fields aren't
|
|
4051
|
+
// always populated through a TransactionGroup save).
|
|
4052
|
+
const testNameById = new Map(this.availableTests.map(t => [t.ID, t.Name]));
|
|
4053
|
+
try {
|
|
4054
|
+
const tg = await provider.CreateTransactionGroup();
|
|
4055
|
+
const newRows = [];
|
|
4056
|
+
for (let i = 0; i < idsToAdd.length; i++) {
|
|
4057
|
+
const row = await provider.GetEntityObject('MJ: Test Suite Tests', provider.CurrentUser);
|
|
4058
|
+
row.NewRecord();
|
|
4059
|
+
row.SuiteID = this.record.ID;
|
|
4060
|
+
row.TestID = idsToAdd[i];
|
|
4061
|
+
row.Sequence = startSequence + i + 1;
|
|
4062
|
+
row.Status = 'Active';
|
|
4063
|
+
row.TransactionGroup = tg;
|
|
4064
|
+
await row.Save();
|
|
4065
|
+
newRows.push(row);
|
|
4066
|
+
}
|
|
4067
|
+
const ok = await tg.Submit();
|
|
4068
|
+
if (ok) {
|
|
4069
|
+
// Optimistic UI update: append the saved rows immediately so the user
|
|
4070
|
+
// sees the new tests right away. If the joined "Test" name field
|
|
4071
|
+
// didn't come back from the save (TG quirk), hydrate it from the
|
|
4072
|
+
// picker snapshot.
|
|
4073
|
+
for (const row of newRows) {
|
|
4074
|
+
if (!row.Test) {
|
|
4075
|
+
const name = testNameById.get(row.TestID);
|
|
4076
|
+
if (name) {
|
|
4077
|
+
row.Set('Test', name);
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
this.suiteTests = [...this.suiteTests, ...newRows];
|
|
4082
|
+
this.cdr.markForCheck();
|
|
4083
|
+
SharedService.Instance.CreateSimpleNotification(idsToAdd.length === 1 ? 'Test added to suite' : `${idsToAdd.length} tests added to suite`, 'success', 2000);
|
|
4084
|
+
this.showAddTestsDialog = false;
|
|
4085
|
+
this.selectedTestIdsToAdd = new Set();
|
|
4086
|
+
this.addTestsSearch = '';
|
|
4087
|
+
}
|
|
4088
|
+
else {
|
|
4089
|
+
const failed = newRows.find(r => r.LatestResult && !r.LatestResult.Success);
|
|
4090
|
+
const detail = failed?.LatestResult?.CompleteMessage || 'Failed to add tests';
|
|
4091
|
+
SharedService.Instance.CreateSimpleNotification(detail, 'error', 4000);
|
|
4092
|
+
}
|
|
4093
|
+
}
|
|
4094
|
+
catch (err) {
|
|
4095
|
+
const msg = err instanceof Error ? err.message : 'Failed to add tests';
|
|
4096
|
+
SharedService.Instance.CreateSimpleNotification(msg, 'error', 4000);
|
|
4097
|
+
}
|
|
4098
|
+
finally {
|
|
4099
|
+
this.isAddingTests = false;
|
|
4100
|
+
this.cdr.markForCheck();
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
/** Show the inline remove-confirm for one suite-test row. */
|
|
4104
|
+
requestRemoveTest(suiteTest, event) {
|
|
4105
|
+
if (event)
|
|
4106
|
+
event.stopPropagation();
|
|
4107
|
+
this.confirmingRemoveSuiteTestId = suiteTest.ID;
|
|
4108
|
+
this.cdr.markForCheck();
|
|
4109
|
+
}
|
|
4110
|
+
cancelRemoveTest(event) {
|
|
4111
|
+
if (event)
|
|
4112
|
+
event.stopPropagation();
|
|
4113
|
+
this.confirmingRemoveSuiteTestId = null;
|
|
4114
|
+
this.cdr.markForCheck();
|
|
4115
|
+
}
|
|
4116
|
+
/** Delete the suite-test join row and refresh the list. */
|
|
4117
|
+
async confirmRemoveTest(suiteTest, event) {
|
|
4118
|
+
if (event)
|
|
4119
|
+
event.stopPropagation();
|
|
4120
|
+
if (this.isRemovingTest)
|
|
4121
|
+
return;
|
|
4122
|
+
this.isRemovingTest = true;
|
|
4123
|
+
this.cdr.markForCheck();
|
|
4124
|
+
try {
|
|
4125
|
+
const ok = await suiteTest.Delete();
|
|
4126
|
+
if (ok) {
|
|
4127
|
+
this.suiteTests = this.suiteTests.filter(t => !UUIDsEqual(t.ID, suiteTest.ID));
|
|
4128
|
+
SharedService.Instance.CreateSimpleNotification('Test removed from suite', 'success', 2000);
|
|
4129
|
+
}
|
|
4130
|
+
else {
|
|
4131
|
+
const detail = suiteTest.LatestResult?.CompleteMessage || 'Failed to remove test';
|
|
4132
|
+
SharedService.Instance.CreateSimpleNotification(detail, 'error', 4000);
|
|
4133
|
+
}
|
|
4134
|
+
}
|
|
4135
|
+
catch (err) {
|
|
4136
|
+
const msg = err instanceof Error ? err.message : 'Failed to remove test';
|
|
4137
|
+
SharedService.Instance.CreateSimpleNotification(msg, 'error', 4000);
|
|
4138
|
+
}
|
|
4139
|
+
finally {
|
|
4140
|
+
this.isRemovingTest = false;
|
|
4141
|
+
this.confirmingRemoveSuiteTestId = null;
|
|
4142
|
+
this.cdr.markForCheck();
|
|
4143
|
+
}
|
|
4144
|
+
}
|
|
4145
|
+
/** Handle CDK drag-drop reordering — persists new Sequence values. */
|
|
4146
|
+
async onTestDrop(event) {
|
|
4147
|
+
if (event.previousIndex === event.currentIndex)
|
|
4148
|
+
return;
|
|
4149
|
+
// Optimistic reorder
|
|
4150
|
+
const reordered = [...this.suiteTests];
|
|
4151
|
+
moveItemInArray(reordered, event.previousIndex, event.currentIndex);
|
|
4152
|
+
this.suiteTests = reordered;
|
|
4153
|
+
this.cdr.markForCheck();
|
|
4154
|
+
// Compute which rows actually changed sequence (1-based contiguous numbering)
|
|
4155
|
+
const dirty = [];
|
|
4156
|
+
reordered.forEach((row, idx) => {
|
|
4157
|
+
const newSeq = idx + 1;
|
|
4158
|
+
if (row.Sequence !== newSeq) {
|
|
4159
|
+
row.Sequence = newSeq;
|
|
4160
|
+
dirty.push(row);
|
|
4161
|
+
}
|
|
4162
|
+
});
|
|
4163
|
+
if (dirty.length === 0)
|
|
4164
|
+
return;
|
|
4165
|
+
this.isReorderingTests = true;
|
|
4166
|
+
this.cdr.markForCheck();
|
|
4167
|
+
const provider = this.ProviderToUse;
|
|
4168
|
+
try {
|
|
4169
|
+
const tg = await provider.CreateTransactionGroup();
|
|
4170
|
+
for (const row of dirty) {
|
|
4171
|
+
row.TransactionGroup = tg;
|
|
4172
|
+
await row.Save();
|
|
4173
|
+
}
|
|
4174
|
+
const ok = await tg.Submit();
|
|
4175
|
+
if (!ok) {
|
|
4176
|
+
const failed = dirty.find(r => r.LatestResult && !r.LatestResult.Success);
|
|
4177
|
+
const detail = failed?.LatestResult?.CompleteMessage || 'Failed to save new order';
|
|
4178
|
+
SharedService.Instance.CreateSimpleNotification(detail, 'error', 4000);
|
|
4179
|
+
this.testsLoaded = false;
|
|
4180
|
+
await this.loadTests();
|
|
4181
|
+
}
|
|
4182
|
+
}
|
|
4183
|
+
catch (err) {
|
|
4184
|
+
const msg = err instanceof Error ? err.message : 'Failed to save new order';
|
|
4185
|
+
SharedService.Instance.CreateSimpleNotification(msg, 'error', 4000);
|
|
4186
|
+
this.testsLoaded = false;
|
|
4187
|
+
await this.loadTests();
|
|
4188
|
+
}
|
|
4189
|
+
finally {
|
|
4190
|
+
this.isReorderingTests = false;
|
|
4191
|
+
this.cdr.markForCheck();
|
|
4192
|
+
}
|
|
4193
|
+
}
|
|
3379
4194
|
static { this.ɵfac = /*@__PURE__*/ (() => { let ɵMJTestSuiteFormComponentExtended_BaseFactory; return function MJTestSuiteFormComponentExtended_Factory(__ngFactoryType__) { return (ɵMJTestSuiteFormComponentExtended_BaseFactory || (ɵMJTestSuiteFormComponentExtended_BaseFactory = i0.ɵɵgetInheritedFactory(MJTestSuiteFormComponentExtended)))(__ngFactoryType__ || MJTestSuiteFormComponentExtended); }; })(); }
|
|
3380
4195
|
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJTestSuiteFormComponentExtended, selectors: [["mj-test-suite-form"]], viewQuery: function MJTestSuiteFormComponentExtended_Query(rf, ctx) { if (rf & 1) {
|
|
3381
4196
|
i0.ɵɵviewQuery(_c0, 5);
|
|
@@ -3383,98 +4198,120 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
3383
4198
|
let _t;
|
|
3384
4199
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.chartContainer = _t.first);
|
|
3385
4200
|
} }, hostBindings: function MJTestSuiteFormComponentExtended_HostBindings(rf, ctx) { if (rf & 1) {
|
|
3386
|
-
i0.ɵɵlistener("keydown", function MJTestSuiteFormComponentExtended_keydown_HostBindingHandler($event) { return ctx.handleKeyboardShortcut($event); }, i0.ɵɵresolveDocument);
|
|
3387
|
-
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 67, vars: 37, consts: [["chartContainer", ""], [1, "test-suite-form"], [1, "suite-header"], ["aria-label", "Breadcrumb", 1, "breadcrumb"], ["href", "javascript:void(0)", 3, "click"], [1, "fas", "fa-vial"], [1, "breadcrumb-text"], [1, "current"], [1, "fas", "fa-chevron-right", "separator"], [1, "fas", "fa-layer-group"], [1, "header-content"], [1, "header-left"], [1, "suite-icon"], [1, "suite-info"], [1, "suite-meta"], [1, "status-badge", 3, "ngClass"], [1, "fas", 3, "ngClass"], [1, "test-count"], [1, "header-actions"], ["mjButton", "", "title", "Export to CSV", 3, "click"], [1, "fas", "fa-file-excel"], ["mjButton", "", "variant", "primary", 3, "click"], [1, "fas", "fa-play"], ["mjButton", "", 3, "click", "disabled"], [1, "suite-description"], [1, "tabs-container"], ["role", "tablist", 1, "tabs"], ["role", "tab", 1, "tab", 3, "click"], [1, "fas", "fa-th-large"], [1, "fas", "fa-flask"], [1, "tab-badge"], [1, "fas", "fa-history"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-balance-scale"], [1, "tab-content"], [1, "overview-tab"], [1, "tests-tab"], [1, "runs-tab"], [1, "analytics-tab"], [1, "compare-tab"], [1, "shortcuts-toggle", 3, "click", "title"], [1, "fas", "fa-keyboard"], [1, "keyboard-shortcuts"], ["Mode", "slide", 3, "Title", "Resizable"], [1, "info-section"], [1, "fas", "fa-info-circle"], [1, "info-grid"], [1, "info-item"], [1, "info-label"], [1, "info-value"], [1, "status-badge-inline", 3, "ngClass"], [1, "config-section"], [1, "fas", "fa-cogs"], [1, "config-grid"], [1, "config-item"], ["type", "number", "placeholder", "Default: 300000 (5 min)", 1, "config-input", 3, "ngModelChange", "ngModel"], [1, "config-hint"], [1, "loading-state"], [1, "tests-list"], [1, "empty-state"], [1, "skeleton-list"], [1, "skeleton-card"], [1, "skeleton-sequence"], [1, "skeleton-icon"], [1, "skeleton-content"], [1, "skeleton-line", "wide"], [1, "skeleton-line", "narrow"], [1, "test-item"], [1, "test-item", 3, "click"], [1, "test-sequence"], [1, "test-icon"], [1, "test-content"], [1, "test-name"], [1, "test-status"], [1, "fas", "fa-chevron-right"], [1, "empty-icon"], [1, "runs-list"], [1, "run-item"], [1, "run-item", 3, "click"], [1, "run-icon"], [1, "fas"], [1, "run-content"], [1, "run-header"], [1, "run-id"], [1, "run-status"], [1, "run-meta"], [1, "fas", "fa-calendar"], [1, "run-eval-metrics"], [1, "eval-metric", "status", 3, "class"], ["title", "Human evaluation", 1, "eval-metric", "human"], ["title", "Auto score (pass rate)", 1, "eval-metric", "auto", 3, "high", "medium", "low"], [1, "run-tags"], [1, "fas", "fa-check-circle"], [1, "eval-metric", "status"], [1, "fas", "fa-user"], [1, "eval-pending"], [1, "fas", "fa-clock"], ["title", "Auto score (pass rate)", 1, "eval-metric", "auto"], [1, "fas", "fa-robot"], [1, "tag-chip"], [1, "fas", "fa-play-circle"], ["text", "Loading analytics data..."], [1, "analytics-subnav"], [1, "subnav-tabs"], [1, "subnav-tab", 3, "click"], [1, "fas", "fa-chart-bar"], [1, "fas", "fa-th"], [1, "fas", "fa-project-diagram"], [1, "analytics-filters"], [1, "filters-header", 3, "click"], [1, "filters-title"], [1, "fas", "fa-filter"], [1, "filter-summary"], [1, "filters-content"], [1, "filter-group"], [1, "filter-buttons"], [1, "filter-btn", 3, "click"], [1, "filter-hint"], [1, "filter-buttons", "tag-filters"], [1, "filter-btn", "tag-btn", "all-tags-btn", 3, "click"], [1, "filter-btn", "tag-btn", 3, "active"], [1, "filter-btn", "tag-btn", 3, "click"], [1, "fas", "fa-check"], [1, "analytics-kpis"], [1, "kpi-card"], [1, "kpi-icon"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-icon", "success"], [1, "kpi-trend", 3, "ngClass"], [1, "kpi-icon", "info"], [1, "kpi-icon", "warning"], [1, "fas", "fa-dollar-sign"], [1, "analytics-table-section"], [1, "fas", "fa-table"], [1, "analytics-table-wrapper"], [1, "analytics-table"], [1, "clickable-row"], [1, "empty-state", "small"], [1, "clickable-row", 3, "click"], [1, "status-chip", 3, "ngClass"], [1, "pass-rate-cell"], [1, "pass-rate-bar", 3, "ngClass"], [1, "tag-cell"], [1, "tag-chip-table"], [1, "tag-more"], [1, "matrix-section"], ["text", "Loading test matrix..."], [1, "matrix-header"], [1, "matrix-header-right"], [1, "matrix-filter-input"], [1, "fas", "fa-search"], ["type", "text", "placeholder", "Filter tests...", 1, "filter-input", 3, "input", "value"], ["title", "Clear filter", 1, "clear-filter-btn"], [1, "matrix-run-count"], ["mjButton", "", "title", "Export matrix to CSV", 3, "click", "disabled"], [1, "fas", "fa-download"], [1, "matrix-scroll-container"], [1, "test-matrix"], ["title", "Sort by sequence", 1, "seq-header", 3, "click"], ["title", "Sort by name", 1, "test-name-header", 3, "click"], [1, "run-header", 3, "title"], [1, "spacer-header"], [3, "row-selected"], [1, "totals-row"], [1, "seq-cell", "totals-label"], [1, "test-name-cell", "totals-label"], [1, "result-cell", "totals-cell"], [1, "spacer-cell"], ["title", "Clear filter", 1, "clear-filter-btn", 3, "click"], [1, "fas", "fa-times"], [1, "run-header", 3, "click", "title"], [1, "run-header-content"], [1, "run-tags-header"], [1, "run-date"], [1, "run-pass-rate", 3, "ngClass"], [1, "tag-chip-header"], [1, "tag-more-header"], [3, "click"], [1, "seq-cell"], [1, "test-name-cell"], [1, "test-name", 3, "title"], [1, "result-cell", 3, "ngClass", "clickable", "cell-not-run", "title"], [1, "result-cell", 3, "click", "ngClass", "title"], [1, "cell-eval-stack"], [1, "cell-not-run-indicator"], [1, "cell-status", 3, "ngClass", "cell-skipped-status", "title"], ["title", "Human Review: No rating submitted yet", 1, "cell-human", "no-feedback"], [1, "cell-human", "has-feedback", 3, "rating-low", "rating-medium", "rating-good", "rating-excellent", "title"], [1, "cell-auto", "has-score", 3, "score-low", "score-medium", "score-good", "score-excellent", "title"], ["title", "Auto Score: No automated score available", 1, "cell-auto", "no-score"], [1, "cell-status", 3, "ngClass", "title"], [1, "fas", "fa-user-slash"], [1, "cell-human", "has-feedback", 3, "title"], [1, "rating-value"], [1, "cell-auto", "has-score", 3, "title"], [1, "score-value"], [1, "fas", "fa-minus"], [1, "cell-eval-stack", "totals-stack"], [1, "totals-status"], [1, "totals-human"], [1, "totals-auto"], [1, "pass-count"], [1, "avg-label"], [1, "count-label"], [1, "chart-section"], ["text", "Loading chart data..."], [1, "chart-header"], [1, "chart-legend"], [1, "legend-item", "chart-passed"], [1, "legend-item", "chart-failed"], [1, "legend-item", "chart-error"], [1, "fas", "fa-exclamation"], [1, "legend-item", "chart-skipped"], [1, "fas", "fa-forward"], [1, "chart-container"], [1, "d3-chart"], [1, "chart-info"], [1, "compare-selection"], [1, "compare-run-selector"], [1, "run-selector-list"], [1, "selected-run-preview"], [1, "compare-vs"], [1, "fas", "fa-exchange-alt"], [1, "compare-results"], [1, "compare-empty"], [1, "run-selector-item", 3, "selected"], [1, "run-selector-item", 3, "click"], [1, "selector-status"], [1, "selector-content"], [1, "selector-date"], [1, "selector-rate"], [1, "selector-tags"], [1, "tag-mini"], [1, "preview-header"], [1, "preview-label"], [1, "clear-btn", 3, "click"], [1, "preview-details"], [1, "preview-rate"], [1, "run-selector-item", 3, "selected", "disabled"], [1, "compare-summary"], [1, "compare-summary-card"], [1, "summary-label"], [1, "summary-value", 3, "ngClass"], [1, "compare-summary-card", "improved"], [1, "summary-value"], [1, "compare-summary-card", "regressed"], [1, "compare-table-section"], [1, "fas", "fa-list"], [1, "compare-table-wrapper"], [1, "compare-table"], [3, "ngClass"], [1, "status-chip", "status-missing"], [1, "muted"], [1, "change-indicator", "improved"], [1, "change-indicator", "regressed"], [1, "change-indicator", "unchanged"], [1, "fas", "fa-arrow-up"], [1, "fas", "fa-arrow-down"], ["text", "Loading comparison data..."], [1, "compare-empty-icon"], [1, "shortcuts-header"], ["title", "Hide shortcuts", 1, "shortcuts-close", 3, "click"], [1, "shortcut-list"], [1, "shortcut-item"], [1, "shortcut-keys"], ["Mode", "slide", 3, "Closed", "Title", "Resizable"], [3, "PanelClose", "PanelMode", "selectedTestId", "selectedSuiteId", "runMode"]], template: function MJTestSuiteFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
|
|
3388
|
-
i0.ɵɵelementStart(0, "div",
|
|
4201
|
+
i0.ɵɵlistener("keydown", function MJTestSuiteFormComponentExtended_keydown_HostBindingHandler($event) { return ctx.handleKeyboardShortcut($event); }, i0.ɵɵresolveDocument)("beforeunload", function MJTestSuiteFormComponentExtended_beforeunload_HostBindingHandler($event) { return ctx.handleBeforeUnload($event); }, i0.ɵɵresolveWindow);
|
|
4202
|
+
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 87, vars: 51, consts: [["tagInput", ""], ["chartContainer", ""], ["pickerSearch", ""], [1, "test-suite-form"], [1, "suite-header"], ["aria-label", "Breadcrumb", 1, "breadcrumb"], ["href", "javascript:void(0)", 3, "click"], [1, "fas", "fa-vial"], [1, "breadcrumb-text"], [1, "current"], [1, "fas", "fa-chevron-right", "separator"], [1, "fas", "fa-layer-group"], [1, "header-content"], [1, "header-left"], [1, "suite-icon"], [1, "suite-info"], ["title", "You have unsaved changes", "aria-label", "Unsaved changes", 1, "dirty-indicator"], [1, "suite-meta"], [1, "status-badge", 3, "ngClass"], [1, "fas", 3, "ngClass"], [1, "test-count"], ["title", "You have unsaved changes", 1, "unsaved-pill"], [1, "header-actions"], ["mjButton", "", "title", "Export to CSV", 3, "click"], [1, "fas", "fa-file-excel"], ["mjButton", "", "variant", "primary", 3, "click"], [1, "fas", "fa-play"], ["mjButton", "", 3, "click", "disabled"], [1, "suite-description"], [1, "tabs-container"], ["role", "tablist", 1, "tabs"], ["role", "tab", 1, "tab", 3, "click"], [1, "fas", "fa-th-large"], [1, "fas", "fa-flask"], [1, "tab-badge"], [1, "fas", "fa-history"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-balance-scale"], [1, "tab-content"], [1, "overview-tab"], [1, "tests-tab"], [1, "runs-tab"], [1, "analytics-tab"], [1, "compare-tab"], [1, "shortcuts-toggle", 3, "click", "title"], [1, "fas", "fa-keyboard"], [1, "keyboard-shortcuts"], ["Mode", "slide", 3, "Title", "Resizable"], ["role", "region", "aria-label", "Unsaved changes", 1, "save-bar"], [1, "save-bar-message"], ["aria-hidden", "true", 1, "save-bar-dot"], [1, "save-bar-text"], [1, "save-bar-fields"], [1, "save-bar-actions"], ["type", "button", "title", "Save changes (\u2318S)", 1, "save-bar-btn", "save-bar-btn--primary", 3, "click", "disabled"], ["type", "button", "title", "Discard changes", 1, "save-bar-btn", "save-bar-btn--ghost", 3, "click", "disabled"], [1, "fas", "fa-undo"], [1, "fas", "fa-circle"], [1, "edit-section"], [1, "edit-section-header"], [1, "fas", "fa-pen-to-square"], [1, "edit-section-sub"], [1, "edit-grid"], [1, "edit-field", "edit-field--full"], ["for", "suite-name"], [1, "required"], ["id", "suite-name", "type", "text", "placeholder", "e.g., Core Agent Test Suite", 1, "config-input", 3, "ngModelChange", "ngModel"], ["for", "suite-description"], ["id", "suite-description", "rows", "3", "placeholder", "What does this suite cover?", 1, "config-input", "config-textarea", 3, "ngModelChange", "ngModel"], [1, "edit-field"], ["for", "suite-status"], [1, "select-wrapper"], ["id", "suite-status", 1, "config-input", 3, "ngModelChange", "ngModel"], [3, "ngValue"], ["for", "suite-parent"], ["id", "suite-parent", 1, "config-input", 3, "ngModelChange", "ngModel"], ["for", "suite-tags"], [1, "tag-editor", 3, "click"], [1, "tag-chip-editable"], ["id", "suite-tags", "type", "text", 1, "tag-input-inline", 3, "ngModelChange", "keydown", "blur", "placeholder", "ngModel"], [1, "config-hint"], [1, "fas", "fa-cogs"], ["for", "suite-timeout"], ["id", "suite-timeout", "type", "number", "placeholder", "Default: 300000 (5 min)", 1, "config-input", 3, "ngModelChange", "ngModel"], [1, "meta-section"], [1, "meta-grid"], [1, "meta-item"], [1, "meta-label"], [1, "meta-value"], [1, "meta-value", "meta-mono"], ["type", "button", 1, "tag-remove", 3, "click"], [1, "fas", "fa-times"], [1, "tests-actionbar"], [1, "tests-actionbar-text"], [1, "tests-actionbar-count"], [1, "tests-actionbar-hint"], [1, "tests-actionbar-actions"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], [1, "fas", "fa-plus"], [1, "loading-state"], ["cdkDropList", "", 1, "tests-list"], [1, "empty-state"], [1, "skeleton-list"], [1, "skeleton-card"], [1, "skeleton-sequence"], [1, "skeleton-icon"], [1, "skeleton-content"], [1, "skeleton-line", "wide"], [1, "skeleton-line", "narrow"], ["cdkDropList", "", 1, "tests-list", 3, "cdkDropListDropped"], ["cdkDrag", "", 1, "test-item", 3, "cdkDragDisabled"], ["cdkDragHandle", "", "title", "Drag to reorder", "aria-label", "Drag to reorder", 1, "test-drag-handle"], [1, "fas", "fa-grip-vertical"], [1, "test-sequence"], [1, "test-icon"], [1, "test-content", 3, "click"], [1, "test-name"], [1, "test-status"], [1, "test-remove-confirm"], [1, "fas", "fa-info-circle"], [1, "test-remove-confirm", 3, "click"], [1, "test-remove-confirm-text"], ["type", "button", 1, "test-remove-confirm-btn", "test-remove-confirm-btn--danger", 3, "click", "disabled"], [1, "fas", "fa-spinner", "fa-spin"], ["type", "button", 1, "test-remove-confirm-btn", "test-remove-confirm-btn--ghost", 3, "click", "disabled"], ["type", "button", "title", "Remove from suite", "aria-label", "Remove from suite", 1, "test-remove-btn", 3, "click"], [1, "fas", "fa-chevron-right", "test-chevron", 3, "click"], [1, "empty-icon"], [1, "runs-list"], [1, "run-item"], [1, "run-item", 3, "click"], [1, "run-icon"], [1, "fas"], [1, "run-content"], [1, "run-header"], [1, "run-id"], [1, "run-status"], [1, "run-meta"], [1, "fas", "fa-calendar"], [1, "run-eval-metrics"], [1, "eval-metric", "status", 3, "class"], ["title", "Human evaluation", 1, "eval-metric", "human"], ["title", "Auto score (pass rate)", 1, "eval-metric", "auto", 3, "high", "medium", "low"], [1, "run-tags"], [1, "fas", "fa-chevron-right"], [1, "fas", "fa-check-circle"], [1, "eval-metric", "status"], [1, "fas", "fa-user"], [1, "eval-pending"], [1, "fas", "fa-clock"], ["title", "Auto score (pass rate)", 1, "eval-metric", "auto"], [1, "fas", "fa-robot"], [1, "tag-chip"], [1, "fas", "fa-play-circle"], ["text", "Loading analytics data..."], [1, "analytics-subnav"], [1, "subnav-tabs"], [1, "subnav-tab", 3, "click"], [1, "fas", "fa-chart-bar"], [1, "fas", "fa-th"], [1, "fas", "fa-project-diagram"], [1, "analytics-filters"], [1, "filters-header", 3, "click"], [1, "filters-title"], [1, "fas", "fa-filter"], [1, "filter-summary"], [1, "filters-content"], [1, "filter-group"], [1, "filter-buttons"], [1, "filter-btn", 3, "click"], [1, "filter-hint"], [1, "filter-buttons", "tag-filters"], [1, "filter-btn", "tag-btn", "all-tags-btn", 3, "click"], [1, "filter-btn", "tag-btn", 3, "active"], [1, "filter-btn", "tag-btn", 3, "click"], [1, "fas", "fa-check"], [1, "analytics-kpis"], [1, "kpi-card"], [1, "kpi-icon"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-icon", "success"], [1, "kpi-trend", 3, "ngClass"], [1, "kpi-icon", "info"], [1, "kpi-icon", "warning"], [1, "fas", "fa-dollar-sign"], [1, "analytics-table-section"], [1, "fas", "fa-table"], [1, "analytics-table-wrapper"], [1, "analytics-table"], [1, "clickable-row"], [1, "empty-state", "small"], [1, "clickable-row", 3, "click"], [1, "status-chip", 3, "ngClass"], [1, "pass-rate-cell"], [1, "pass-rate-bar", 3, "ngClass"], [1, "tag-cell"], [1, "tag-chip-table"], [1, "tag-more"], [1, "matrix-section"], ["text", "Loading test matrix..."], [1, "matrix-header"], [1, "matrix-header-right"], [1, "matrix-filter-input"], [1, "fas", "fa-search"], ["type", "text", "placeholder", "Filter tests...", 1, "filter-input", 3, "input", "value"], ["title", "Clear filter", 1, "clear-filter-btn"], [1, "matrix-run-count"], ["mjButton", "", "title", "Export matrix to CSV", 3, "click", "disabled"], [1, "fas", "fa-download"], [1, "matrix-scroll-container"], [1, "test-matrix"], ["title", "Sort by sequence", 1, "seq-header", 3, "click"], ["title", "Sort by name", 1, "test-name-header", 3, "click"], [1, "run-header", 3, "title"], [1, "spacer-header"], [3, "row-selected"], [1, "totals-row"], [1, "seq-cell", "totals-label"], [1, "test-name-cell", "totals-label"], [1, "result-cell", "totals-cell"], [1, "spacer-cell"], ["title", "Clear filter", 1, "clear-filter-btn", 3, "click"], [1, "run-header", 3, "click", "title"], [1, "run-header-content"], [1, "run-tags-header"], [1, "run-date"], [1, "run-pass-rate", 3, "ngClass"], [1, "tag-chip-header"], [1, "tag-more-header"], [3, "click"], [1, "seq-cell"], [1, "test-name-cell"], [1, "test-name", 3, "title"], [1, "result-cell", 3, "ngClass", "clickable", "cell-not-run", "title"], [1, "result-cell", 3, "click", "ngClass", "title"], [1, "cell-eval-stack"], [1, "cell-not-run-indicator"], [1, "cell-status", 3, "ngClass", "cell-skipped-status", "title"], ["title", "Human Review: No rating submitted yet", 1, "cell-human", "no-feedback"], [1, "cell-human", "has-feedback", 3, "rating-low", "rating-medium", "rating-good", "rating-excellent", "title"], [1, "cell-auto", "has-score", 3, "score-low", "score-medium", "score-good", "score-excellent", "title"], ["title", "Auto Score: No automated score available", 1, "cell-auto", "no-score"], [1, "cell-status", 3, "ngClass", "title"], [1, "fas", "fa-user-slash"], [1, "cell-human", "has-feedback", 3, "title"], [1, "rating-value"], [1, "cell-auto", "has-score", 3, "title"], [1, "score-value"], [1, "fas", "fa-minus"], [1, "cell-eval-stack", "totals-stack"], [1, "totals-status"], [1, "totals-human"], [1, "totals-auto"], [1, "pass-count"], [1, "avg-label"], [1, "count-label"], [1, "chart-section"], ["text", "Loading chart data..."], [1, "chart-header"], [1, "chart-legend"], [1, "legend-item", "chart-passed"], [1, "legend-item", "chart-failed"], [1, "legend-item", "chart-error"], [1, "fas", "fa-exclamation"], [1, "legend-item", "chart-skipped"], [1, "fas", "fa-forward"], [1, "chart-container"], [1, "d3-chart"], [1, "chart-info"], [1, "compare-selection"], [1, "compare-run-selector"], [1, "run-selector-list"], [1, "selected-run-preview"], [1, "compare-vs"], [1, "fas", "fa-exchange-alt"], [1, "compare-results"], [1, "compare-empty"], [1, "run-selector-item", 3, "selected"], [1, "run-selector-item", 3, "click"], [1, "selector-status"], [1, "selector-content"], [1, "selector-date"], [1, "selector-rate"], [1, "selector-tags"], [1, "tag-mini"], [1, "preview-header"], [1, "preview-label"], [1, "clear-btn", 3, "click"], [1, "preview-details"], [1, "preview-rate"], [1, "run-selector-item", 3, "selected", "disabled"], [1, "compare-summary"], [1, "compare-summary-card"], [1, "summary-label"], [1, "summary-value", 3, "ngClass"], [1, "compare-summary-card", "improved"], [1, "summary-value"], [1, "compare-summary-card", "regressed"], [1, "compare-table-section"], [1, "fas", "fa-list"], [1, "compare-table-wrapper"], [1, "compare-table"], [3, "ngClass"], [1, "status-chip", "status-missing"], [1, "muted"], [1, "change-indicator", "improved"], [1, "change-indicator", "regressed"], [1, "change-indicator", "unchanged"], [1, "fas", "fa-arrow-up"], [1, "fas", "fa-arrow-down"], ["text", "Loading comparison data..."], [1, "compare-empty-icon"], [1, "shortcuts-header"], ["title", "Hide shortcuts", 1, "shortcuts-close", 3, "click"], [1, "shortcut-list"], [1, "shortcut-item"], [1, "shortcut-keys"], ["Mode", "slide", 3, "Closed", "Title", "Resizable"], [3, "PanelClose", "PanelMode", "selectedTestId", "selectedSuiteId", "runMode"], [1, "picker-backdrop", 3, "click"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "add-tests-dialog-title", 1, "picker-dialog", 3, "click"], [1, "picker-header"], ["id", "add-tests-dialog-title", 1, "picker-title"], [1, "fas", "fa-plus-circle"], ["type", "button", "aria-label", "Close", 1, "picker-close", 3, "click", "disabled"], [1, "picker-search"], [1, "fas", "fa-search", "picker-search-icon"], ["type", "text", "placeholder", "Search tests by name, description, or type...", "autofocus", "", 1, "picker-search-input", 3, "ngModelChange", "ngModel"], ["type", "button", "aria-label", "Clear search", 1, "picker-search-clear"], [1, "picker-toolbar"], [1, "picker-toolbar-status"], [1, "picker-toolbar-actions"], ["type", "button", 1, "picker-link-btn", 3, "click", "disabled"], [1, "picker-body"], [1, "picker-loading"], [1, "picker-empty"], [1, "picker-list"], [1, "picker-footer"], ["type", "button", 1, "picker-btn", "picker-btn--primary", 3, "click", "disabled"], ["type", "button", 1, "picker-btn", "picker-btn--ghost", 3, "click", "disabled"], ["type", "button", "aria-label", "Clear search", 1, "picker-search-clear", 3, "click"], ["text", "Loading tests..."], ["role", "checkbox", "tabindex", "0", 1, "picker-row", 3, "picker-row--selected"], ["role", "checkbox", "tabindex", "0", 1, "picker-row", 3, "click"], [1, "picker-check"], [1, "picker-row-main"], [1, "picker-row-name"], [1, "picker-row-desc"], [1, "picker-row-meta"], [1, "picker-row-pill"], [1, "picker-row-pill", "picker-row-pill--status"], [1, "save-bar-kbd"]], template: function MJTestSuiteFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
|
|
4203
|
+
i0.ɵɵelementStart(0, "div", 3)(1, "div", 4)(2, "nav", 5)(3, "ol")(4, "li")(5, "a", 6);
|
|
3389
4204
|
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_a_click_5_listener() { return ctx.navigateToTestingDashboard(); });
|
|
3390
|
-
i0.ɵɵelement(6, "i",
|
|
3391
|
-
i0.ɵɵelementStart(7, "span",
|
|
4205
|
+
i0.ɵɵelement(6, "i", 7);
|
|
4206
|
+
i0.ɵɵelementStart(7, "span", 8);
|
|
3392
4207
|
i0.ɵɵtext(8, "Testing");
|
|
3393
4208
|
i0.ɵɵelementEnd()()();
|
|
3394
|
-
i0.ɵɵelementStart(9, "li",
|
|
3395
|
-
i0.ɵɵelement(10, "i",
|
|
4209
|
+
i0.ɵɵelementStart(9, "li", 9);
|
|
4210
|
+
i0.ɵɵelement(10, "i", 10)(11, "i", 11);
|
|
3396
4211
|
i0.ɵɵelementStart(12, "span");
|
|
3397
4212
|
i0.ɵɵtext(13);
|
|
3398
4213
|
i0.ɵɵelementEnd()()()();
|
|
3399
|
-
i0.ɵɵelementStart(14, "div",
|
|
3400
|
-
i0.ɵɵelement(17, "i",
|
|
4214
|
+
i0.ɵɵelementStart(14, "div", 12)(15, "div", 13)(16, "div", 14);
|
|
4215
|
+
i0.ɵɵelement(17, "i", 11);
|
|
3401
4216
|
i0.ɵɵelementEnd();
|
|
3402
|
-
i0.ɵɵelementStart(18, "div",
|
|
4217
|
+
i0.ɵɵelementStart(18, "div", 15)(19, "h1");
|
|
3403
4218
|
i0.ɵɵtext(20);
|
|
4219
|
+
i0.ɵɵconditionalCreate(21, MJTestSuiteFormComponentExtended_Conditional_21_Template, 2, 0, "span", 16);
|
|
3404
4220
|
i0.ɵɵelementEnd();
|
|
3405
|
-
i0.ɵɵelementStart(
|
|
3406
|
-
i0.ɵɵelement(
|
|
3407
|
-
i0.ɵɵtext(
|
|
4221
|
+
i0.ɵɵelementStart(22, "div", 17)(23, "span", 18);
|
|
4222
|
+
i0.ɵɵelement(24, "i", 19);
|
|
4223
|
+
i0.ɵɵtext(25);
|
|
3408
4224
|
i0.ɵɵelementEnd();
|
|
3409
|
-
i0.ɵɵconditionalCreate(
|
|
4225
|
+
i0.ɵɵconditionalCreate(26, MJTestSuiteFormComponentExtended_Conditional_26_Template, 3, 1, "span", 20);
|
|
4226
|
+
i0.ɵɵconditionalCreate(27, MJTestSuiteFormComponentExtended_Conditional_27_Template, 3, 0, "span", 21);
|
|
3410
4227
|
i0.ɵɵelementEnd()()();
|
|
3411
|
-
i0.ɵɵelementStart(
|
|
3412
|
-
i0.ɵɵelement(
|
|
3413
|
-
i0.ɵɵelementStart(
|
|
3414
|
-
i0.ɵɵlistener("click", function
|
|
3415
|
-
i0.ɵɵelement(
|
|
3416
|
-
i0.ɵɵtext(
|
|
4228
|
+
i0.ɵɵelementStart(28, "div", 22);
|
|
4229
|
+
i0.ɵɵelement(29, "app-evaluation-mode-toggle");
|
|
4230
|
+
i0.ɵɵelementStart(30, "button", 23);
|
|
4231
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_30_listener() { return ctx.exportToExcel(); });
|
|
4232
|
+
i0.ɵɵelement(31, "i", 24);
|
|
4233
|
+
i0.ɵɵtext(32, " Export ");
|
|
3417
4234
|
i0.ɵɵelementEnd();
|
|
3418
|
-
i0.ɵɵelementStart(
|
|
3419
|
-
i0.ɵɵlistener("click", function
|
|
3420
|
-
i0.ɵɵelement(
|
|
3421
|
-
i0.ɵɵtext(
|
|
4235
|
+
i0.ɵɵelementStart(33, "button", 25);
|
|
4236
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_33_listener() { return ctx.runSuite(); });
|
|
4237
|
+
i0.ɵɵelement(34, "i", 26);
|
|
4238
|
+
i0.ɵɵtext(35, " Run Suite ");
|
|
3422
4239
|
i0.ɵɵelementEnd();
|
|
3423
|
-
i0.ɵɵelementStart(
|
|
3424
|
-
i0.ɵɵlistener("click", function
|
|
3425
|
-
i0.ɵɵelement(
|
|
3426
|
-
i0.ɵɵtext(
|
|
4240
|
+
i0.ɵɵelementStart(36, "button", 27);
|
|
4241
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_36_listener() { return ctx.refresh(); });
|
|
4242
|
+
i0.ɵɵelement(37, "i", 19);
|
|
4243
|
+
i0.ɵɵtext(38);
|
|
3427
4244
|
i0.ɵɵelementEnd()()();
|
|
3428
|
-
i0.ɵɵconditionalCreate(
|
|
4245
|
+
i0.ɵɵconditionalCreate(39, MJTestSuiteFormComponentExtended_Conditional_39_Template, 3, 1, "div", 28);
|
|
3429
4246
|
i0.ɵɵelementEnd();
|
|
3430
|
-
i0.ɵɵelementStart(
|
|
3431
|
-
i0.ɵɵlistener("click", function
|
|
3432
|
-
i0.ɵɵelement(
|
|
3433
|
-
i0.ɵɵtext(
|
|
4247
|
+
i0.ɵɵelementStart(40, "div", 29)(41, "div", 30)(42, "button", 31);
|
|
4248
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_42_listener() { return ctx.changeTab("overview"); });
|
|
4249
|
+
i0.ɵɵelement(43, "i", 32);
|
|
4250
|
+
i0.ɵɵtext(44, " Overview ");
|
|
3434
4251
|
i0.ɵɵelementEnd();
|
|
3435
|
-
i0.ɵɵelementStart(
|
|
3436
|
-
i0.ɵɵlistener("click", function
|
|
3437
|
-
i0.ɵɵelement(
|
|
3438
|
-
i0.ɵɵtext(
|
|
3439
|
-
i0.ɵɵconditionalCreate(
|
|
4252
|
+
i0.ɵɵelementStart(45, "button", 31);
|
|
4253
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_45_listener() { return ctx.changeTab("tests"); });
|
|
4254
|
+
i0.ɵɵelement(46, "i", 33);
|
|
4255
|
+
i0.ɵɵtext(47, " Tests ");
|
|
4256
|
+
i0.ɵɵconditionalCreate(48, MJTestSuiteFormComponentExtended_Conditional_48_Template, 2, 1, "span", 34);
|
|
3440
4257
|
i0.ɵɵelementEnd();
|
|
3441
|
-
i0.ɵɵelementStart(
|
|
3442
|
-
i0.ɵɵlistener("click", function
|
|
3443
|
-
i0.ɵɵelement(
|
|
3444
|
-
i0.ɵɵtext(
|
|
3445
|
-
i0.ɵɵconditionalCreate(
|
|
4258
|
+
i0.ɵɵelementStart(49, "button", 31);
|
|
4259
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_49_listener() { return ctx.changeTab("runs"); });
|
|
4260
|
+
i0.ɵɵelement(50, "i", 35);
|
|
4261
|
+
i0.ɵɵtext(51, " Runs ");
|
|
4262
|
+
i0.ɵɵconditionalCreate(52, MJTestSuiteFormComponentExtended_Conditional_52_Template, 2, 1, "span", 34);
|
|
3446
4263
|
i0.ɵɵelementEnd();
|
|
3447
|
-
i0.ɵɵelementStart(
|
|
3448
|
-
i0.ɵɵlistener("click", function
|
|
3449
|
-
i0.ɵɵelement(
|
|
3450
|
-
i0.ɵɵtext(
|
|
4264
|
+
i0.ɵɵelementStart(53, "button", 31);
|
|
4265
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_53_listener() { return ctx.changeTab("analytics"); });
|
|
4266
|
+
i0.ɵɵelement(54, "i", 36);
|
|
4267
|
+
i0.ɵɵtext(55, " Analytics ");
|
|
3451
4268
|
i0.ɵɵelementEnd();
|
|
3452
|
-
i0.ɵɵelementStart(
|
|
3453
|
-
i0.ɵɵlistener("click", function
|
|
3454
|
-
i0.ɵɵelement(
|
|
3455
|
-
i0.ɵɵtext(
|
|
4269
|
+
i0.ɵɵelementStart(56, "button", 31);
|
|
4270
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_56_listener() { return ctx.changeTab("compare"); });
|
|
4271
|
+
i0.ɵɵelement(57, "i", 37);
|
|
4272
|
+
i0.ɵɵtext(58, " Compare ");
|
|
3456
4273
|
i0.ɵɵelementEnd()()();
|
|
3457
|
-
i0.ɵɵelementStart(
|
|
3458
|
-
i0.ɵɵconditionalCreate(
|
|
3459
|
-
i0.ɵɵconditionalCreate(
|
|
3460
|
-
i0.ɵɵconditionalCreate(
|
|
3461
|
-
i0.ɵɵconditionalCreate(
|
|
3462
|
-
i0.ɵɵconditionalCreate(
|
|
4274
|
+
i0.ɵɵelementStart(59, "div", 38);
|
|
4275
|
+
i0.ɵɵconditionalCreate(60, MJTestSuiteFormComponentExtended_Conditional_60_Template, 75, 18, "div", 39);
|
|
4276
|
+
i0.ɵɵconditionalCreate(61, MJTestSuiteFormComponentExtended_Conditional_61_Template, 15, 5, "div", 40);
|
|
4277
|
+
i0.ɵɵconditionalCreate(62, MJTestSuiteFormComponentExtended_Conditional_62_Template, 4, 3, "div", 41);
|
|
4278
|
+
i0.ɵɵconditionalCreate(63, MJTestSuiteFormComponentExtended_Conditional_63_Template, 4, 3, "div", 42);
|
|
4279
|
+
i0.ɵɵconditionalCreate(64, MJTestSuiteFormComponentExtended_Conditional_64_Template, 18, 8, "div", 43);
|
|
4280
|
+
i0.ɵɵelementEnd();
|
|
4281
|
+
i0.ɵɵelementStart(65, "button", 44);
|
|
4282
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_65_listener() { return ctx.toggleShortcuts(); });
|
|
4283
|
+
i0.ɵɵelement(66, "i", 45);
|
|
3463
4284
|
i0.ɵɵelementEnd();
|
|
3464
|
-
i0.ɵɵ
|
|
3465
|
-
i0.ɵɵ
|
|
3466
|
-
i0.ɵɵ
|
|
4285
|
+
i0.ɵɵconditionalCreate(67, MJTestSuiteFormComponentExtended_Conditional_67_Template, 40, 0, "div", 46);
|
|
4286
|
+
i0.ɵɵconditionalCreate(68, MJTestSuiteFormComponentExtended_Conditional_68_Template, 2, 6, "mj-slide-panel", 47);
|
|
4287
|
+
i0.ɵɵconditionalCreate(69, MJTestSuiteFormComponentExtended_Conditional_69_Template, 32, 10);
|
|
4288
|
+
i0.ɵɵelementStart(70, "div", 48)(71, "div", 49)(72, "span", 50);
|
|
4289
|
+
i0.ɵɵtext(73, "\u25CF");
|
|
3467
4290
|
i0.ɵɵelementEnd();
|
|
3468
|
-
i0.ɵɵ
|
|
3469
|
-
i0.ɵɵ
|
|
4291
|
+
i0.ɵɵelementStart(74, "span", 51)(75, "strong");
|
|
4292
|
+
i0.ɵɵtext(76, "Unsaved changes");
|
|
3470
4293
|
i0.ɵɵelementEnd();
|
|
4294
|
+
i0.ɵɵelementStart(77, "span", 52);
|
|
4295
|
+
i0.ɵɵconditionalCreate(78, MJTestSuiteFormComponentExtended_Conditional_78_Template, 1, 1)(79, MJTestSuiteFormComponentExtended_Conditional_79_Template, 1, 1);
|
|
4296
|
+
i0.ɵɵelementEnd()()();
|
|
4297
|
+
i0.ɵɵelementStart(80, "div", 53)(81, "button", 54);
|
|
4298
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_81_listener() { return ctx.saveChanges(); });
|
|
4299
|
+
i0.ɵɵconditionalCreate(82, MJTestSuiteFormComponentExtended_Conditional_82_Template, 2, 0)(83, MJTestSuiteFormComponentExtended_Conditional_83_Template, 7, 0);
|
|
4300
|
+
i0.ɵɵelementEnd();
|
|
4301
|
+
i0.ɵɵelementStart(84, "button", 55);
|
|
4302
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_84_listener() { return ctx.discardChanges(); });
|
|
4303
|
+
i0.ɵɵelement(85, "i", 56);
|
|
4304
|
+
i0.ɵɵtext(86, " Discard ");
|
|
4305
|
+
i0.ɵɵelementEnd()()()();
|
|
3471
4306
|
} if (rf & 2) {
|
|
3472
4307
|
i0.ɵɵadvance(13);
|
|
3473
4308
|
i0.ɵɵtextInterpolate(ctx.record.Name);
|
|
3474
4309
|
i0.ɵɵadvance(3);
|
|
3475
4310
|
i0.ɵɵstyleProp("background-color", ctx.getStatusColor());
|
|
3476
4311
|
i0.ɵɵadvance(4);
|
|
3477
|
-
i0.ɵɵ
|
|
4312
|
+
i0.ɵɵtextInterpolate1(" ", ctx.record.Name, " ");
|
|
4313
|
+
i0.ɵɵadvance();
|
|
4314
|
+
i0.ɵɵconditional(ctx.isDirty ? 21 : -1);
|
|
3478
4315
|
i0.ɵɵadvance(2);
|
|
3479
4316
|
i0.ɵɵproperty("ngClass", ctx.getStatusClass());
|
|
3480
4317
|
i0.ɵɵadvance();
|
|
@@ -3482,7 +4319,9 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
3482
4319
|
i0.ɵɵadvance();
|
|
3483
4320
|
i0.ɵɵtextInterpolate1(" ", ctx.record.Status, " ");
|
|
3484
4321
|
i0.ɵɵadvance();
|
|
3485
|
-
i0.ɵɵconditional(ctx.testsLoaded ?
|
|
4322
|
+
i0.ɵɵconditional(ctx.testsLoaded ? 26 : -1);
|
|
4323
|
+
i0.ɵɵadvance();
|
|
4324
|
+
i0.ɵɵconditional(ctx.isDirty ? 27 : -1);
|
|
3486
4325
|
i0.ɵɵadvance(9);
|
|
3487
4326
|
i0.ɵɵproperty("disabled", ctx.isRefreshing);
|
|
3488
4327
|
i0.ɵɵadvance();
|
|
@@ -3490,7 +4329,7 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
3490
4329
|
i0.ɵɵadvance();
|
|
3491
4330
|
i0.ɵɵtextInterpolate1(" ", ctx.isRefreshing ? "Refreshing..." : "Refresh", " ");
|
|
3492
4331
|
i0.ɵɵadvance();
|
|
3493
|
-
i0.ɵɵconditional(ctx.record.Description ?
|
|
4332
|
+
i0.ɵɵconditional(ctx.record.Description ? 39 : -1);
|
|
3494
4333
|
i0.ɵɵadvance(3);
|
|
3495
4334
|
i0.ɵɵclassProp("active", ctx.activeTab === "overview");
|
|
3496
4335
|
i0.ɵɵattribute("aria-selected", ctx.activeTab === "overview");
|
|
@@ -3498,35 +4337,52 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
3498
4337
|
i0.ɵɵclassProp("active", ctx.activeTab === "tests");
|
|
3499
4338
|
i0.ɵɵattribute("aria-selected", ctx.activeTab === "tests");
|
|
3500
4339
|
i0.ɵɵadvance(3);
|
|
3501
|
-
i0.ɵɵconditional(ctx.testsLoaded ?
|
|
4340
|
+
i0.ɵɵconditional(ctx.testsLoaded ? 48 : -1);
|
|
3502
4341
|
i0.ɵɵadvance();
|
|
3503
4342
|
i0.ɵɵclassProp("active", ctx.activeTab === "runs");
|
|
3504
4343
|
i0.ɵɵattribute("aria-selected", ctx.activeTab === "runs");
|
|
3505
4344
|
i0.ɵɵadvance(3);
|
|
3506
|
-
i0.ɵɵconditional(ctx.runsLoaded ?
|
|
4345
|
+
i0.ɵɵconditional(ctx.runsLoaded ? 52 : -1);
|
|
3507
4346
|
i0.ɵɵadvance();
|
|
3508
4347
|
i0.ɵɵclassProp("active", ctx.activeTab === "analytics");
|
|
3509
4348
|
i0.ɵɵattribute("aria-selected", ctx.activeTab === "analytics");
|
|
3510
4349
|
i0.ɵɵadvance(3);
|
|
3511
4350
|
i0.ɵɵclassProp("active", ctx.activeTab === "compare");
|
|
3512
4351
|
i0.ɵɵattribute("aria-selected", ctx.activeTab === "compare");
|
|
3513
|
-
i0.ɵɵadvance(
|
|
3514
|
-
i0.ɵɵ
|
|
4352
|
+
i0.ɵɵadvance(3);
|
|
4353
|
+
i0.ɵɵclassProp("has-savebar", ctx.isDirty);
|
|
4354
|
+
i0.ɵɵadvance();
|
|
4355
|
+
i0.ɵɵconditional(ctx.activeTab === "overview" ? 60 : -1);
|
|
3515
4356
|
i0.ɵɵadvance();
|
|
3516
|
-
i0.ɵɵconditional(ctx.activeTab === "tests" ?
|
|
4357
|
+
i0.ɵɵconditional(ctx.activeTab === "tests" ? 61 : -1);
|
|
3517
4358
|
i0.ɵɵadvance();
|
|
3518
|
-
i0.ɵɵconditional(ctx.activeTab === "runs" ?
|
|
4359
|
+
i0.ɵɵconditional(ctx.activeTab === "runs" ? 62 : -1);
|
|
3519
4360
|
i0.ɵɵadvance();
|
|
3520
|
-
i0.ɵɵconditional(ctx.activeTab === "analytics" ?
|
|
4361
|
+
i0.ɵɵconditional(ctx.activeTab === "analytics" ? 63 : -1);
|
|
3521
4362
|
i0.ɵɵadvance();
|
|
3522
|
-
i0.ɵɵconditional(ctx.activeTab === "compare" ?
|
|
4363
|
+
i0.ɵɵconditional(ctx.activeTab === "compare" ? 64 : -1);
|
|
3523
4364
|
i0.ɵɵadvance();
|
|
3524
4365
|
i0.ɵɵproperty("title", ctx.showShortcuts ? "Hide keyboard shortcuts" : "Show keyboard shortcuts");
|
|
3525
4366
|
i0.ɵɵadvance(2);
|
|
3526
|
-
i0.ɵɵconditional(ctx.showShortcuts ?
|
|
4367
|
+
i0.ɵɵconditional(ctx.showShortcuts ? 67 : -1);
|
|
3527
4368
|
i0.ɵɵadvance();
|
|
3528
|
-
i0.ɵɵconditional(ctx.testingDialogService.IsPanelOpen ?
|
|
3529
|
-
} }, dependencies: [i1.NgClass, i2.DefaultValueAccessor, i2.NumberValueAccessor, i2.NgControlStatus, i2.NgModel, i3.MJButtonDirective, i4.TestRunDialogComponent, i4.EvaluationModeToggleComponent, i5.LoadingComponent, i6.MjSlidePanelComponent, i1.DatePipe], styles: ["\n\n\n\n\n\n\n[_nghost-%COMP%] {\n --test-primary: var(--mj-brand-primary);\n --test-primary-light: var(--mj-brand-primary);\n --test-success: var(--mj-status-success);\n --test-error: var(--mj-status-error);\n --test-warning: var(--mj-status-warning);\n --test-disabled: var(--mj-text-muted);\n --test-bg: var(--mj-bg-surface-card);\n --test-surface: var(--mj-bg-surface);\n --test-border: var(--mj-border-default);\n --test-text: var(--mj-text-primary);\n --test-text-secondary: var(--mj-text-secondary);\n --test-text-muted: var(--mj-text-disabled);\n --test-radius-sm: 6px;\n --test-radius-md: 10px;\n --test-radius-lg: 16px;\n --test-shadow-sm: var(--mj-shadow-sm);\n --test-shadow-md: var(--mj-shadow-md);\n --test-shadow-lg: var(--mj-shadow-lg);\n --test-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: block;\n height: 100%;\n}\n\n.test-suite-form[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--test-bg);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n\n\n.breadcrumb[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n font-size: 13px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: var(--test-primary);\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 6px;\n transition: background 0.15s;\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n text-decoration: none;\n}\n\n.breadcrumb[_ngcontent-%COMP%] .separator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--test-text-muted);\n margin: 0 4px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] .current[_ngcontent-%COMP%] {\n color: var(--test-text-secondary);\n font-weight: 500;\n}\n\n.breadcrumb-text[_ngcontent-%COMP%] {\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n\n.suite-header[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n padding: 20px;\n}\n\n.header-content[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 16px;\n gap: 16px;\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex: 1;\n min-width: 0;\n}\n\n.suite-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n border-radius: var(--test-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-size: 24px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.suite-icon[_ngcontent-%COMP%]:hover { transform: scale(1.05); }\n\n.suite-info[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n\n.suite-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: clamp(18px, 4vw, 24px);\n font-weight: 700;\n color: var(--test-text);\n word-wrap: break-word;\n}\n\n.suite-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: 20px;\n color: var(--mj-text-inverse);\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-active[_ngcontent-%COMP%] { background: var(--test-success); }\n.status-badge.status-disabled[_ngcontent-%COMP%] { background: var(--test-disabled); }\n.status-badge.status-pending[_ngcontent-%COMP%] { background: var(--test-warning); }\n\n.status-badge-inline[_ngcontent-%COMP%] {\n display: inline-flex;\n padding: 2px 10px;\n border-radius: 10px;\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n}\n\n.status-badge-inline.status-active[_ngcontent-%COMP%] { background: var(--test-success); }\n.status-badge-inline.status-disabled[_ngcontent-%COMP%] { background: var(--test-disabled); }\n.status-badge-inline.status-pending[_ngcontent-%COMP%] { background: var(--test-warning); }\n\n.test-count[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n color: var(--test-text-secondary);\n padding: 4px 10px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.suite-description[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.suite-description[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n color: var(--test-text-secondary);\n line-height: 1.6;\n font-size: 14px;\n}\n\n\n\n.tabs-container[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n\n.tabs[_ngcontent-%COMP%] {\n display: flex;\n padding: 0 20px;\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.tabs[_ngcontent-%COMP%]::-webkit-scrollbar { display: none; }\n\n.tab[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 18px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: var(--test-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n white-space: nowrap;\n}\n\n.tab[_ngcontent-%COMP%]:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.tab.active[_ngcontent-%COMP%] {\n color: var(--test-primary);\n border-bottom-color: var(--test-primary);\n font-weight: 600;\n}\n\n.tab-badge[_ngcontent-%COMP%] {\n background: var(--test-border);\n color: var(--test-text-secondary);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active[_ngcontent-%COMP%] .tab-badge[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--test-primary);\n}\n\n.tab-shortcut[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--test-text-muted);\n background: var(--test-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n\n\n.tab-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n\n\n.overview-tab[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; transform: translateY(10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.info-section[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.info-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 20px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.info-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.info-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n.info-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.info-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 500;\n}\n\n.config-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.config-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.config-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.config-input[_ngcontent-%COMP%] {\n padding: 10px 14px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.config-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.config-hint[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--test-text-muted);\n}\n\n\n\n.tests-tab[_ngcontent-%COMP%], .runs-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.loading-state[_ngcontent-%COMP%] { padding: 0; }\n\n.skeleton-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.skeleton-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.skeleton-sequence[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: var(--test-radius-md);\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.skeleton-line[_ngcontent-%COMP%] {\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-line.wide[_ngcontent-%COMP%] { width: 70%; }\n.skeleton-line.narrow[_ngcontent-%COMP%] { width: 40%; }\n\n@keyframes _ngcontent-%COMP%_shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n.tests-list[_ngcontent-%COMP%], .runs-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.test-item[_ngcontent-%COMP%]:hover, .run-item[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n}\n\n.test-sequence[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n font-size: 14px;\n font-weight: 700;\n color: var(--test-text-secondary);\n flex-shrink: 0;\n}\n\n.test-icon[_ngcontent-%COMP%], .run-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 18px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-sm);\n}\n\n.test-icon[_ngcontent-%COMP%] {\n background: var(--test-primary);\n}\n\n.test-content[_ngcontent-%COMP%], .run-content[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n\n.test-name[_ngcontent-%COMP%], .run-header[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.run-id[_ngcontent-%COMP%] { font-weight: 600; }\n\n.run-status[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.test-status[_ngcontent-%COMP%], .run-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.test-status[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .run-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.test-item[_ngcontent-%COMP%] > i[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.test-item[_ngcontent-%COMP%]:hover > i[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%]:hover > i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 24px;\n text-align: center;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n margin-bottom: 20px;\n}\n\n.empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 36px;\n color: var(--test-text-muted);\n}\n\n.empty-state[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 20px 0;\n font-size: 14px;\n color: var(--test-text-secondary);\n max-width: 300px;\n}\n\n\n\n\n\n.shortcuts-toggle[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n box-shadow: var(--test-shadow-md);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--test-text-secondary);\n font-size: 14px;\n z-index: 99;\n transition: var(--test-transition);\n opacity: 0.7;\n}\n\n.shortcuts-toggle[_ngcontent-%COMP%]:hover {\n opacity: 1;\n transform: scale(1.1);\n color: var(--test-primary);\n border-color: var(--test-primary);\n}\n\n.keyboard-shortcuts[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 12px 16px;\n box-shadow: var(--test-shadow-lg);\n font-size: 12px;\n z-index: 100;\n max-width: 260px;\n}\n\n.shortcuts-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text);\n}\n\n.shortcuts-close[_ngcontent-%COMP%] {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--test-text-muted);\n font-size: 12px;\n padding: 2px 4px;\n border-radius: 4px;\n transition: var(--test-transition);\n}\n\n.shortcuts-close[_ngcontent-%COMP%]:hover {\n color: var(--test-text);\n background: var(--test-border);\n}\n\n.shortcut-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.shortcut-item[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n color: var(--test-text-secondary);\n}\n\n.shortcut-keys[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.shortcut-keys[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n background: var(--test-bg);\n border: 1px solid var(--test-border);\n border-radius: 4px;\n padding: 2px 6px;\n font-size: 11px;\n color: var(--test-text);\n}\n\n\n\n@media (max-width: 1024px) {\n .keyboard-shortcuts[_ngcontent-%COMP%], .shortcuts-toggle[_ngcontent-%COMP%] { display: none; }\n}\n\n@media (max-width: 768px) {\n .suite-header[_ngcontent-%COMP%] { padding: 16px; }\n\n .header-content[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] { flex: 1; }\n\n .tab-shortcut[_ngcontent-%COMP%] { display: none; }\n\n .info-grid[_ngcontent-%COMP%] { grid-template-columns: 1fr; }\n\n .test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] { padding: 14px; }\n}\n\n@media (max-width: 480px) {\n .suite-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 18px;\n }\n\n .suite-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] { font-size: 16px; }\n\n .tab-badge[_ngcontent-%COMP%] { display: none; }\n\n .test-sequence[_ngcontent-%COMP%] { display: none; }\n}\n\n@media (hover: none) and (pointer: coarse) {\n .test-item[_ngcontent-%COMP%]:active, .run-item[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n transform: scale(0.98);\n }\n\n .tab[_ngcontent-%COMP%] { min-height: 48px; }\n .test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] { min-height: 64px; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *[_ngcontent-%COMP%], *[_ngcontent-%COMP%]::before, *[_ngcontent-%COMP%]::after {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n@media print {\n .header-actions[_ngcontent-%COMP%], .tabs-container[_ngcontent-%COMP%], .keyboard-shortcuts[_ngcontent-%COMP%] {\n display: none !important;\n }\n}\n\n\n\n\n\n.run-tags[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 8px;\n}\n\n.tag-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-mini[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.tag-more[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n\n\n.run-eval-metrics[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n}\n\n.eval-metric[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.eval-metric.status[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-metric.status.status-completed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.eval-metric.status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.eval-metric.status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.status.status-pending[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-warning);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human[_ngcontent-%COMP%] .eval-pending[_ngcontent-%COMP%] {\n font-size: 9px;\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.auto.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n color: var(--mj-status-success);\n}\n\n.eval-metric.auto.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n color: var(--mj-status-error);\n}\n\n.tag-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.tag-chip-table[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 80px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n\n\n\n.analytics-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n\n\n.analytics-filters[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n margin-bottom: 16px;\n box-shadow: var(--test-shadow-sm);\n overflow: hidden;\n}\n\n.analytics-filters.collapsed[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.filters-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s ease;\n}\n\n.filters-header[_ngcontent-%COMP%]:hover {\n background: var(--test-bg);\n}\n\n.filters-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text-secondary);\n}\n\n.filters-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.filter-summary[_ngcontent-%COMP%] {\n font-weight: 400;\n color: var(--test-text-muted);\n margin-left: 8px;\n}\n\n.filters-header[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 12px;\n}\n\n.filters-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 16px 16px 16px;\n border-top: 1px solid var(--test-border);\n}\n\n.filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.filter-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.filter-buttons[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.filter-btn[_ngcontent-%COMP%] {\n padding: 8px 16px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.filter-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--test-primary);\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.filter-btn.active[_ngcontent-%COMP%] {\n background: var(--test-primary);\n border-color: var(--test-primary);\n color: var(--mj-text-inverse);\n}\n\n.filter-btn.tag-btn[_ngcontent-%COMP%] {\n padding: 6px 12px;\n font-size: 12px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.filter-btn.tag-btn[_ngcontent-%COMP%] i.fa-check[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.filter-btn.tag-btn.all-tags-btn[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n.filter-btn.tag-btn.all-tags-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.filter-hint[_ngcontent-%COMP%] {\n font-weight: 400;\n font-size: 10px;\n color: var(--test-primary);\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-filters[_ngcontent-%COMP%] {\n max-height: 120px;\n overflow-y: auto;\n}\n\n\n\n.analytics-kpis[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.kpi-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: var(--test-radius-md);\n color: var(--test-primary);\n font-size: 20px;\n}\n\n.kpi-icon.success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-icon.info[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.kpi-icon.warning[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n line-height: 1.2;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n margin-top: 2px;\n}\n\n.kpi-trend[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n font-weight: 600;\n margin-top: 4px;\n padding: 2px 8px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-secondary);\n}\n\n.kpi-trend.trend-up[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-trend.trend-down[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n\n\n.analytics-table-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.analytics-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.analytics-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.analytics-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n margin: 0 -24px;\n padding: 0 24px;\n}\n\n.analytics-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.analytics-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.analytics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.analytics-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.clickable-row[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.analytics-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.clickable-row[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.status-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-chip.status-completed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-passed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-failed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--test-error); }\n.status-chip.status-error[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-running[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--test-primary); }\n.status-chip.status-pending[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-chip.status-cancelled[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n.status-chip.status-missing[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-text-muted); }\n.status-chip.status-timeout[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-skipped[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n\n.pass-rate-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 100px;\n}\n\n.pass-rate-bar[_ngcontent-%COMP%] {\n height: 6px;\n border-radius: 3px;\n background: var(--test-success);\n transition: width 0.3s ease;\n max-width: 60px;\n}\n\n.pass-rate-bar.medium[_ngcontent-%COMP%] { background: var(--test-warning); }\n.pass-rate-bar.low[_ngcontent-%COMP%] { background: var(--test-error); }\n\n\n\n.analytics-subnav[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 8px;\n margin-bottom: 20px;\n box-shadow: var(--test-shadow-sm);\n display: inline-flex;\n}\n\n.subnav-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n}\n\n.subnav-tab[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border: none;\n border-radius: var(--test-radius-sm);\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.subnav-tab[_ngcontent-%COMP%]:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.subnav-tab.active[_ngcontent-%COMP%] {\n background: var(--test-surface);\n color: var(--test-primary);\n box-shadow: var(--test-shadow-sm);\n}\n\n.subnav-tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.matrix-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 16px;\n box-shadow: var(--test-shadow-sm);\n display: flex;\n flex-direction: column;\n max-height: calc(100vh - 280px);\n min-height: 300px;\n}\n\n.matrix-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--test-border);\n flex-shrink: 0;\n}\n\n.matrix-header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.matrix-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.matrix-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.matrix-run-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n font-weight: 500;\n}\n\n\n\n.matrix-filter-input[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--test-border);\n border-radius: 6px;\n padding: 4px 10px;\n min-width: 180px;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] i.fa-search[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] .filter-input[_ngcontent-%COMP%] {\n border: none;\n background: transparent;\n outline: none;\n font-size: 12px;\n color: var(--test-text);\n width: 100%;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] .filter-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.clear-filter-btn[_ngcontent-%COMP%] {\n border: none;\n background: none;\n padding: 2px 4px;\n cursor: pointer;\n color: var(--mj-text-disabled);\n font-size: 10px;\n border-radius: 3px;\n transition: all 0.15s ease;\n}\n\n.clear-filter-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n}\n\n\n\n.matrix-scroll-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n}\n\n.test-matrix[_ngcontent-%COMP%] {\n display: table;\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.test-matrix[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] {\n display: table-header-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n display: table-row;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] {\n display: table-row-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n display: table-row;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] .test-name-cell[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix[_ngcontent-%COMP%] tfoot[_ngcontent-%COMP%] {\n display: table-footer-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n display: table-cell;\n border: 1px solid var(--test-border);\n padding: 8px 12px;\n text-align: center;\n vertical-align: middle;\n}\n\n.test-matrix[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background: var(--test-bg);\n font-weight: 600;\n font-size: 11px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n position: sticky;\n top: 0;\n z-index: 10;\n border-bottom: 3px solid var(--mj-text-secondary) !important;\n}\n\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%] {\n width: 36px;\n min-width: 36px;\n max-width: 36px;\n text-align: center;\n position: sticky;\n left: 0;\n font-size: 11px;\n color: var(--mj-text-muted);\n border-right: 1px solid var(--test-border);\n padding: 6px 4px !important;\n}\n\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%] {\n cursor: pointer;\n font-weight: 600;\n background: var(--test-bg);\n z-index: 12; \n\n top: 0;\n}\n\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%] {\n background: var(--test-surface);\n z-index: 2;\n}\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n margin-left: 2px;\n opacity: 0.6;\n}\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%] {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-bg);\n z-index: 11;\n border-right: 2px solid var(--test-border);\n cursor: pointer;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n margin-left: 4px;\n opacity: 0.6;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix[_ngcontent-%COMP%] .run-header[_ngcontent-%COMP%] {\n min-width: 120px;\n width: 120px;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n\n\n.test-matrix[_ngcontent-%COMP%] .spacer-header[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] .spacer-cell[_ngcontent-%COMP%] {\n width: 100%;\n min-width: 20px;\n background: var(--test-bg);\n border: none;\n}\n\n.test-matrix[_ngcontent-%COMP%] .spacer-cell[_ngcontent-%COMP%] {\n background: var(--test-surface);\n}\n\n.test-matrix[_ngcontent-%COMP%] .run-header[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-header-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.run-date[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-pass-rate[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.run-pass-rate.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.run-pass-rate.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.run-pass-rate.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.run-tags[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.tag-tiny[_ngcontent-%COMP%] {\n font-size: 9px;\n padding: 2px 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--test-primary);\n border-radius: 8px;\n white-space: nowrap;\n max-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n\n.run-tags-header[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 3px;\n justify-content: center;\n margin-bottom: 4px;\n}\n\n.tag-chip-header[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 70px;\n overflow: hidden;\n text-overflow: ellipsis;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-more-header[_ngcontent-%COMP%] {\n font-size: 9px;\n color: var(--test-text-secondary);\n padding: 2px 4px;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-cell[_ngcontent-%COMP%] {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-surface);\n z-index: 2;\n border-right: 2px solid var(--test-border);\n padding: 6px 10px !important;\n}\n\n.test-name[_ngcontent-%COMP%] {\n display: block;\n white-space: nowrap;\n font-weight: 500;\n color: var(--test-text);\n font-size: 12px;\n}\n\n.result-cell[_ngcontent-%COMP%] {\n position: relative;\n min-width: 120px;\n width: 120px;\n transition: var(--test-transition);\n}\n\n.result-cell.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.result-cell.clickable[_ngcontent-%COMP%]:hover {\n transform: scale(1.1);\n box-shadow: var(--mj-shadow-md);\n z-index: 5;\n}\n\n.result-cell[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.result-cell.cell-passed[_ngcontent-%COMP%], \n.result-cell.cell-failed[_ngcontent-%COMP%], \n.result-cell.cell-error[_ngcontent-%COMP%], \n.result-cell.cell-timeout[_ngcontent-%COMP%], \n.result-cell.cell-running[_ngcontent-%COMP%], \n.result-cell.cell-pending[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--test-text);\n}\n\n\n\n.result-cell.cell-skipped[_ngcontent-%COMP%] {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--test-disabled);\n}\n\n.result-cell.cell-none[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n color: var(--test-text-muted);\n}\n\n.cell-score[_ngcontent-%COMP%] {\n display: block;\n font-size: 10px;\n font-weight: 600;\n margin-top: 2px;\n}\n\n\n\n.cell-eval-stack[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n flex-wrap: nowrap;\n}\n\n.result-cell.multi-eval[_ngcontent-%COMP%] {\n min-width: 120px;\n width: auto;\n}\n\n\n\n.cell-status.status-timeout[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-status.status-pending[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.cell-human[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n font-size: 10px;\n}\n\n.cell-auto[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-auto.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-none-indicator[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n opacity: 0.5;\n}\n\n.matrix-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.matrix-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n\n\n\n\n.chart-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.chart-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.chart-legend[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-skipped[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-disabled);\n}\n\n.chart-container[_ngcontent-%COMP%] {\n min-height: 500px;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.d3-chart[_ngcontent-%COMP%] {\n width: 100%;\n height: 500px;\n}\n\n.d3-chart[_ngcontent-%COMP%] svg[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n}\n\n\n\n.d3-chart[_ngcontent-%COMP%] .node[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: transform 0.2s ease;\n}\n\n.d3-chart[_ngcontent-%COMP%] .node[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n.d3-chart[_ngcontent-%COMP%] .node-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 500;\n fill: var(--test-text);\n pointer-events: none;\n}\n\n.d3-chart[_ngcontent-%COMP%] .link[_ngcontent-%COMP%] {\n fill: none;\n stroke-opacity: 0.4;\n transition: stroke-opacity 0.2s ease;\n}\n\n.d3-chart[_ngcontent-%COMP%] .link[_ngcontent-%COMP%]:hover {\n stroke-opacity: 0.8;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip[_ngcontent-%COMP%] {\n position: absolute;\n padding: 10px 14px;\n background: var(--mj-bg-overlay);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 12px;\n pointer-events: none;\n z-index: 100;\n box-shadow: var(--mj-shadow-lg);\n max-width: 250px;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip-title[_ngcontent-%COMP%] {\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip-value[_ngcontent-%COMP%] {\n opacity: 0.8;\n}\n\n.chart-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n margin-top: 16px;\n}\n\n.chart-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n\n\n\n\n.compare-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.compare-selection[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 24px;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.compare-run-selector[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-run-selector[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.run-selector-list[_ngcontent-%COMP%] {\n max-height: 200px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.run-selector-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.run-selector-item[_ngcontent-%COMP%]:hover {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-selector-item.selected[_ngcontent-%COMP%] {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.run-selector-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.selector-status[_ngcontent-%COMP%] {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.selector-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.selector-date[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--test-text);\n}\n\n.selector-rate[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--test-text-secondary);\n}\n\n.selector-tags[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.selected-run-preview[_ngcontent-%COMP%] {\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-sm);\n border: 1px solid var(--test-border);\n}\n\n.preview-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.preview-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n}\n\n.clear-btn[_ngcontent-%COMP%] {\n padding: 4px 8px;\n border: none;\n background: transparent;\n color: var(--test-error);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.clear-btn[_ngcontent-%COMP%]:hover { text-decoration: underline; }\n\n.preview-details[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--test-text);\n}\n\n.preview-rate[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--test-success);\n}\n\n.compare-vs[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--test-bg);\n border-radius: 50%;\n color: var(--test-text-muted);\n font-size: 16px;\n align-self: center;\n margin-top: 60px;\n}\n\n\n\n.compare-results[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.compare-summary[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n text-align: center;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n margin-bottom: 8px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-value.positive[_ngcontent-%COMP%] { color: var(--test-success); }\n.compare-summary-card[_ngcontent-%COMP%] .summary-value.negative[_ngcontent-%COMP%] { color: var(--test-error); }\n\n.compare-summary-card.improved[_ngcontent-%COMP%] {\n border-left: 4px solid var(--test-success);\n}\n\n.compare-summary-card.improved[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] { color: var(--test-success); }\n\n.compare-summary-card.regressed[_ngcontent-%COMP%] {\n border-left: 4px solid var(--test-error);\n}\n\n.compare-summary-card.regressed[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] { color: var(--test-error); }\n\n\n\n.compare-table-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.compare-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.compare-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.compare-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.compare-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.compare-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.compare-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.improved[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.compare-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.regressed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.test-name-cell[_ngcontent-%COMP%] {\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.positive[_ngcontent-%COMP%] { color: var(--test-success); }\n.negative[_ngcontent-%COMP%] { color: var(--test-error); }\n.muted[_ngcontent-%COMP%] { color: var(--test-text-muted); }\n\n.change-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.change-indicator.improved[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.change-indicator.regressed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.change-indicator.unchanged[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-muted);\n}\n\n\n\n.compare-empty[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px 24px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n margin-top: 24px;\n}\n\n.compare-empty-icon[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n margin: 0 auto 20px;\n}\n\n.compare-empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n color: var(--test-text-muted);\n}\n\n.compare-empty[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.compare-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: var(--test-text-secondary);\n max-width: 400px;\n margin: 0 auto;\n}\n\n\n\n.empty-state.small[_ngcontent-%COMP%] {\n padding: 32px 16px;\n}\n\n.empty-state.small[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n}\n\n\n\n\n\n@media (max-width: 1024px) {\n .compare-selection[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n .compare-vs[_ngcontent-%COMP%] {\n margin: 0;\n align-self: center;\n justify-self: center;\n }\n\n .analytics-kpis[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .filter-buttons[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .filter-btn[_ngcontent-%COMP%] {\n width: 100%;\n text-align: center;\n }\n\n .analytics-kpis[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .kpi-card[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .kpi-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .compare-summary[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .analytics-table-wrapper[_ngcontent-%COMP%], \n .compare-table-wrapper[_ngcontent-%COMP%] {\n margin: 0 -20px;\n padding: 0 20px;\n }\n\n .run-selector-list[_ngcontent-%COMP%] {\n max-height: 150px;\n }\n}\n\n@media (max-width: 480px) {\n .compare-summary[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .compare-summary-card[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .analytics-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .analytics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%], \n .compare-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .compare-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-size: 12px;\n }\n}\n\n\n\n\n\n\n\n\n.cell-human[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-human.no-feedback[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-human.no-feedback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] .rating-value[_ngcontent-%COMP%] {\n font-weight: 700;\n font-size: 11px;\n}\n\n\n\n.cell-human.rating-low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-human.rating-medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-human.rating-good[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-human.rating-excellent[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n\n\n.cell-auto[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-auto.no-score[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-auto.no-score[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] .score-value[_ngcontent-%COMP%] {\n font-weight: 700;\n font-size: 10px;\n}\n\n\n\n.cell-auto.score-low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-auto.score-medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.score-good[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.score-excellent[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n\n\n.cell-status[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-timeout[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped[_ngcontent-%COMP%], \n.cell-status.status-pending[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n\n\n.result-cell.cell-not-run[_ngcontent-%COMP%] {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--mj-text-disabled);\n}\n\n.result-cell.cell-not-run[_ngcontent-%COMP%] .cell-eval-stack[_ngcontent-%COMP%] {\n opacity: 0.6;\n}\n\n.cell-not-run-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n color: var(--mj-text-disabled);\n font-size: 11px;\n}\n\n\n\n\n\n.test-matrix[_ngcontent-%COMP%] tfoot[_ngcontent-%COMP%] {\n position: sticky;\n bottom: 0;\n z-index: 2;\n}\n\n.totals-row[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-top: 2px solid var(--test-border);\n}\n\n.totals-row[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-weight: 600;\n}\n\n.totals-row[_ngcontent-%COMP%] .totals-label[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n font-size: 12px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.totals-row[_ngcontent-%COMP%] .totals-cell[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n}\n\n.totals-stack[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.totals-status[_ngcontent-%COMP%], \n.totals-human[_ngcontent-%COMP%], \n.totals-auto[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.totals-status[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.totals-status[_ngcontent-%COMP%] .pass-count[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-human[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.totals-human[_ngcontent-%COMP%] .avg-label[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-human[_ngcontent-%COMP%] .count-label[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.8;\n}\n\n.totals-auto[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.totals-auto[_ngcontent-%COMP%] .avg-label[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-auto[_ngcontent-%COMP%] .count-label[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.8;\n}"], changeDetection: 0 }); }
|
|
4369
|
+
i0.ɵɵconditional(ctx.testingDialogService.IsPanelOpen ? 68 : -1);
|
|
4370
|
+
i0.ɵɵadvance();
|
|
4371
|
+
i0.ɵɵconditional(ctx.showAddTestsDialog ? 69 : -1);
|
|
4372
|
+
i0.ɵɵadvance();
|
|
4373
|
+
i0.ɵɵclassProp("save-bar--visible", ctx.isDirty);
|
|
4374
|
+
i0.ɵɵattribute("aria-hidden", !ctx.isDirty);
|
|
4375
|
+
i0.ɵɵadvance(8);
|
|
4376
|
+
i0.ɵɵconditional(ctx.dirtyFieldNames.length === 1 ? 78 : ctx.dirtyFieldNames.length > 1 ? 79 : -1);
|
|
4377
|
+
i0.ɵɵadvance(3);
|
|
4378
|
+
i0.ɵɵproperty("disabled", ctx.isSaving || !ctx.isDirty);
|
|
4379
|
+
i0.ɵɵattribute("tabindex", ctx.isDirty ? 0 : -1);
|
|
4380
|
+
i0.ɵɵadvance();
|
|
4381
|
+
i0.ɵɵconditional(ctx.isSaving ? 82 : 83);
|
|
4382
|
+
i0.ɵɵadvance(2);
|
|
4383
|
+
i0.ɵɵproperty("disabled", ctx.isSaving || !ctx.isDirty);
|
|
4384
|
+
i0.ɵɵattribute("tabindex", ctx.isDirty ? 0 : -1);
|
|
4385
|
+
} }, dependencies: [i1.NgClass, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.NumberValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.CdkDropList, i3.CdkDrag, i3.CdkDragHandle, i4.MJButtonDirective, i5.TestRunDialogComponent, i5.EvaluationModeToggleComponent, i6.LoadingComponent, i7.MjSlidePanelComponent, i1.DatePipe], styles: ["\n\n\n\n\n\n\n[_nghost-%COMP%] {\n --test-primary: var(--mj-brand-primary);\n --test-primary-light: var(--mj-brand-primary);\n --test-success: var(--mj-status-success);\n --test-error: var(--mj-status-error);\n --test-warning: var(--mj-status-warning);\n --test-disabled: var(--mj-text-muted);\n --test-bg: var(--mj-bg-surface-card);\n --test-surface: var(--mj-bg-surface);\n --test-border: var(--mj-border-default);\n --test-text: var(--mj-text-primary);\n --test-text-secondary: var(--mj-text-secondary);\n --test-text-muted: var(--mj-text-disabled);\n --test-radius-sm: 6px;\n --test-radius-md: 10px;\n --test-radius-lg: 16px;\n --test-shadow-sm: var(--mj-shadow-sm);\n --test-shadow-md: var(--mj-shadow-md);\n --test-shadow-lg: var(--mj-shadow-lg);\n --test-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: block;\n height: 100%;\n}\n\n.test-suite-form[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--test-bg);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n\n\n.breadcrumb[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n font-size: 13px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: var(--test-primary);\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 6px;\n transition: background 0.15s;\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n text-decoration: none;\n}\n\n.breadcrumb[_ngcontent-%COMP%] .separator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--test-text-muted);\n margin: 0 4px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] .current[_ngcontent-%COMP%] {\n color: var(--test-text-secondary);\n font-weight: 500;\n}\n\n.breadcrumb-text[_ngcontent-%COMP%] {\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n\n.suite-header[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n padding: 20px;\n}\n\n.header-content[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 16px;\n gap: 16px;\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex: 1;\n min-width: 0;\n}\n\n.suite-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n border-radius: var(--test-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-size: 24px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.suite-icon[_ngcontent-%COMP%]:hover { transform: scale(1.05); }\n\n.suite-info[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n\n.suite-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: clamp(18px, 4vw, 24px);\n font-weight: 700;\n color: var(--test-text);\n word-wrap: break-word;\n}\n\n.suite-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: 20px;\n color: var(--mj-text-inverse);\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-active[_ngcontent-%COMP%] { background: var(--test-success); }\n.status-badge.status-disabled[_ngcontent-%COMP%] { background: var(--test-disabled); }\n.status-badge.status-pending[_ngcontent-%COMP%] { background: var(--test-warning); }\n\n.status-badge-inline[_ngcontent-%COMP%] {\n display: inline-flex;\n padding: 2px 10px;\n border-radius: 10px;\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n}\n\n.status-badge-inline.status-active[_ngcontent-%COMP%] { background: var(--test-success); }\n.status-badge-inline.status-disabled[_ngcontent-%COMP%] { background: var(--test-disabled); }\n.status-badge-inline.status-pending[_ngcontent-%COMP%] { background: var(--test-warning); }\n\n.test-count[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n color: var(--test-text-secondary);\n padding: 4px 10px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.suite-description[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.suite-description[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n color: var(--test-text-secondary);\n line-height: 1.6;\n font-size: 14px;\n}\n\n\n\n.tabs-container[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n\n.tabs[_ngcontent-%COMP%] {\n display: flex;\n padding: 0 20px;\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.tabs[_ngcontent-%COMP%]::-webkit-scrollbar { display: none; }\n\n.tab[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 18px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: var(--test-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n white-space: nowrap;\n}\n\n.tab[_ngcontent-%COMP%]:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.tab.active[_ngcontent-%COMP%] {\n color: var(--test-primary);\n border-bottom-color: var(--test-primary);\n font-weight: 600;\n}\n\n.tab-badge[_ngcontent-%COMP%] {\n background: var(--test-border);\n color: var(--test-text-secondary);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active[_ngcontent-%COMP%] .tab-badge[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--test-primary);\n}\n\n.tab-shortcut[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--test-text-muted);\n background: var(--test-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n\n\n.tab-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n\n\n.overview-tab[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; transform: translateY(10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.info-section[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.info-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 20px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.info-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.info-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n.info-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.info-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 500;\n}\n\n.config-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.config-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.config-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.config-input[_ngcontent-%COMP%] {\n padding: 10px 14px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.config-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.config-hint[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--test-text-muted);\n}\n\n\n\n.tests-tab[_ngcontent-%COMP%], .runs-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.loading-state[_ngcontent-%COMP%] { padding: 0; }\n\n.skeleton-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.skeleton-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.skeleton-sequence[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: var(--test-radius-md);\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.skeleton-line[_ngcontent-%COMP%] {\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-line.wide[_ngcontent-%COMP%] { width: 70%; }\n.skeleton-line.narrow[_ngcontent-%COMP%] { width: 40%; }\n\n@keyframes _ngcontent-%COMP%_shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n.tests-list[_ngcontent-%COMP%], .runs-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.test-item[_ngcontent-%COMP%]:hover, .run-item[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n}\n\n.test-sequence[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n font-size: 14px;\n font-weight: 700;\n color: var(--test-text-secondary);\n flex-shrink: 0;\n}\n\n.test-icon[_ngcontent-%COMP%], .run-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 18px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-sm);\n}\n\n.test-icon[_ngcontent-%COMP%] {\n background: var(--test-primary);\n}\n\n.test-content[_ngcontent-%COMP%], .run-content[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n\n.test-name[_ngcontent-%COMP%], .run-header[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.run-id[_ngcontent-%COMP%] { font-weight: 600; }\n\n.run-status[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.test-status[_ngcontent-%COMP%], .run-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.test-status[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .run-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.test-item[_ngcontent-%COMP%] > i[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.test-item[_ngcontent-%COMP%]:hover > i[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%]:hover > i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 24px;\n text-align: center;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n margin-bottom: 20px;\n}\n\n.empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 36px;\n color: var(--test-text-muted);\n}\n\n.empty-state[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 20px 0;\n font-size: 14px;\n color: var(--test-text-secondary);\n max-width: 300px;\n}\n\n\n\n\n\n.shortcuts-toggle[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n box-shadow: var(--test-shadow-md);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--test-text-secondary);\n font-size: 14px;\n z-index: 99;\n transition: var(--test-transition);\n opacity: 0.7;\n}\n\n.shortcuts-toggle[_ngcontent-%COMP%]:hover {\n opacity: 1;\n transform: scale(1.1);\n color: var(--test-primary);\n border-color: var(--test-primary);\n}\n\n.keyboard-shortcuts[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 12px 16px;\n box-shadow: var(--test-shadow-lg);\n font-size: 12px;\n z-index: 100;\n max-width: 260px;\n}\n\n.shortcuts-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text);\n}\n\n.shortcuts-close[_ngcontent-%COMP%] {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--test-text-muted);\n font-size: 12px;\n padding: 2px 4px;\n border-radius: 4px;\n transition: var(--test-transition);\n}\n\n.shortcuts-close[_ngcontent-%COMP%]:hover {\n color: var(--test-text);\n background: var(--test-border);\n}\n\n.shortcut-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.shortcut-item[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n color: var(--test-text-secondary);\n}\n\n.shortcut-keys[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.shortcut-keys[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n background: var(--test-bg);\n border: 1px solid var(--test-border);\n border-radius: 4px;\n padding: 2px 6px;\n font-size: 11px;\n color: var(--test-text);\n}\n\n\n\n@media (max-width: 1024px) {\n .keyboard-shortcuts[_ngcontent-%COMP%], .shortcuts-toggle[_ngcontent-%COMP%] { display: none; }\n}\n\n@media (max-width: 768px) {\n .suite-header[_ngcontent-%COMP%] { padding: 16px; }\n\n .header-content[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] { flex: 1; }\n\n .tab-shortcut[_ngcontent-%COMP%] { display: none; }\n\n .info-grid[_ngcontent-%COMP%] { grid-template-columns: 1fr; }\n\n .test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] { padding: 14px; }\n}\n\n@media (max-width: 480px) {\n .suite-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 18px;\n }\n\n .suite-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] { font-size: 16px; }\n\n .tab-badge[_ngcontent-%COMP%] { display: none; }\n\n .test-sequence[_ngcontent-%COMP%] { display: none; }\n}\n\n@media (hover: none) and (pointer: coarse) {\n .test-item[_ngcontent-%COMP%]:active, .run-item[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n transform: scale(0.98);\n }\n\n .tab[_ngcontent-%COMP%] { min-height: 48px; }\n .test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] { min-height: 64px; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *[_ngcontent-%COMP%], *[_ngcontent-%COMP%]::before, *[_ngcontent-%COMP%]::after {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n@media print {\n .header-actions[_ngcontent-%COMP%], .tabs-container[_ngcontent-%COMP%], .keyboard-shortcuts[_ngcontent-%COMP%] {\n display: none !important;\n }\n}\n\n\n\n\n\n.run-tags[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 8px;\n}\n\n.tag-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-mini[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.tag-more[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n\n\n.run-eval-metrics[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n}\n\n.eval-metric[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.eval-metric.status[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-metric.status.status-completed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.eval-metric.status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.eval-metric.status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.status.status-pending[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-warning);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human[_ngcontent-%COMP%] .eval-pending[_ngcontent-%COMP%] {\n font-size: 9px;\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.auto.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n color: var(--mj-status-success);\n}\n\n.eval-metric.auto.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n color: var(--mj-status-error);\n}\n\n.tag-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.tag-chip-table[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 80px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n\n\n\n.analytics-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n\n\n.analytics-filters[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n margin-bottom: 16px;\n box-shadow: var(--test-shadow-sm);\n overflow: hidden;\n}\n\n.analytics-filters.collapsed[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.filters-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s ease;\n}\n\n.filters-header[_ngcontent-%COMP%]:hover {\n background: var(--test-bg);\n}\n\n.filters-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text-secondary);\n}\n\n.filters-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.filter-summary[_ngcontent-%COMP%] {\n font-weight: 400;\n color: var(--test-text-muted);\n margin-left: 8px;\n}\n\n.filters-header[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 12px;\n}\n\n.filters-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 16px 16px 16px;\n border-top: 1px solid var(--test-border);\n}\n\n.filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.filter-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.filter-buttons[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.filter-btn[_ngcontent-%COMP%] {\n padding: 8px 16px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.filter-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--test-primary);\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.filter-btn.active[_ngcontent-%COMP%] {\n background: var(--test-primary);\n border-color: var(--test-primary);\n color: var(--mj-text-inverse);\n}\n\n.filter-btn.tag-btn[_ngcontent-%COMP%] {\n padding: 6px 12px;\n font-size: 12px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.filter-btn.tag-btn[_ngcontent-%COMP%] i.fa-check[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.filter-btn.tag-btn.all-tags-btn[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n.filter-btn.tag-btn.all-tags-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.filter-hint[_ngcontent-%COMP%] {\n font-weight: 400;\n font-size: 10px;\n color: var(--test-primary);\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-filters[_ngcontent-%COMP%] {\n max-height: 120px;\n overflow-y: auto;\n}\n\n\n\n.analytics-kpis[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.kpi-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: var(--test-radius-md);\n color: var(--test-primary);\n font-size: 20px;\n}\n\n.kpi-icon.success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-icon.info[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.kpi-icon.warning[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n line-height: 1.2;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n margin-top: 2px;\n}\n\n.kpi-trend[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n font-weight: 600;\n margin-top: 4px;\n padding: 2px 8px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-secondary);\n}\n\n.kpi-trend.trend-up[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-trend.trend-down[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n\n\n.analytics-table-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.analytics-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.analytics-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.analytics-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n margin: 0 -24px;\n padding: 0 24px;\n}\n\n.analytics-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.analytics-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.analytics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.analytics-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.clickable-row[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.analytics-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.clickable-row[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.status-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-chip.status-completed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-passed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-failed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--test-error); }\n.status-chip.status-error[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-running[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--test-primary); }\n.status-chip.status-pending[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-chip.status-cancelled[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n.status-chip.status-missing[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-text-muted); }\n.status-chip.status-timeout[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-skipped[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n\n.pass-rate-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 100px;\n}\n\n.pass-rate-bar[_ngcontent-%COMP%] {\n height: 6px;\n border-radius: 3px;\n background: var(--test-success);\n transition: width 0.3s ease;\n max-width: 60px;\n}\n\n.pass-rate-bar.medium[_ngcontent-%COMP%] { background: var(--test-warning); }\n.pass-rate-bar.low[_ngcontent-%COMP%] { background: var(--test-error); }\n\n\n\n.analytics-subnav[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 8px;\n margin-bottom: 20px;\n box-shadow: var(--test-shadow-sm);\n display: inline-flex;\n}\n\n.subnav-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n}\n\n.subnav-tab[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border: none;\n border-radius: var(--test-radius-sm);\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.subnav-tab[_ngcontent-%COMP%]:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.subnav-tab.active[_ngcontent-%COMP%] {\n background: var(--test-surface);\n color: var(--test-primary);\n box-shadow: var(--test-shadow-sm);\n}\n\n.subnav-tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.matrix-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 16px;\n box-shadow: var(--test-shadow-sm);\n display: flex;\n flex-direction: column;\n max-height: calc(100vh - 280px);\n min-height: 300px;\n}\n\n.matrix-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--test-border);\n flex-shrink: 0;\n}\n\n.matrix-header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.matrix-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.matrix-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.matrix-run-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n font-weight: 500;\n}\n\n\n\n.matrix-filter-input[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--test-border);\n border-radius: 6px;\n padding: 4px 10px;\n min-width: 180px;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] i.fa-search[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] .filter-input[_ngcontent-%COMP%] {\n border: none;\n background: transparent;\n outline: none;\n font-size: 12px;\n color: var(--test-text);\n width: 100%;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] .filter-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.clear-filter-btn[_ngcontent-%COMP%] {\n border: none;\n background: none;\n padding: 2px 4px;\n cursor: pointer;\n color: var(--mj-text-disabled);\n font-size: 10px;\n border-radius: 3px;\n transition: all 0.15s ease;\n}\n\n.clear-filter-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n}\n\n\n\n.matrix-scroll-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n}\n\n.test-matrix[_ngcontent-%COMP%] {\n display: table;\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.test-matrix[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] {\n display: table-header-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n display: table-row;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] {\n display: table-row-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n display: table-row;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] .test-name-cell[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix[_ngcontent-%COMP%] tfoot[_ngcontent-%COMP%] {\n display: table-footer-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n display: table-cell;\n border: 1px solid var(--test-border);\n padding: 8px 12px;\n text-align: center;\n vertical-align: middle;\n}\n\n.test-matrix[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background: var(--test-bg);\n font-weight: 600;\n font-size: 11px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n position: sticky;\n top: 0;\n z-index: 10;\n border-bottom: 3px solid var(--mj-text-secondary) !important;\n}\n\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%] {\n width: 36px;\n min-width: 36px;\n max-width: 36px;\n text-align: center;\n position: sticky;\n left: 0;\n font-size: 11px;\n color: var(--mj-text-muted);\n border-right: 1px solid var(--test-border);\n padding: 6px 4px !important;\n}\n\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%] {\n cursor: pointer;\n font-weight: 600;\n background: var(--test-bg);\n z-index: 12; \n\n top: 0;\n}\n\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%] {\n background: var(--test-surface);\n z-index: 2;\n}\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n margin-left: 2px;\n opacity: 0.6;\n}\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%] {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-bg);\n z-index: 11;\n border-right: 2px solid var(--test-border);\n cursor: pointer;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n margin-left: 4px;\n opacity: 0.6;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix[_ngcontent-%COMP%] .run-header[_ngcontent-%COMP%] {\n min-width: 120px;\n width: 120px;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n\n\n.test-matrix[_ngcontent-%COMP%] .spacer-header[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] .spacer-cell[_ngcontent-%COMP%] {\n width: 100%;\n min-width: 20px;\n background: var(--test-bg);\n border: none;\n}\n\n.test-matrix[_ngcontent-%COMP%] .spacer-cell[_ngcontent-%COMP%] {\n background: var(--test-surface);\n}\n\n.test-matrix[_ngcontent-%COMP%] .run-header[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-header-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.run-date[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-pass-rate[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.run-pass-rate.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.run-pass-rate.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.run-pass-rate.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.run-tags[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.tag-tiny[_ngcontent-%COMP%] {\n font-size: 9px;\n padding: 2px 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--test-primary);\n border-radius: 8px;\n white-space: nowrap;\n max-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n\n.run-tags-header[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 3px;\n justify-content: center;\n margin-bottom: 4px;\n}\n\n.tag-chip-header[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 70px;\n overflow: hidden;\n text-overflow: ellipsis;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-more-header[_ngcontent-%COMP%] {\n font-size: 9px;\n color: var(--test-text-secondary);\n padding: 2px 4px;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-cell[_ngcontent-%COMP%] {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-surface);\n z-index: 2;\n border-right: 2px solid var(--test-border);\n padding: 6px 10px !important;\n}\n\n.test-name[_ngcontent-%COMP%] {\n display: block;\n white-space: nowrap;\n font-weight: 500;\n color: var(--test-text);\n font-size: 12px;\n}\n\n.result-cell[_ngcontent-%COMP%] {\n position: relative;\n min-width: 120px;\n width: 120px;\n transition: var(--test-transition);\n}\n\n.result-cell.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.result-cell.clickable[_ngcontent-%COMP%]:hover {\n transform: scale(1.1);\n box-shadow: var(--mj-shadow-md);\n z-index: 5;\n}\n\n.result-cell[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.result-cell.cell-passed[_ngcontent-%COMP%], \n.result-cell.cell-failed[_ngcontent-%COMP%], \n.result-cell.cell-error[_ngcontent-%COMP%], \n.result-cell.cell-timeout[_ngcontent-%COMP%], \n.result-cell.cell-running[_ngcontent-%COMP%], \n.result-cell.cell-pending[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--test-text);\n}\n\n\n\n.result-cell.cell-skipped[_ngcontent-%COMP%] {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--test-disabled);\n}\n\n.result-cell.cell-none[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n color: var(--test-text-muted);\n}\n\n.cell-score[_ngcontent-%COMP%] {\n display: block;\n font-size: 10px;\n font-weight: 600;\n margin-top: 2px;\n}\n\n\n\n.cell-eval-stack[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n flex-wrap: nowrap;\n}\n\n.result-cell.multi-eval[_ngcontent-%COMP%] {\n min-width: 120px;\n width: auto;\n}\n\n\n\n.cell-status.status-timeout[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-status.status-pending[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.cell-human[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n font-size: 10px;\n}\n\n.cell-auto[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-auto.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-none-indicator[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n opacity: 0.5;\n}\n\n.matrix-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.matrix-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n\n\n\n\n.chart-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.chart-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.chart-legend[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-skipped[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-disabled);\n}\n\n.chart-container[_ngcontent-%COMP%] {\n min-height: 500px;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.d3-chart[_ngcontent-%COMP%] {\n width: 100%;\n height: 500px;\n}\n\n.d3-chart[_ngcontent-%COMP%] svg[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n}\n\n\n\n.d3-chart[_ngcontent-%COMP%] .node[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: transform 0.2s ease;\n}\n\n.d3-chart[_ngcontent-%COMP%] .node[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n.d3-chart[_ngcontent-%COMP%] .node-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 500;\n fill: var(--test-text);\n pointer-events: none;\n}\n\n.d3-chart[_ngcontent-%COMP%] .link[_ngcontent-%COMP%] {\n fill: none;\n stroke-opacity: 0.4;\n transition: stroke-opacity 0.2s ease;\n}\n\n.d3-chart[_ngcontent-%COMP%] .link[_ngcontent-%COMP%]:hover {\n stroke-opacity: 0.8;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip[_ngcontent-%COMP%] {\n position: absolute;\n padding: 10px 14px;\n background: var(--mj-bg-overlay);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 12px;\n pointer-events: none;\n z-index: 100;\n box-shadow: var(--mj-shadow-lg);\n max-width: 250px;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip-title[_ngcontent-%COMP%] {\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip-value[_ngcontent-%COMP%] {\n opacity: 0.8;\n}\n\n.chart-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n margin-top: 16px;\n}\n\n.chart-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n\n\n\n\n.compare-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.compare-selection[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 24px;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.compare-run-selector[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-run-selector[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.run-selector-list[_ngcontent-%COMP%] {\n max-height: 200px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.run-selector-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.run-selector-item[_ngcontent-%COMP%]:hover {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-selector-item.selected[_ngcontent-%COMP%] {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.run-selector-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.selector-status[_ngcontent-%COMP%] {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.selector-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.selector-date[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--test-text);\n}\n\n.selector-rate[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--test-text-secondary);\n}\n\n.selector-tags[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.selected-run-preview[_ngcontent-%COMP%] {\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-sm);\n border: 1px solid var(--test-border);\n}\n\n.preview-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.preview-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n}\n\n.clear-btn[_ngcontent-%COMP%] {\n padding: 4px 8px;\n border: none;\n background: transparent;\n color: var(--test-error);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.clear-btn[_ngcontent-%COMP%]:hover { text-decoration: underline; }\n\n.preview-details[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--test-text);\n}\n\n.preview-rate[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--test-success);\n}\n\n.compare-vs[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--test-bg);\n border-radius: 50%;\n color: var(--test-text-muted);\n font-size: 16px;\n align-self: center;\n margin-top: 60px;\n}\n\n\n\n.compare-results[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.compare-summary[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n text-align: center;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n margin-bottom: 8px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-value.positive[_ngcontent-%COMP%] { color: var(--test-success); }\n.compare-summary-card[_ngcontent-%COMP%] .summary-value.negative[_ngcontent-%COMP%] { color: var(--test-error); }\n\n.compare-summary-card.improved[_ngcontent-%COMP%] {\n border-left: 4px solid var(--test-success);\n}\n\n.compare-summary-card.improved[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] { color: var(--test-success); }\n\n.compare-summary-card.regressed[_ngcontent-%COMP%] {\n border-left: 4px solid var(--test-error);\n}\n\n.compare-summary-card.regressed[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] { color: var(--test-error); }\n\n\n\n.compare-table-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.compare-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.compare-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.compare-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.compare-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.compare-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.compare-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.improved[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.compare-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.regressed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.test-name-cell[_ngcontent-%COMP%] {\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.positive[_ngcontent-%COMP%] { color: var(--test-success); }\n.negative[_ngcontent-%COMP%] { color: var(--test-error); }\n.muted[_ngcontent-%COMP%] { color: var(--test-text-muted); }\n\n.change-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.change-indicator.improved[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.change-indicator.regressed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.change-indicator.unchanged[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-muted);\n}\n\n\n\n.compare-empty[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px 24px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n margin-top: 24px;\n}\n\n.compare-empty-icon[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n margin: 0 auto 20px;\n}\n\n.compare-empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n color: var(--test-text-muted);\n}\n\n.compare-empty[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.compare-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: var(--test-text-secondary);\n max-width: 400px;\n margin: 0 auto;\n}\n\n\n\n.empty-state.small[_ngcontent-%COMP%] {\n padding: 32px 16px;\n}\n\n.empty-state.small[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n}\n\n\n\n\n\n@media (max-width: 1024px) {\n .compare-selection[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n .compare-vs[_ngcontent-%COMP%] {\n margin: 0;\n align-self: center;\n justify-self: center;\n }\n\n .analytics-kpis[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .filter-buttons[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .filter-btn[_ngcontent-%COMP%] {\n width: 100%;\n text-align: center;\n }\n\n .analytics-kpis[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .kpi-card[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .kpi-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .compare-summary[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .analytics-table-wrapper[_ngcontent-%COMP%], \n .compare-table-wrapper[_ngcontent-%COMP%] {\n margin: 0 -20px;\n padding: 0 20px;\n }\n\n .run-selector-list[_ngcontent-%COMP%] {\n max-height: 150px;\n }\n}\n\n@media (max-width: 480px) {\n .compare-summary[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .compare-summary-card[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .analytics-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .analytics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%], \n .compare-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .compare-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-size: 12px;\n }\n}\n\n\n\n\n\n\n\n\n.cell-human[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-human.no-feedback[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-human.no-feedback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] .rating-value[_ngcontent-%COMP%] {\n font-weight: 700;\n font-size: 11px;\n}\n\n\n\n.cell-human.rating-low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-human.rating-medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-human.rating-good[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-human.rating-excellent[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n\n\n.cell-auto[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-auto.no-score[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-auto.no-score[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] .score-value[_ngcontent-%COMP%] {\n font-weight: 700;\n font-size: 10px;\n}\n\n\n\n.cell-auto.score-low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-auto.score-medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.score-good[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.score-excellent[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n\n\n.cell-status[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-timeout[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped[_ngcontent-%COMP%], \n.cell-status.status-pending[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n\n\n.result-cell.cell-not-run[_ngcontent-%COMP%] {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--mj-text-disabled);\n}\n\n.result-cell.cell-not-run[_ngcontent-%COMP%] .cell-eval-stack[_ngcontent-%COMP%] {\n opacity: 0.6;\n}\n\n.cell-not-run-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n color: var(--mj-text-disabled);\n font-size: 11px;\n}\n\n\n\n\n\n.test-matrix[_ngcontent-%COMP%] tfoot[_ngcontent-%COMP%] {\n position: sticky;\n bottom: 0;\n z-index: 2;\n}\n\n.totals-row[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-top: 2px solid var(--test-border);\n}\n\n.totals-row[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-weight: 600;\n}\n\n.totals-row[_ngcontent-%COMP%] .totals-label[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n font-size: 12px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.totals-row[_ngcontent-%COMP%] .totals-cell[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n}\n\n.totals-stack[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.totals-status[_ngcontent-%COMP%], \n.totals-human[_ngcontent-%COMP%], \n.totals-auto[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.totals-status[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.totals-status[_ngcontent-%COMP%] .pass-count[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-human[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.totals-human[_ngcontent-%COMP%] .avg-label[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-human[_ngcontent-%COMP%] .count-label[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.8;\n}\n\n.totals-auto[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.totals-auto[_ngcontent-%COMP%] .avg-label[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-auto[_ngcontent-%COMP%] .count-label[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.8;\n}\n\n\n\n\n\n\n.edit-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.edit-section-header[_ngcontent-%COMP%] {\n margin: 0 0 18px 0;\n}\n\n.edit-section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.edit-section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.edit-section-sub[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.edit-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 18px;\n}\n\n@media (max-width: 720px) {\n .edit-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}\n\n.edit-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.edit-field--full[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n}\n\n.edit-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.edit-field[_ngcontent-%COMP%] .required[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n margin-left: 2px;\n}\n\n.config-textarea[_ngcontent-%COMP%] {\n resize: vertical;\n min-height: 72px;\n font-family: inherit;\n line-height: 1.5;\n}\n\n.select-wrapper[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.select-wrapper[_ngcontent-%COMP%] select.config-input[_ngcontent-%COMP%] {\n padding-right: 36px;\n appearance: none;\n background-color: var(--test-surface);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%2364748b' d='M1.41 0L6 4.59 10.59 0 12 1.41l-6 6-6-6z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 14px center;\n background-size: 10px 7px;\n}\n\n\n\n.tag-editor[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 8px 10px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n transition: var(--test-transition);\n cursor: text;\n min-height: 42px;\n align-items: center;\n}\n\n.tag-editor[_ngcontent-%COMP%]:focus-within {\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.tag-chip-editable[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 4px 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n border-radius: 999px;\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.tag-chip-editable[_ngcontent-%COMP%] .tag-remove[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: 10px;\n transition: background 0.15s;\n}\n\n.tag-chip-editable[_ngcontent-%COMP%] .tag-remove[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-input-inline[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 140px;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: var(--test-text);\n padding: 4px 2px;\n}\n\n.tag-input-inline[_ngcontent-%COMP%]::placeholder {\n color: var(--test-text-muted);\n}\n\n\n\n.meta-section[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--test-radius-md);\n padding: 14px 18px;\n border: 1px solid var(--test-border);\n}\n\n.meta-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 14px;\n}\n\n.meta-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.meta-label[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.meta-value[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.meta-mono[_ngcontent-%COMP%] {\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n font-size: 11px;\n}\n\n\n\n.dirty-indicator[_ngcontent-%COMP%] {\n display: inline-block;\n margin-left: 8px;\n font-size: 14px;\n color: var(--mj-status-warning);\n line-height: 1;\n animation: _ngcontent-%COMP%_pulseDot 1.8s ease-in-out infinite;\n vertical-align: middle;\n}\n\n@keyframes _ngcontent-%COMP%_pulseDot {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.85); }\n}\n\n.unsaved-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n}\n\n.unsaved-pill[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 6px;\n animation: _ngcontent-%COMP%_pulseDot 1.8s ease-in-out infinite;\n}\n\n\n\n\n.tab-content.has-savebar[_ngcontent-%COMP%] {\n padding-bottom: 84px;\n}\n\n\n\n\n\n\n.save-bar[_ngcontent-%COMP%] {\n position: absolute;\n left: 16px;\n right: 96px; \n\n bottom: 16px;\n z-index: 50;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 12px 16px 12px 20px;\n background: var(--mj-bg-surface-elevated, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--test-border));\n border-radius: 14px;\n box-shadow: 0 12px 32px color-mix(in srgb, var(--mj-status-warning) 10%, rgba(15, 23, 42, 0.18));\n backdrop-filter: blur(8px);\n \n\n\n\n opacity: 0;\n transform: translateY(calc(100% + 32px));\n pointer-events: none;\n transition:\n transform 420ms cubic-bezier(0.16, 1, 0.3, 1),\n opacity 260ms cubic-bezier(0.16, 1, 0.3, 1);\n will-change: transform, opacity;\n}\n\n.save-bar--visible[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .save-bar[_ngcontent-%COMP%] {\n transition: opacity 180ms ease-out;\n transform: none;\n }\n .save-bar--visible[_ngcontent-%COMP%] {\n transform: none;\n }\n}\n\n.save-bar-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.save-bar-dot[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 12px;\n line-height: 1;\n animation: _ngcontent-%COMP%_pulseDot 1.8s ease-in-out infinite;\n}\n\n.save-bar-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.save-bar-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.save-bar-fields[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.save-bar-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.save-bar-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n transition: var(--test-transition);\n font-family: inherit;\n}\n\n.save-bar-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.save-bar-btn--primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n}\n\n.save-bar-btn--primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 45%, transparent);\n}\n\n.save-bar-btn--primary[_ngcontent-%COMP%]:active:not(:disabled) {\n transform: translateY(0);\n}\n\n.save-bar-btn--ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.save-bar-btn--ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n border-color: var(--test-text-muted);\n}\n\n.save-bar-kbd[_ngcontent-%COMP%] {\n display: inline-flex;\n gap: 3px;\n margin-left: 6px;\n opacity: 0.85;\n}\n\n.save-bar-kbd[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n font-size: 10px;\n font-weight: 600;\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n background: color-mix(in srgb, white 18%, transparent);\n border: 1px solid color-mix(in srgb, white 35%, transparent);\n border-radius: 4px;\n color: inherit;\n}\n\n@media (max-width: 640px) {\n .save-bar[_ngcontent-%COMP%] {\n left: 8px;\n right: 8px;\n bottom: 88px; \n\n flex-direction: column;\n align-items: stretch;\n padding: 12px;\n }\n .save-bar-actions[_ngcontent-%COMP%] {\n justify-content: space-between;\n }\n .save-bar-kbd[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n\n\n\n\n\n.tests-actionbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n}\n\n.tests-actionbar-text[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n min-width: 0;\n}\n\n.tests-actionbar-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.tests-actionbar-count[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 8px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n font-size: 12px;\n font-weight: 700;\n}\n\n.tests-actionbar-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.tests-actionbar-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n\n\n.tests-list[cdk-drop-list][_ngcontent-%COMP%] .test-item[_ngcontent-%COMP%]:hover, \n.tests-list[_ngcontent-%COMP%] .test-item.cdk-drag[_ngcontent-%COMP%]:hover {\n transform: none;\n}\n\n\n\n.test-item.cdk-drag[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.test-item[_ngcontent-%COMP%] .test-content[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n\n\n.test-drag-handle[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 28px;\n border-radius: 4px;\n color: var(--test-text-muted);\n cursor: grab;\n flex-shrink: 0;\n transition: background 0.15s, color 0.15s;\n user-select: none;\n}\n\n.test-drag-handle[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n}\n\n.test-drag-handle[_ngcontent-%COMP%]:active, \n.cdk-drag-preview[_ngcontent-%COMP%] .test-drag-handle[_ngcontent-%COMP%] {\n cursor: grabbing;\n}\n\n\n\n.test-remove-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 0.15s, background 0.15s, color 0.15s;\n}\n\n.test-item[_ngcontent-%COMP%]:hover .test-remove-btn[_ngcontent-%COMP%], \n.test-remove-btn[_ngcontent-%COMP%]:focus-visible {\n opacity: 1;\n}\n\n.test-remove-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n color: var(--mj-status-error);\n}\n\n.test-chevron[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n\n\n.test-remove-confirm[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 4px 8px 4px 12px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n flex-shrink: 0;\n}\n\n.test-remove-confirm-text[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-error-text, var(--mj-status-error));\n}\n\n.test-remove-confirm-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 4px 10px;\n border-radius: 6px;\n border: 1px solid transparent;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.test-remove-confirm-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.test-remove-confirm-btn--danger[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse, white);\n}\n\n.test-remove-confirm-btn--danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 88%, black);\n}\n\n.test-remove-confirm-btn--ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.test-remove-confirm-btn--ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n\n\n.cdk-drag-preview[_ngcontent-%COMP%] {\n box-shadow: 0 12px 32px rgba(15, 23, 42, 0.25);\n border-radius: var(--test-radius-md);\n background: var(--test-surface);\n opacity: 0.95;\n}\n\n.cdk-drag-placeholder[_ngcontent-%COMP%] {\n opacity: 0;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border: 2px dashed var(--test-primary);\n border-radius: var(--test-radius-md);\n}\n\n.cdk-drag-placeholder[_ngcontent-%COMP%] *[_ngcontent-%COMP%] {\n visibility: hidden;\n}\n\n.cdk-drag-animating[_ngcontent-%COMP%] {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.tests-list.cdk-drop-list-dragging[_ngcontent-%COMP%] .test-item[_ngcontent-%COMP%]:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n\n\n\n\n\n.picker-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: rgba(15, 23, 42, 0.45);\n z-index: 200;\n animation: _ngcontent-%COMP%_pickerFadeIn 180ms ease-out;\n backdrop-filter: blur(2px);\n}\n\n@keyframes _ngcontent-%COMP%_pickerFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.picker-dialog[_ngcontent-%COMP%] {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: min(720px, calc(100vw - 32px));\n max-height: min(80vh, 720px);\n z-index: 201;\n display: flex;\n flex-direction: column;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n box-shadow: 0 24px 64px rgba(15, 23, 42, 0.28);\n animation: _ngcontent-%COMP%_pickerSlideUp 220ms cubic-bezier(0.16, 1, 0.3, 1);\n overflow: hidden;\n}\n\n@keyframes _ngcontent-%COMP%_pickerSlideUp {\n from {\n opacity: 0;\n transform: translate(-50%, calc(-50% + 16px));\n }\n to {\n opacity: 1;\n transform: translate(-50%, -50%);\n }\n}\n\n.picker-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.picker-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.picker-close[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 14px;\n transition: background 0.15s, color 0.15s;\n}\n\n.picker-close[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-close[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.picker-search[_ngcontent-%COMP%] {\n position: relative;\n padding: 14px 20px 0 20px;\n}\n\n.picker-search-icon[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 32px;\n transform: translateY(-30%);\n color: var(--test-text-muted);\n font-size: 13px;\n pointer-events: none;\n}\n\n.picker-search-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 10px 36px 10px 36px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n font-size: 14px;\n color: var(--test-text);\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-search-clear[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n right: 32px;\n transform: translateY(-30%);\n width: 22px;\n height: 22px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 11px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.picker-search-clear[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-toolbar-status[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.picker-toolbar-status[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary-hover);\n font-weight: 700;\n}\n\n.picker-toolbar-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 14px;\n}\n\n.picker-link-btn[_ngcontent-%COMP%] {\n border: none;\n background: transparent;\n color: var(--test-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n padding: 0;\n font-family: inherit;\n}\n\n.picker-link-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n text-decoration: underline;\n}\n\n.picker-link-btn[_ngcontent-%COMP%]:disabled {\n color: var(--test-text-muted);\n cursor: not-allowed;\n}\n\n.picker-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n min-height: 200px;\n}\n\n.picker-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.picker-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n padding: 40px 20px;\n color: var(--test-text-muted);\n}\n\n.picker-empty[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 14px;\n color: var(--test-text-muted);\n}\n\n.picker-empty[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 6px 0;\n font-size: 15px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.picker-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n}\n\n.picker-list[_ngcontent-%COMP%] {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.picker-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.12s, border-color 0.12s;\n border: 1px solid transparent;\n}\n\n.picker-row[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n}\n\n.picker-row[_ngcontent-%COMP%]:focus-visible {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-row--selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--test-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.picker-row--selected[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--test-surface));\n}\n\n.picker-check[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 1.5px solid var(--test-border);\n background: var(--test-surface);\n color: var(--mj-text-inverse, white);\n font-size: 11px;\n flex-shrink: 0;\n transition: background 0.12s, border-color 0.12s;\n}\n\n.picker-row--selected[_ngcontent-%COMP%] .picker-check[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-row-main[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.picker-row-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.picker-row-desc[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: 2px;\n}\n\n.picker-row-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.picker-row-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: 999px;\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-secondary);\n border: 1px solid var(--test-border);\n}\n\n.picker-row-pill--status[data-status=\"active\"][_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n}\n\n.picker-row-pill--status[data-status=\"disabled\"][_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-muted);\n}\n\n.picker-row-pill--status[data-status=\"pending\"][_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n}\n\n.picker-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--test-border);\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n}\n\n.picker-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.picker-btn--primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-btn--primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n}\n\n.picker-btn--ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.picker-btn--ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n@media (max-width: 640px) {\n .picker-dialog[_ngcontent-%COMP%] {\n width: calc(100vw - 16px);\n max-height: calc(100vh - 32px);\n }\n .tests-actionbar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n }\n .tests-actionbar-actions[_ngcontent-%COMP%] {\n justify-content: flex-end;\n }\n .test-remove-btn[_ngcontent-%COMP%] {\n opacity: 1; \n\n }\n}"], changeDetection: 0 }); }
|
|
3530
4386
|
};
|
|
3531
4387
|
MJTestSuiteFormComponentExtended = __decorate([
|
|
3532
4388
|
RegisterClass(BaseFormComponent, 'MJ: Test Suites')
|
|
@@ -3534,13 +4390,16 @@ MJTestSuiteFormComponentExtended = __decorate([
|
|
|
3534
4390
|
export { MJTestSuiteFormComponentExtended };
|
|
3535
4391
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJTestSuiteFormComponentExtended, [{
|
|
3536
4392
|
type: Component,
|
|
3537
|
-
args: [{ standalone: false, selector: 'mj-test-suite-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"test-suite-form\">\n <!-- Header Section -->\n <div class=\"suite-header\">\n <!-- Breadcrumb Navigation -->\n <nav class=\"breadcrumb\" aria-label=\"Breadcrumb\">\n <ol>\n <li>\n <a href=\"javascript:void(0)\" (click)=\"navigateToTestingDashboard()\">\n <i class=\"fas fa-vial\"></i>\n <span class=\"breadcrumb-text\">Testing</span>\n </a>\n </li>\n <li class=\"current\">\n <i class=\"fas fa-chevron-right separator\"></i>\n <i class=\"fas fa-layer-group\"></i>\n <span>{{ record.Name }}</span>\n </li>\n </ol>\n </nav>\n\n <div class=\"header-content\">\n <div class=\"header-left\">\n <div class=\"suite-icon\" [style.background-color]=\"getStatusColor()\">\n <i class=\"fas fa-layer-group\"></i>\n </div>\n <div class=\"suite-info\">\n <h1>{{ record.Name }}</h1>\n <div class=\"suite-meta\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass()\">\n <i class=\"fas\" [ngClass]=\"record.Status === 'Active' ? 'fa-circle-check' : 'fa-circle-pause'\"></i>\n {{ record.Status }}\n </span>\n @if (testsLoaded) {\n <span class=\"test-count\">\n <i class=\"fas fa-flask\"></i>\n {{ suiteTests.length }} tests\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"header-actions\">\n <app-evaluation-mode-toggle></app-evaluation-mode-toggle>\n <button mjButton (click)=\"exportToExcel()\" title=\"Export to CSV\">\n <i class=\"fas fa-file-excel\"></i> Export\n </button>\n <button mjButton (click)=\"runSuite()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Suite\n </button>\n <button mjButton (click)=\"refresh()\" [disabled]=\"isRefreshing\">\n <i class=\"fas\" [ngClass]=\"isRefreshing ? 'fa-sync fa-spin' : 'fa-sync'\"></i>\n {{ isRefreshing ? 'Refreshing...' : 'Refresh' }}\n </button>\n </div>\n </div>\n @if (record.Description) {\n <div class=\"suite-description\">\n <p>{{ record.Description }}</p>\n </div>\n }\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs-container\">\n <div class=\"tabs\" role=\"tablist\">\n <button class=\"tab\"\n [class.active]=\"activeTab === 'overview'\"\n (click)=\"changeTab('overview')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'overview'\">\n <i class=\"fas fa-th-large\"></i> Overview\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'tests'\"\n (click)=\"changeTab('tests')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'tests'\">\n <i class=\"fas fa-flask\"></i> Tests\n @if (testsLoaded) {\n <span class=\"tab-badge\">{{ suiteTests.length }}</span>\n }\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'runs'\"\n (click)=\"changeTab('runs')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'runs'\">\n <i class=\"fas fa-history\"></i> Runs\n @if (runsLoaded) {\n <span class=\"tab-badge\">{{ suiteRuns.length }}</span>\n }\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'analytics'\"\n (click)=\"changeTab('analytics')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'analytics'\">\n <i class=\"fas fa-chart-line\"></i> Analytics\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'compare'\"\n (click)=\"changeTab('compare')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'compare'\">\n <i class=\"fas fa-balance-scale\"></i> Compare\n </button>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tab-content\">\n <!-- Overview Tab -->\n @if (activeTab === 'overview') {\n <div class=\"overview-tab\">\n <div class=\"info-section\">\n <h3><i class=\"fas fa-info-circle\"></i> Suite Information</h3>\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <div class=\"info-label\">Name</div>\n <div class=\"info-value\">{{ record.Name }}</div>\n </div>\n <div class=\"info-item\">\n <div class=\"info-label\">Status</div>\n <div class=\"info-value\">\n <span class=\"status-badge-inline\" [ngClass]=\"getStatusClass()\">{{ record.Status }}</span>\n </div>\n </div>\n <div class=\"info-item\">\n <div class=\"info-label\">Created</div>\n <div class=\"info-value\">{{ record.__mj_CreatedAt | date:'medium' }}</div>\n </div>\n <div class=\"info-item\">\n <div class=\"info-label\">Updated</div>\n <div class=\"info-value\">{{ record.__mj_UpdatedAt | date:'medium' }}</div>\n </div>\n <div class=\"info-item\">\n <div class=\"info-label\">Max Execution Time</div>\n <div class=\"info-value\">{{ formatTimeout(record.MaxExecutionTimeMS) }}</div>\n </div>\n </div>\n </div>\n <div class=\"config-section\">\n <h3><i class=\"fas fa-cogs\"></i> Execution Settings</h3>\n <div class=\"config-grid\">\n <div class=\"config-item\">\n <label>Max Execution Time (ms)</label>\n <input type=\"number\" [(ngModel)]=\"record.MaxExecutionTimeMS\" class=\"config-input\" placeholder=\"Default: 300000 (5 min)\" />\n <span class=\"config-hint\">Default timeout for tests in this suite</span>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Tests Tab -->\n @if (activeTab === 'tests') {\n <div class=\"tests-tab\">\n <!-- Loading State -->\n @if (loadingTests) {\n <div class=\"loading-state\">\n <div class=\"skeleton-list\">\n @for (i of [1,2,3,4,5]; track i) {\n <div class=\"skeleton-card\">\n <div class=\"skeleton-sequence\"></div>\n <div class=\"skeleton-icon\"></div>\n <div class=\"skeleton-content\">\n <div class=\"skeleton-line wide\"></div>\n <div class=\"skeleton-line narrow\"></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Tests List -->\n @if (!loadingTests && suiteTests.length > 0) {\n <div class=\"tests-list\">\n @for (test of suiteTests; track test) {\n <div class=\"test-item\" (click)=\"openTest(test.TestID)\">\n <div class=\"test-sequence\">{{ test.Sequence }}</div>\n <div class=\"test-icon\"><i class=\"fas fa-flask\"></i></div>\n <div class=\"test-content\">\n <div class=\"test-name\">{{ test.Test }}</div>\n <div class=\"test-status\">\n @if (test.Status) {\n <span><i class=\"fas fa-info-circle\"></i> {{ test.Status }}</span>\n }\n </div>\n </div>\n <i class=\"fas fa-chevron-right\"></i>\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (testsLoaded && !loadingTests && suiteTests.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-flask\"></i>\n </div>\n <h4>No Tests in Suite</h4>\n <p>Add tests to this suite to start running them together.</p>\n </div>\n }\n </div>\n }\n\n <!-- Runs Tab -->\n @if (activeTab === 'runs') {\n <div class=\"runs-tab\">\n <!-- Loading State -->\n @if (loadingRuns) {\n <div class=\"loading-state\">\n <div class=\"skeleton-list\">\n @for (i of [1,2,3]; track i) {\n <div class=\"skeleton-card\">\n <div class=\"skeleton-icon\"></div>\n <div class=\"skeleton-content\">\n <div class=\"skeleton-line wide\"></div>\n <div class=\"skeleton-line narrow\"></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Runs List -->\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"runs-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-item\" (click)=\"openSuiteRun(run.ID)\">\n <div class=\"run-icon\" [style.background-color]=\"getRunStatusColor(run.Status)\">\n <i class=\"fas\"\n [class.fa-check]=\"run.Status === 'Completed'\"\n [class.fa-times]=\"run.Status === 'Failed'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"\n [class.fa-ban]=\"run.Status === 'Cancelled'\"></i>\n </div>\n <div class=\"run-content\">\n <div class=\"run-header\">\n <span class=\"run-id\">Run #{{ run.ID.substring(0, 8) }}</span>\n <span class=\"run-status\" [style.color]=\"getRunStatusColor(run.Status)\">{{ run.Status }}</span>\n </div>\n <div class=\"run-meta\">\n <span><i class=\"fas fa-calendar\"></i> {{ getRelativeTime(run.StartedAt) }}</span>\n @if (run.TotalTests) {\n <span>\n <i class=\"fas fa-check-circle\"></i> {{ run.PassedTests }}/{{ run.TotalTests }}\n ({{ getPassRate(run).toFixed(0) }}%)\n </span>\n }\n </div>\n <!-- Evaluation metrics row -->\n <div class=\"run-eval-metrics\">\n <!-- Status badge -->\n @if (evalPreferences.showExecution) {\n <span class=\"eval-metric status\" [class]=\"'status-' + run.Status.toLowerCase()\">\n <i class=\"fas\"\n [class.fa-circle-check]=\"run.Status === 'Completed'\"\n [class.fa-circle-xmark]=\"run.Status === 'Failed'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"\n [class.fa-ban]=\"run.Status === 'Cancelled'\"></i>\n </span>\n }\n <!-- Human score (placeholder - need avg from suite run) -->\n @if (evalPreferences.showHuman) {\n <span class=\"eval-metric human\" title=\"Human evaluation\">\n <i class=\"fas fa-user\"></i>\n <span class=\"eval-pending\"><i class=\"fas fa-clock\"></i></span>\n </span>\n }\n <!-- Auto score (pass rate as proxy) -->\n @if (evalPreferences.showAuto && run.TotalTests) {\n <span class=\"eval-metric auto\"\n [class.high]=\"getPassRate(run) >= 80\"\n [class.medium]=\"getPassRate(run) >= 50 && getPassRate(run) < 80\"\n [class.low]=\"getPassRate(run) < 50\"\n title=\"Auto score (pass rate)\">\n <i class=\"fas fa-robot\"></i>\n <span>{{ getPassRate(run).toFixed(0) }}%</span>\n </span>\n }\n </div>\n <!-- Tags display -->\n @if (getRunTags(run).length > 0) {\n <div class=\"run-tags\">\n @for (tag of getRunTags(run); track tag) {\n <span class=\"tag-chip\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n <i class=\"fas fa-chevron-right\"></i>\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (runsLoaded && !loadingRuns && suiteRuns.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-play-circle\"></i>\n </div>\n <h4>No Suite Runs Yet</h4>\n <p>Run this suite to see execution history and results here.</p>\n <button mjButton (click)=\"runSuite()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Suite Now\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Analytics Tab -->\n @if (activeTab === 'analytics') {\n <div class=\"analytics-tab\">\n <!-- Loading State -->\n @if (loadingAnalytics) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading analytics data...\"></mj-loading>\n </div>\n }\n @if (!loadingAnalytics && analyticsLoaded) {\n <!-- View Toggle Sub-nav -->\n <div class=\"analytics-subnav\">\n <div class=\"subnav-tabs\">\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'summary'\"\n (click)=\"setAnalyticsView('summary')\">\n <i class=\"fas fa-chart-bar\"></i>\n <span>Summary</span>\n </button>\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'matrix'\"\n (click)=\"setAnalyticsView('matrix')\">\n <i class=\"fas fa-th\"></i>\n <span>Matrix</span>\n </button>\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'chart'\"\n (click)=\"setAnalyticsView('chart')\">\n <i class=\"fas fa-project-diagram\"></i>\n <span>Chart</span>\n </button>\n </div>\n </div>\n <!-- Collapsible Filters (shared by both views) -->\n <div class=\"analytics-filters\" [class.collapsed]=\"filtersCollapsed\">\n <div class=\"filters-header\" (click)=\"toggleFilters()\">\n <span class=\"filters-title\">\n <i class=\"fas fa-filter\"></i>\n Filters\n @if (filtersCollapsed) {\n <span class=\"filter-summary\">\n {{ analyticsTimeRange === 'all' ? 'All Time' : analyticsTimeRange }}\n @if (selectedTags.length > 0) {\n <span> \u00B7 {{ selectedTags.length }} tags</span>\n }\n </span>\n }\n </span>\n <i class=\"fas\" [ngClass]=\"filtersCollapsed ? 'fa-chevron-down' : 'fa-chevron-up'\"></i>\n </div>\n @if (!filtersCollapsed) {\n <div class=\"filters-content\">\n <div class=\"filter-group\">\n <label>Time Range</label>\n <div class=\"filter-buttons\">\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '7d'\" (click)=\"setTimeRange('7d')\">7 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '30d'\" (click)=\"setTimeRange('30d')\">30 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '90d'\" (click)=\"setTimeRange('90d')\">90 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === 'all'\" (click)=\"setTimeRange('all')\">All Time</button>\n </div>\n </div>\n @if (uniqueTags.length > 0) {\n <div class=\"filter-group\">\n <label>Filter by Tag @if (selectedTags.length > 0) {\n <span class=\"filter-hint\">({{ selectedTags.length }} selected)</span>\n }</label>\n <div class=\"filter-buttons tag-filters\">\n <button class=\"filter-btn tag-btn all-tags-btn\"\n [class.active]=\"selectedTags.length === 0\"\n (click)=\"toggleTagFilter(null)\">\n <i class=\"fas fa-layer-group\"></i> All Tags\n </button>\n @for (tag of uniqueTags; track tag) {\n <button class=\"filter-btn tag-btn\"\n [class.active]=\"isTagSelected(tag)\"\n (click)=\"toggleTagFilter(tag)\">\n @if (isTagSelected(tag)) {\n <i class=\"fas fa-check\"></i>\n }\n {{ tag }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n <!-- Summary View -->\n @if (analyticsView === 'summary') {\n <!-- KPI Cards -->\n <div class=\"analytics-kpis\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\"><i class=\"fas fa-play-circle\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ getTotalRuns() }}</div>\n <div class=\"kpi-label\">Total Runs</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon success\"><i class=\"fas fa-check-circle\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ getAveragePassRate().toFixed(1) }}%</div>\n <div class=\"kpi-label\">Avg Pass Rate</div>\n <div class=\"kpi-trend\" [ngClass]=\"{'trend-up': getPassRateTrend().direction === 'up', 'trend-down': getPassRateTrend().direction === 'down'}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-up': getPassRateTrend().direction === 'up', 'fa-arrow-down': getPassRateTrend().direction === 'down', 'fa-minus': getPassRateTrend().direction === 'stable'}\"></i>\n {{ getPassRateTrend().value.toFixed(1) }}%\n </div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon info\"><i class=\"fas fa-clock\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatDuration(getAverageDuration()) }}</div>\n <div class=\"kpi-label\">Avg Duration</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon warning\"><i class=\"fas fa-dollar-sign\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatCost(getTotalCost()) }}</div>\n <div class=\"kpi-label\">Total Cost</div>\n </div>\n </div>\n </div>\n <!-- Runs Table -->\n <div class=\"analytics-table-section\">\n <h3><i class=\"fas fa-table\"></i> Run History</h3>\n <div class=\"analytics-table-wrapper\">\n <table class=\"analytics-table\">\n <thead>\n <tr>\n <th>Date</th>\n <th>Status</th>\n <th>Pass Rate</th>\n <th>Tests</th>\n <th>Duration</th>\n <th>Cost</th>\n <th>Tags</th>\n </tr>\n </thead>\n <tbody>\n @for (dp of getFilteredAnalyticsData(); track dp) {\n <tr (click)=\"openSuiteRun(dp.runId)\" class=\"clickable-row\">\n <td>{{ dp.date | date:'short' }}</td>\n <td>\n <span class=\"status-chip\" [ngClass]=\"'status-' + dp.status.toLowerCase()\">{{ dp.status }}</span>\n </td>\n <td>\n <div class=\"pass-rate-cell\">\n <div class=\"pass-rate-bar\" [style.width.%]=\"dp.passRate\" [ngClass]=\"{'high': dp.passRate >= 80, 'medium': dp.passRate >= 50 && dp.passRate < 80, 'low': dp.passRate < 50}\"></div>\n <span>{{ dp.passRate.toFixed(0) }}%</span>\n </div>\n </td>\n <td>{{ dp.passedTests }}/{{ dp.totalTests }}</td>\n <td>{{ formatDuration(dp.duration) }}</td>\n <td>{{ formatCost(dp.cost) }}</td>\n <td>\n <div class=\"tag-cell\">\n @for (tag of dp.tags.slice(0, 2); track tag) {\n <span class=\"tag-chip-table\">{{ tag }}</span>\n }\n @if (dp.tags.length > 2) {\n <span class=\"tag-more\">+{{ dp.tags.length - 2 }}</span>\n }\n </div>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n @if (getFilteredAnalyticsData().length === 0) {\n <div class=\"empty-state small\">\n <p>No runs match the current filters.</p>\n </div>\n }\n </div>\n }\n <!-- Matrix View -->\n @if (analyticsView === 'matrix') {\n <!-- Loading Matrix -->\n @if (loadingMatrix) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading test matrix...\"></mj-loading>\n </div>\n }\n <!-- Matrix Content -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length > 0) {\n <div class=\"matrix-section\">\n <div class=\"matrix-header\">\n <h3><i class=\"fas fa-th\"></i> Test Results Matrix</h3>\n <div class=\"matrix-header-right\">\n <div class=\"matrix-filter-input\">\n <i class=\"fas fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Filter tests...\"\n [value]=\"matrixTestFilter\"\n (input)=\"onMatrixFilterInput($event)\"\n class=\"filter-input\">\n @if (matrixTestFilter) {\n <button class=\"clear-filter-btn\" (click)=\"clearMatrixFilter()\" title=\"Clear filter\">\n <i class=\"fas fa-times\"></i>\n </button>\n }\n </div>\n <span class=\"matrix-run-count\">{{ matrixData.length }} runs \u00B7 {{ getUniqueTestsFromMatrix().length }} tests</span>\n <button mjButton (click)=\"exportMatrixToCSV()\" [disabled]=\"matrixData.length === 0\" title=\"Export matrix to CSV\">\n <i class=\"fas fa-download\"></i> Export\n </button>\n </div>\n </div>\n <div class=\"matrix-scroll-container\">\n <table class=\"test-matrix\">\n <thead>\n <tr>\n <th class=\"seq-header\" (click)=\"toggleMatrixSort('sequence')\" title=\"Sort by sequence\">\n #\n <i class=\"fas\" [ngClass]=\"matrixSortBy === 'sequence' ? (matrixSortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort'\"></i>\n </th>\n <th class=\"test-name-header\" (click)=\"toggleMatrixSort('name')\" title=\"Sort by name\">\n Test\n <i class=\"fas\" [ngClass]=\"matrixSortBy === 'name' ? (matrixSortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort'\"></i>\n </th>\n @for (run of matrixData; track run) {\n <th class=\"run-header\" (click)=\"openSuiteRun(run.runId)\" [title]=\"'Click to view suite run - ' + (run.date | date:'medium')\">\n <div class=\"run-header-content\">\n @if (run.tags.length > 0) {\n <div class=\"run-tags-header\">\n @for (tag of run.tags.slice(0, 2); track tag) {\n <span class=\"tag-chip-header\">{{ tag }}</span>\n }\n @if (run.tags.length > 2) {\n <span class=\"tag-more-header\">+{{ run.tags.length - 2 }}</span>\n }\n </div>\n }\n <div class=\"run-date\">{{ getRelativeTime(run.date) }}</div>\n <div class=\"run-pass-rate\" [ngClass]=\"{'high': run.passRate >= 80, 'medium': run.passRate >= 50 && run.passRate < 80, 'low': run.passRate < 50}\">\n {{ run.passRate.toFixed(0) }}%\n </div>\n </div>\n </th>\n }\n <th class=\"spacer-header\"></th>\n </tr>\n </thead>\n <tbody>\n @for (test of getUniqueTestsFromMatrix(); track test) {\n <tr\n [class.row-selected]=\"selectedMatrixTestId === test.testId\"\n (click)=\"selectMatrixRow(test.testId)\">\n <td class=\"seq-cell\">{{ test.sequence }}</td>\n <td class=\"test-name-cell\">\n <span class=\"test-name\" [title]=\"test.testName\">{{ test.testName }}</span>\n </td>\n @for (run of matrixData; track run) {\n <td class=\"result-cell\"\n [ngClass]=\"getMatrixCellClass(getTestResultForRun(run.runId, test.testId))\"\n [class.clickable]=\"getTestResultForRun(run.runId, test.testId)\"\n [class.cell-not-run]=\"!getTestResultForRun(run.runId, test.testId)\"\n [title]=\"getTestResultForRun(run.runId, test.testId)?.status + ' - Click to view test run' || 'Not Run'\"\n (click)=\"onMatrixCellClick(getTestResultForRun(run.runId, test.testId), $event)\">\n @if (getTestResultForRun(run.runId, test.testId); as result) {\n <div class=\"cell-eval-stack\">\n <!-- Status indicator -->\n @if (evalPreferences.showExecution) {\n <span class=\"cell-status\"\n [ngClass]=\"'status-' + result.status.toLowerCase()\"\n [class.cell-skipped-status]=\"result.status === 'Skipped' || result.status === 'Pending'\"\n [title]=\"getStatusTooltip(result.status)\">\n <i class=\"fas\"\n [class.fa-check]=\"result.status === 'Passed'\"\n [class.fa-times]=\"result.status === 'Failed'\"\n [class.fa-exclamation]=\"result.status === 'Error'\"\n [class.fa-hourglass-end]=\"result.status === 'Timeout'\"\n [class.fa-forward]=\"result.status === 'Skipped'\"\n [class.fa-spinner]=\"result.status === 'Running'\"\n [class.fa-clock]=\"result.status === 'Pending'\"></i>\n </span>\n }\n <!-- Human score - slashed icon if no feedback, colored by rating if has feedback -->\n @if (evalPreferences.showHuman && !result.humanRating) {\n <span class=\"cell-human no-feedback\"\n title=\"Human Review: No rating submitted yet\">\n <i class=\"fas fa-user-slash\"></i>\n </span>\n }\n @if (evalPreferences.showHuman && result.humanRating) {\n <span class=\"cell-human has-feedback\"\n [class.rating-low]=\"result.humanRating <= 4\"\n [class.rating-medium]=\"result.humanRating >= 5 && result.humanRating <= 6\"\n [class.rating-good]=\"result.humanRating >= 7 && result.humanRating <= 8\"\n [class.rating-excellent]=\"result.humanRating >= 9\"\n [title]=\"getHumanTooltip(result.humanRating, result.humanComments)\">\n <i class=\"fas fa-user\"></i>\n <span class=\"rating-value\">{{ result.humanRating }}</span>\n </span>\n }\n <!-- Auto score - colored by percentage -->\n @if (evalPreferences.showAuto && result.score != null) {\n <span class=\"cell-auto has-score\"\n [class.score-low]=\"result.score < 0.5\"\n [class.score-medium]=\"result.score >= 0.5 && result.score < 0.7\"\n [class.score-good]=\"result.score >= 0.7 && result.score < 0.85\"\n [class.score-excellent]=\"result.score >= 0.85\"\n [title]=\"'Auto Score: ' + (result.score * 100).toFixed(0) + '% automated evaluation'\">\n <i class=\"fas fa-robot\"></i>\n <span class=\"score-value\">{{ (result.score * 100).toFixed(0) }}</span>\n </span>\n }\n @if (evalPreferences.showAuto && result.score == null) {\n <span class=\"cell-auto no-score\"\n title=\"Auto Score: No automated score available\">\n <i class=\"fas fa-robot\"></i>\n </span>\n }\n </div>\n }\n @if (!getTestResultForRun(run.runId, test.testId)) {\n <span class=\"cell-not-run-indicator\">\n <i class=\"fas fa-minus\"></i>\n </span>\n }\n </td>\n }\n <td class=\"spacer-cell\"></td>\n </tr>\n }\n </tbody>\n <!-- Footer row with totals -->\n <tfoot>\n <tr class=\"totals-row\">\n <td class=\"seq-cell totals-label\"></td>\n <td class=\"test-name-cell totals-label\">\n <strong>Totals</strong>\n </td>\n @for (run of matrixData; track run) {\n <td class=\"result-cell totals-cell\">\n <div class=\"cell-eval-stack totals-stack\">\n <!-- Status totals -->\n @if (evalPreferences.showExecution) {\n <span class=\"totals-status\">\n <span class=\"pass-count\">{{ getRunPassedCount(run) }}/{{ getRunTotalCount(run) }}</span>\n </span>\n }\n <!-- Human totals -->\n @if (evalPreferences.showHuman) {\n <span class=\"totals-human\">\n @if (getRunHumanAvg(run) != null) {\n <span class=\"avg-label\">{{ getRunHumanAvg(run)?.toFixed(1) }}</span>\n }\n <span class=\"count-label\">({{ getRunHumanCount(run) }})</span>\n </span>\n }\n <!-- Auto totals -->\n @if (evalPreferences.showAuto) {\n <span class=\"totals-auto\">\n @if (getRunAutoAvg(run) != null) {\n <span class=\"avg-label\">{{ (getRunAutoAvg(run)! * 100).toFixed(0) }}%</span>\n }\n <span class=\"count-label\">({{ getRunAutoCount(run) }})</span>\n </span>\n }\n </div>\n </td>\n }\n <td class=\"spacer-cell\"></td>\n </tr>\n </tfoot>\n </table>\n </div>\n </div>\n }\n <!-- Empty Matrix State -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-th\"></i>\n </div>\n <h4>No Matrix Data</h4>\n <p>No suite runs match the current filters.</p>\n </div>\n }\n }\n <!-- Chart View -->\n @if (analyticsView === 'chart') {\n <!-- Loading Chart -->\n @if (loadingMatrix) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading chart data...\"></mj-loading>\n </div>\n }\n <!-- Chart Content -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length > 0) {\n <div class=\"chart-section\">\n <div class=\"chart-header\">\n <h3><i class=\"fas fa-project-diagram\"></i> Test Results Flow</h3>\n <div class=\"chart-legend\">\n <span class=\"legend-item chart-passed\"><i class=\"fas fa-check\"></i> Passed</span>\n <span class=\"legend-item chart-failed\"><i class=\"fas fa-times\"></i> Failed</span>\n <span class=\"legend-item chart-error\"><i class=\"fas fa-exclamation\"></i> Error</span>\n <span class=\"legend-item chart-skipped\"><i class=\"fas fa-forward\"></i> Skipped</span>\n </div>\n </div>\n <div class=\"chart-container\">\n <div #chartContainer class=\"d3-chart\"></div>\n </div>\n <div class=\"chart-info\">\n <i class=\"fas fa-info-circle\"></i>\n Interactive visualization showing test results across {{ matrixData.length }} runs.\n Hover over elements for details, click nodes to navigate.\n </div>\n </div>\n }\n <!-- Empty Chart State -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-project-diagram\"></i>\n </div>\n <h4>No Chart Data</h4>\n <p>No suite runs match the current filters.</p>\n </div>\n }\n }\n }\n <!-- Empty State -->\n @if (!loadingAnalytics && analyticsLoaded && analyticsData.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-chart-line\"></i>\n </div>\n <h4>No Analytics Data</h4>\n <p>Run this suite to start collecting analytics data.</p>\n <button mjButton (click)=\"runSuite()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Suite Now\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Compare Tab -->\n @if (activeTab === 'compare') {\n <div class=\"compare-tab\">\n <!-- Run Selection -->\n <div class=\"compare-selection\">\n <div class=\"compare-run-selector\">\n <h4>Run A (Baseline)</h4>\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"run-selector-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-selector-item\"\n [class.selected]=\"IsCompareRunA(run)\"\n (click)=\"selectCompareRunA(run)\">\n <div class=\"selector-status\" [style.background-color]=\"getRunStatusColor(run.Status)\"></div>\n <div class=\"selector-content\">\n <div class=\"selector-date\">{{ run.StartedAt | date:'short' }}</div>\n <div class=\"selector-rate\">{{ getPassRate(run).toFixed(0) }}% pass</div>\n </div>\n @if (getRunTags(run).length > 0) {\n <div class=\"selector-tags\">\n @for (tag of getRunTags(run).slice(0, 2); track tag) {\n <span class=\"tag-mini\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (compareRunA) {\n <div class=\"selected-run-preview\">\n <div class=\"preview-header\">\n <span class=\"preview-label\">Selected:</span>\n <button class=\"clear-btn\" (click)=\"compareRunA = null; compareResults = []\">Clear</button>\n </div>\n <div class=\"preview-details\">\n <span>{{ compareRunA.StartedAt | date:'medium' }}</span>\n <span class=\"preview-rate\">{{ getPassRate(compareRunA).toFixed(1) }}%</span>\n </div>\n </div>\n }\n </div>\n <div class=\"compare-vs\"><i class=\"fas fa-exchange-alt\"></i></div>\n <div class=\"compare-run-selector\">\n <h4>Run B (Compare)</h4>\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"run-selector-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-selector-item\"\n [class.selected]=\"IsCompareRunB(run)\"\n [class.disabled]=\"IsCompareRunA(run)\"\n (click)=\"!IsCompareRunA(run) && selectCompareRunB(run)\">\n <div class=\"selector-status\" [style.background-color]=\"getRunStatusColor(run.Status)\"></div>\n <div class=\"selector-content\">\n <div class=\"selector-date\">{{ run.StartedAt | date:'short' }}</div>\n <div class=\"selector-rate\">{{ getPassRate(run).toFixed(0) }}% pass</div>\n </div>\n @if (getRunTags(run).length > 0) {\n <div class=\"selector-tags\">\n @for (tag of getRunTags(run).slice(0, 2); track tag) {\n <span class=\"tag-mini\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (compareRunB) {\n <div class=\"selected-run-preview\">\n <div class=\"preview-header\">\n <span class=\"preview-label\">Selected:</span>\n <button class=\"clear-btn\" (click)=\"compareRunB = null; compareResults = []\">Clear</button>\n </div>\n <div class=\"preview-details\">\n <span>{{ compareRunB.StartedAt | date:'medium' }}</span>\n <span class=\"preview-rate\">{{ getPassRate(compareRunB).toFixed(1) }}%</span>\n </div>\n </div>\n }\n </div>\n </div>\n <!-- Comparison Results -->\n @if (compareRunA && compareRunB && !loadingCompare) {\n <div class=\"compare-results\">\n <!-- Summary Cards -->\n <div class=\"compare-summary\">\n <div class=\"compare-summary-card\">\n <div class=\"summary-label\">Pass Rate Change</div>\n <div class=\"summary-value\" [ngClass]=\"{'positive': getComparePassRateDiff()! > 0, 'negative': getComparePassRateDiff()! < 0}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-up': getComparePassRateDiff()! > 0, 'fa-arrow-down': getComparePassRateDiff()! < 0, 'fa-minus': getComparePassRateDiff() === 0}\"></i>\n {{ getComparePassRateDiff()! > 0 ? '+' : '' }}{{ getComparePassRateDiff()?.toFixed(1) }}%\n </div>\n </div>\n <div class=\"compare-summary-card\">\n <div class=\"summary-label\">Duration Change</div>\n <div class=\"summary-value\" [ngClass]=\"{'positive': getCompareDurationDiff()! < 0, 'negative': getCompareDurationDiff()! > 0}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-down': getCompareDurationDiff()! < 0, 'fa-arrow-up': getCompareDurationDiff()! > 0, 'fa-minus': getCompareDurationDiff() === 0}\"></i>\n {{ formatDuration(getAbsCompareDurationDiff()) }}\n </div>\n </div>\n <div class=\"compare-summary-card improved\">\n <div class=\"summary-label\">Improved</div>\n <div class=\"summary-value\">{{ getCompareImprovedCount() }}</div>\n </div>\n <div class=\"compare-summary-card regressed\">\n <div class=\"summary-label\">Regressed</div>\n <div class=\"summary-value\">{{ getCompareRegressedCount() }}</div>\n </div>\n </div>\n <!-- Detailed Comparison Table -->\n <div class=\"compare-table-section\">\n <h3><i class=\"fas fa-list\"></i> Test-by-Test Comparison</h3>\n <div class=\"compare-table-wrapper\">\n <table class=\"compare-table\">\n <thead>\n <tr>\n <th>Test</th>\n <th>Run A Status</th>\n <th>Run B Status</th>\n <th>Score Diff</th>\n <th>Duration Diff</th>\n <th>Change</th>\n </tr>\n </thead>\n <tbody>\n @for (result of compareResults; track result) {\n <tr [ngClass]=\"{'improved': result.runA && result.runB && result.runA.status !== 'Passed' && result.runB.status === 'Passed', 'regressed': result.runA && result.runB && result.runA.status === 'Passed' && result.runB.status !== 'Passed'}\">\n <td class=\"test-name-cell\">{{ result.testName }}</td>\n <td>\n @if (result.runA) {\n <span class=\"status-chip\" [ngClass]=\"'status-' + result.runA.status.toLowerCase()\">{{ result.runA.status }}</span>\n }\n @if (!result.runA) {\n <span class=\"status-chip status-missing\">N/A</span>\n }\n </td>\n <td>\n @if (result.runB) {\n <span class=\"status-chip\" [ngClass]=\"'status-' + result.runB.status.toLowerCase()\">{{ result.runB.status }}</span>\n }\n @if (!result.runB) {\n <span class=\"status-chip status-missing\">N/A</span>\n }\n </td>\n <td>\n @if (result.scoreDiff != null) {\n <span [ngClass]=\"{'positive': result.scoreDiff > 0, 'negative': result.scoreDiff < 0}\">\n {{ result.scoreDiff > 0 ? '+' : '' }}{{ (result.scoreDiff * 100).toFixed(1) }}%\n </span>\n }\n @if (result.scoreDiff == null) {\n <span class=\"muted\">-</span>\n }\n </td>\n <td>\n @if (result.durationDiff != null) {\n <span [ngClass]=\"{'positive': result.durationDiff < 0, 'negative': result.durationDiff > 0}\">\n {{ result.durationDiff > 0 ? '+' : '' }}{{ result.durationDiff.toFixed(1) }}s\n </span>\n }\n @if (result.durationDiff == null) {\n <span class=\"muted\">-</span>\n }\n </td>\n <td>\n @if (result.runA && result.runB && result.runA.status !== 'Passed' && result.runB.status === 'Passed') {\n <span class=\"change-indicator improved\">\n <i class=\"fas fa-arrow-up\"></i> Fixed\n </span>\n }\n @if (result.runA && result.runB && result.runA.status === 'Passed' && result.runB.status !== 'Passed') {\n <span class=\"change-indicator regressed\">\n <i class=\"fas fa-arrow-down\"></i> Broke\n </span>\n }\n @if (!result.statusChanged) {\n <span class=\"change-indicator unchanged\">\n <i class=\"fas fa-minus\"></i>\n </span>\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </div>\n }\n <!-- Loading State for Compare -->\n @if (loadingCompare) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading comparison data...\"></mj-loading>\n </div>\n }\n <!-- Empty State -->\n @if (!compareRunA || !compareRunB) {\n <div class=\"compare-empty\">\n <div class=\"compare-empty-icon\">\n <i class=\"fas fa-balance-scale\"></i>\n </div>\n <h4>Select Two Runs to Compare</h4>\n <p>Choose a baseline run (A) and a comparison run (B) from the lists above to see a detailed side-by-side comparison.</p>\n </div>\n }\n <!-- No Runs State -->\n @if (runsLoaded && suiteRuns.length < 2) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-balance-scale\"></i>\n </div>\n <h4>Not Enough Runs to Compare</h4>\n <p>You need at least 2 suite runs to use the comparison feature.</p>\n <button mjButton (click)=\"runSuite()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Suite Now\n </button>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Keyboard Shortcuts Toggle Button -->\n <button class=\"shortcuts-toggle\" (click)=\"toggleShortcuts()\" [title]=\"showShortcuts ? 'Hide keyboard shortcuts' : 'Show keyboard shortcuts'\">\n <i class=\"fas fa-keyboard\"></i>\n </button>\n\n <!-- Keyboard Shortcuts Hint (Desktop Only) -->\n @if (showShortcuts) {\n <div class=\"keyboard-shortcuts\">\n <div class=\"shortcuts-header\">\n <i class=\"fas fa-keyboard\"></i>\n Shortcuts\n <button class=\"shortcuts-close\" (click)=\"toggleShortcuts()\" title=\"Hide shortcuts\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n <div class=\"shortcut-list\">\n <div class=\"shortcut-item\">\n <span>Refresh</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>R</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Run Suite</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>Enter</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Switch Tabs</span>\n <span class=\"shortcut-keys\"><kbd>1</kbd>-<kbd>5</kbd></span>\n </div>\n </div>\n </div>\n }\n\n <!-- Slide Panel for Suite Execution -->\n @if (testingDialogService.IsPanelOpen) {\n <mj-slide-panel\n Mode=\"slide\"\n [Title]=\"testingDialogService.PanelOptions?.suiteId ? 'Suite Execution' : 'Run Suite'\"\n [Resizable]=\"true\"\n (Closed)=\"OnPanelClosed()\">\n <app-test-run-dialog\n [PanelMode]=\"true\"\n [selectedTestId]=\"testingDialogService.PanelOptions?.testId ?? null\"\n [selectedSuiteId]=\"testingDialogService.PanelOptions?.suiteId ?? null\"\n [runMode]=\"testingDialogService.PanelOptions?.mode ?? 'suite'\"\n (PanelClose)=\"OnPanelClosed()\">\n </app-test-run-dialog>\n </mj-slide-panel>\n }\n</div>\n", styles: ["/* ===========================\n Test Suite Form - World-Class UX\n =========================== */\n\n/* CSS Custom Properties for Theming - using :host for Angular encapsulation */\n:host {\n --test-primary: var(--mj-brand-primary);\n --test-primary-light: var(--mj-brand-primary);\n --test-success: var(--mj-status-success);\n --test-error: var(--mj-status-error);\n --test-warning: var(--mj-status-warning);\n --test-disabled: var(--mj-text-muted);\n --test-bg: var(--mj-bg-surface-card);\n --test-surface: var(--mj-bg-surface);\n --test-border: var(--mj-border-default);\n --test-text: var(--mj-text-primary);\n --test-text-secondary: var(--mj-text-secondary);\n --test-text-muted: var(--mj-text-disabled);\n --test-radius-sm: 6px;\n --test-radius-md: 10px;\n --test-radius-lg: 16px;\n --test-shadow-sm: var(--mj-shadow-sm);\n --test-shadow-md: var(--mj-shadow-md);\n --test-shadow-lg: var(--mj-shadow-lg);\n --test-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: block;\n height: 100%;\n}\n\n.test-suite-form {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--test-bg);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n/* Breadcrumb */\n.breadcrumb {\n margin-bottom: 16px;\n}\n\n.breadcrumb ol {\n display: flex;\n align-items: center;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n font-size: 13px;\n}\n\n.breadcrumb li {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.breadcrumb a {\n color: var(--test-primary);\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 6px;\n transition: background 0.15s;\n}\n\n.breadcrumb a:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n text-decoration: none;\n}\n\n.breadcrumb .separator {\n font-size: 10px;\n color: var(--test-text-muted);\n margin: 0 4px;\n}\n\n.breadcrumb .current {\n color: var(--test-text-secondary);\n font-weight: 500;\n}\n\n.breadcrumb-text {\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Header */\n.suite-header {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n padding: 20px;\n}\n\n.header-content {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 16px;\n gap: 16px;\n}\n\n.header-left {\n display: flex;\n gap: 16px;\n flex: 1;\n min-width: 0;\n}\n\n.suite-icon {\n width: 56px;\n height: 56px;\n border-radius: var(--test-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-size: 24px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.suite-icon:hover { transform: scale(1.05); }\n\n.suite-info { flex: 1; min-width: 0; }\n\n.suite-info h1 {\n margin: 0 0 8px 0;\n font-size: clamp(18px, 4vw, 24px);\n font-weight: 700;\n color: var(--test-text);\n word-wrap: break-word;\n}\n\n.suite-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: 20px;\n color: var(--mj-text-inverse);\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-active { background: var(--test-success); }\n.status-badge.status-disabled { background: var(--test-disabled); }\n.status-badge.status-pending { background: var(--test-warning); }\n\n.status-badge-inline {\n display: inline-flex;\n padding: 2px 10px;\n border-radius: 10px;\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n}\n\n.status-badge-inline.status-active { background: var(--test-success); }\n.status-badge-inline.status-disabled { background: var(--test-disabled); }\n.status-badge-inline.status-pending { background: var(--test-warning); }\n\n.test-count {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n color: var(--test-text-secondary);\n padding: 4px 10px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.suite-description {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.suite-description p {\n margin: 0;\n color: var(--test-text-secondary);\n line-height: 1.6;\n font-size: 14px;\n}\n\n/* Tabs */\n.tabs-container {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n\n.tabs {\n display: flex;\n padding: 0 20px;\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.tabs::-webkit-scrollbar { display: none; }\n\n.tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 18px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: var(--test-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n white-space: nowrap;\n}\n\n.tab:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.tab.active {\n color: var(--test-primary);\n border-bottom-color: var(--test-primary);\n font-weight: 600;\n}\n\n.tab-badge {\n background: var(--test-border);\n color: var(--test-text-secondary);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active .tab-badge {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--test-primary);\n}\n\n.tab-shortcut {\n font-size: 10px;\n color: var(--test-text-muted);\n background: var(--test-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n/* Tab Content */\n.tab-content {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n/* Overview Tab */\n.overview-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: fadeIn 0.3s ease-out;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; transform: translateY(10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.info-section, .config-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.info-section h3, .config-section h3 {\n margin: 0 0 20px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.info-section h3 i, .config-section h3 i {\n color: var(--test-primary);\n}\n\n.info-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n.info-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.info-value {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 500;\n}\n\n.config-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.config-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.config-item label {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.config-input {\n padding: 10px 14px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.config-input:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.config-hint {\n font-size: 11px;\n color: var(--test-text-muted);\n}\n\n/* Tests Tab */\n.tests-tab, .runs-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n.loading-state { padding: 0; }\n\n.skeleton-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.skeleton-card {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.skeleton-sequence {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-icon {\n width: 40px;\n height: 40px;\n border-radius: var(--test-radius-md);\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.skeleton-line {\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-line.wide { width: 70%; }\n.skeleton-line.narrow { width: 40%; }\n\n@keyframes shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n.tests-list, .runs-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.test-item, .run-item {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.test-item:hover, .run-item:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n}\n\n.test-sequence {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n font-size: 14px;\n font-weight: 700;\n color: var(--test-text-secondary);\n flex-shrink: 0;\n}\n\n.test-icon, .run-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 18px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-sm);\n}\n\n.test-icon {\n background: var(--test-primary);\n}\n\n.test-content, .run-content { flex: 1; min-width: 0; }\n\n.test-name, .run-header {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-header {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.run-id { font-weight: 600; }\n\n.run-status {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.test-status, .run-meta {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.test-status span, .run-meta span {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.test-item > i, .run-item > i {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.test-item:hover > i, .run-item:hover > i {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n/* Empty States */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 24px;\n text-align: center;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n}\n\n.empty-icon {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n margin-bottom: 20px;\n}\n\n.empty-icon i {\n font-size: 36px;\n color: var(--test-text-muted);\n}\n\n.empty-state h4 {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.empty-state p {\n margin: 0 0 20px 0;\n font-size: 14px;\n color: var(--test-text-secondary);\n max-width: 300px;\n}\n\n/* Keyboard Shortcuts */\n/* Keyboard shortcuts toggle button - visible when shortcuts are hidden */\n.shortcuts-toggle {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n box-shadow: var(--test-shadow-md);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--test-text-secondary);\n font-size: 14px;\n z-index: 99;\n transition: var(--test-transition);\n opacity: 0.7;\n}\n\n.shortcuts-toggle:hover {\n opacity: 1;\n transform: scale(1.1);\n color: var(--test-primary);\n border-color: var(--test-primary);\n}\n\n.keyboard-shortcuts {\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 12px 16px;\n box-shadow: var(--test-shadow-lg);\n font-size: 12px;\n z-index: 100;\n max-width: 260px;\n}\n\n.shortcuts-header {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text);\n}\n\n.shortcuts-close {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--test-text-muted);\n font-size: 12px;\n padding: 2px 4px;\n border-radius: 4px;\n transition: var(--test-transition);\n}\n\n.shortcuts-close:hover {\n color: var(--test-text);\n background: var(--test-border);\n}\n\n.shortcut-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.shortcut-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n color: var(--test-text-secondary);\n}\n\n.shortcut-keys {\n display: flex;\n gap: 4px;\n}\n\n.shortcut-keys kbd {\n background: var(--test-bg);\n border: 1px solid var(--test-border);\n border-radius: 4px;\n padding: 2px 6px;\n font-size: 11px;\n color: var(--test-text);\n}\n\n/* Responsive */\n@media (max-width: 1024px) {\n .keyboard-shortcuts, .shortcuts-toggle { display: none; }\n}\n\n@media (max-width: 768px) {\n .suite-header { padding: 16px; }\n\n .header-content {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions button { flex: 1; }\n\n .tab-shortcut { display: none; }\n\n .info-grid { grid-template-columns: 1fr; }\n\n .test-item, .run-item { padding: 14px; }\n}\n\n@media (max-width: 480px) {\n .suite-icon {\n width: 40px;\n height: 40px;\n font-size: 18px;\n }\n\n .suite-info h1 { font-size: 16px; }\n\n .tab-badge { display: none; }\n\n .test-sequence { display: none; }\n}\n\n@media (hover: none) and (pointer: coarse) {\n .test-item:active, .run-item:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n transform: scale(0.98);\n }\n\n .tab { min-height: 48px; }\n .test-item, .run-item { min-height: 64px; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n@media print {\n .header-actions, .tabs-container, .keyboard-shortcuts {\n display: none !important;\n }\n}\n\n/* ===========================\n Tags UI\n =========================== */\n.run-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 8px;\n}\n\n.tag-chip {\n display: inline-flex;\n align-items: center;\n padding: 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-mini {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.tag-more {\n font-size: 10px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n/* Evaluation metrics row for Runs list */\n.run-eval-metrics {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n}\n\n.eval-metric {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.eval-metric.status {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-metric.status.status-completed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.eval-metric.status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.eval-metric.status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.status.status-pending {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-warning);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human .eval-pending {\n font-size: 9px;\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.auto.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n color: var(--mj-status-success);\n}\n\n.eval-metric.auto.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n color: var(--mj-status-error);\n}\n\n.tag-cell {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.tag-chip-table {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 80px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* ===========================\n Analytics Tab\n =========================== */\n.analytics-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n/* Collapsible filters */\n.analytics-filters {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n margin-bottom: 16px;\n box-shadow: var(--test-shadow-sm);\n overflow: hidden;\n}\n\n.analytics-filters.collapsed {\n margin-bottom: 12px;\n}\n\n.filters-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s ease;\n}\n\n.filters-header:hover {\n background: var(--test-bg);\n}\n\n.filters-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text-secondary);\n}\n\n.filters-title i {\n color: var(--test-primary);\n}\n\n.filter-summary {\n font-weight: 400;\n color: var(--test-text-muted);\n margin-left: 8px;\n}\n\n.filters-header > i {\n color: var(--test-text-muted);\n font-size: 12px;\n}\n\n.filters-content {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 16px 16px 16px;\n border-top: 1px solid var(--test-border);\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.filter-group label {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.filter-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.filter-btn {\n padding: 8px 16px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.filter-btn:hover {\n border-color: var(--test-primary);\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.filter-btn.active {\n background: var(--test-primary);\n border-color: var(--test-primary);\n color: var(--mj-text-inverse);\n}\n\n.filter-btn.tag-btn {\n padding: 6px 12px;\n font-size: 12px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.filter-btn.tag-btn i.fa-check {\n font-size: 10px;\n}\n\n.filter-btn.tag-btn.all-tags-btn {\n font-weight: 600;\n}\n\n.filter-btn.tag-btn.all-tags-btn i {\n font-size: 11px;\n}\n\n.filter-hint {\n font-weight: 400;\n font-size: 10px;\n color: var(--test-primary);\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-filters {\n max-height: 120px;\n overflow-y: auto;\n}\n\n/* KPI Cards */\n.analytics-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n gap: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.kpi-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.kpi-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: var(--test-radius-md);\n color: var(--test-primary);\n font-size: 20px;\n}\n\n.kpi-icon.success {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-icon.info {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.kpi-icon.warning {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n line-height: 1.2;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--test-text-secondary);\n margin-top: 2px;\n}\n\n.kpi-trend {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n font-weight: 600;\n margin-top: 4px;\n padding: 2px 8px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-secondary);\n}\n\n.kpi-trend.trend-up {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-trend.trend-down {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n/* Analytics Table */\n.analytics-table-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.analytics-table-section h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.analytics-table-section h3 i {\n color: var(--test-primary);\n}\n\n.analytics-table-wrapper {\n overflow-x: auto;\n margin: 0 -24px;\n padding: 0 24px;\n}\n\n.analytics-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.analytics-table th {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.analytics-table td {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.analytics-table tbody tr.clickable-row {\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.analytics-table tbody tr.clickable-row:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.status-chip {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-chip.status-completed { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-passed { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-failed { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--test-error); }\n.status-chip.status-error { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-running { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--test-primary); }\n.status-chip.status-pending { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-chip.status-cancelled { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n.status-chip.status-missing { background: var(--mj-bg-surface-sunken); color: var(--test-text-muted); }\n.status-chip.status-timeout { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-skipped { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n\n.pass-rate-cell {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 100px;\n}\n\n.pass-rate-bar {\n height: 6px;\n border-radius: 3px;\n background: var(--test-success);\n transition: width 0.3s ease;\n max-width: 60px;\n}\n\n.pass-rate-bar.medium { background: var(--test-warning); }\n.pass-rate-bar.low { background: var(--test-error); }\n\n/* Analytics Sub-navigation */\n.analytics-subnav {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 8px;\n margin-bottom: 20px;\n box-shadow: var(--test-shadow-sm);\n display: inline-flex;\n}\n\n.subnav-tabs {\n display: flex;\n gap: 4px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n}\n\n.subnav-tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border: none;\n border-radius: var(--test-radius-sm);\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.subnav-tab:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.subnav-tab.active {\n background: var(--test-surface);\n color: var(--test-primary);\n box-shadow: var(--test-shadow-sm);\n}\n\n.subnav-tab i {\n font-size: 14px;\n}\n\n/* Matrix View */\n.matrix-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 16px;\n box-shadow: var(--test-shadow-sm);\n display: flex;\n flex-direction: column;\n max-height: calc(100vh - 280px);\n min-height: 300px;\n}\n\n.matrix-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--test-border);\n flex-shrink: 0;\n}\n\n.matrix-header-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.matrix-header h3 {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.matrix-header h3 i {\n color: var(--test-primary);\n}\n\n.matrix-run-count {\n font-size: 12px;\n color: var(--test-text-muted);\n font-weight: 500;\n}\n\n/* Matrix filter input */\n.matrix-filter-input {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--test-border);\n border-radius: 6px;\n padding: 4px 10px;\n min-width: 180px;\n}\n\n.matrix-filter-input i.fa-search {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.matrix-filter-input .filter-input {\n border: none;\n background: transparent;\n outline: none;\n font-size: 12px;\n color: var(--test-text);\n width: 100%;\n}\n\n.matrix-filter-input .filter-input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.clear-filter-btn {\n border: none;\n background: none;\n padding: 2px 4px;\n cursor: pointer;\n color: var(--mj-text-disabled);\n font-size: 10px;\n border-radius: 3px;\n transition: all 0.15s ease;\n}\n\n.clear-filter-btn:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n}\n\n/* Scrollable matrix container with fixed height */\n.matrix-scroll-container {\n flex: 1;\n overflow: auto;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n}\n\n.test-matrix {\n display: table;\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.test-matrix thead {\n display: table-header-group;\n}\n\n.test-matrix thead tr {\n display: table-row;\n}\n\n.test-matrix tbody {\n display: table-row-group;\n}\n\n.test-matrix tbody tr {\n display: table-row;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.test-matrix tbody tr:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.test-matrix tbody tr.row-selected {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix tbody tr.row-selected td {\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.test-matrix tbody tr.row-selected .seq-cell,\n.test-matrix tbody tr.row-selected .test-name-cell {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix tfoot {\n display: table-footer-group;\n}\n\n.test-matrix th,\n.test-matrix td {\n display: table-cell;\n border: 1px solid var(--test-border);\n padding: 8px 12px;\n text-align: center;\n vertical-align: middle;\n}\n\n.test-matrix th {\n background: var(--test-bg);\n font-weight: 600;\n font-size: 11px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n position: sticky;\n top: 0;\n z-index: 10;\n border-bottom: 3px solid var(--mj-text-secondary) !important;\n}\n\n/* Sequence column - shared styles */\n.test-matrix .seq-header,\n.test-matrix .seq-cell {\n width: 36px;\n min-width: 36px;\n max-width: 36px;\n text-align: center;\n position: sticky;\n left: 0;\n font-size: 11px;\n color: var(--mj-text-muted);\n border-right: 1px solid var(--test-border);\n padding: 6px 4px !important;\n}\n\n/* Seq header - sticky top AND left, highest z-index */\n.test-matrix .seq-header {\n cursor: pointer;\n font-weight: 600;\n background: var(--test-bg);\n z-index: 12; /* Higher than other headers */\n top: 0;\n}\n\n/* Seq body cells - sticky left only, lower z-index */\n.test-matrix .seq-cell {\n background: var(--test-surface);\n z-index: 2;\n}\n\n.test-matrix .seq-header i {\n font-size: 9px;\n margin-left: 2px;\n opacity: 0.6;\n}\n\n.test-matrix .seq-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix .test-name-header {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-bg);\n z-index: 11;\n border-right: 2px solid var(--test-border);\n cursor: pointer;\n}\n\n.test-matrix .test-name-header i {\n font-size: 9px;\n margin-left: 4px;\n opacity: 0.6;\n}\n\n.test-matrix .test-name-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix .run-header {\n min-width: 120px;\n width: 120px;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n/* Spacer column absorbs extra width */\n.test-matrix .spacer-header,\n.test-matrix .spacer-cell {\n width: 100%;\n min-width: 20px;\n background: var(--test-bg);\n border: none;\n}\n\n.test-matrix .spacer-cell {\n background: var(--test-surface);\n}\n\n.test-matrix .run-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-header-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.run-date {\n font-size: 12px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-pass-rate {\n font-size: 11px;\n font-weight: 700;\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.run-pass-rate.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.run-pass-rate.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.run-pass-rate.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.run-tags {\n display: flex;\n gap: 4px;\n}\n\n.tag-tiny {\n font-size: 9px;\n padding: 2px 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--test-primary);\n border-radius: 8px;\n white-space: nowrap;\n max-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Matrix column header tags - emphasized */\n.run-tags-header {\n display: flex;\n flex-wrap: wrap;\n gap: 3px;\n justify-content: center;\n margin-bottom: 4px;\n}\n\n.tag-chip-header {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 70px;\n overflow: hidden;\n text-overflow: ellipsis;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-more-header {\n font-size: 9px;\n color: var(--test-text-secondary);\n padding: 2px 4px;\n}\n\n.test-matrix .test-name-cell {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-surface);\n z-index: 2;\n border-right: 2px solid var(--test-border);\n padding: 6px 10px !important;\n}\n\n.test-name {\n display: block;\n white-space: nowrap;\n font-weight: 500;\n color: var(--test-text);\n font-size: 12px;\n}\n\n.result-cell {\n position: relative;\n min-width: 120px;\n width: 120px;\n transition: var(--test-transition);\n}\n\n.result-cell.clickable {\n cursor: pointer;\n}\n\n.result-cell.clickable:hover {\n transform: scale(1.1);\n box-shadow: var(--mj-shadow-md);\n z-index: 5;\n}\n\n.result-cell i {\n font-size: 14px;\n}\n\n/* Completed cells have neutral white background - pills tell the story */\n.result-cell.cell-passed,\n.result-cell.cell-failed,\n.result-cell.cell-error,\n.result-cell.cell-timeout,\n.result-cell.cell-running,\n.result-cell.cell-pending {\n background: var(--mj-bg-surface);\n color: var(--test-text);\n}\n\n/* Skipped/not-run cells get hatched background */\n.result-cell.cell-skipped {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--test-disabled);\n}\n\n.result-cell.cell-none {\n background: var(--mj-bg-surface-card);\n color: var(--test-text-muted);\n}\n\n.cell-score {\n display: block;\n font-size: 10px;\n font-weight: 600;\n margin-top: 2px;\n}\n\n/* Matrix cell evaluation stack - shows multiple eval types horizontally */\n.cell-eval-stack {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n flex-wrap: nowrap;\n}\n\n.result-cell.multi-eval {\n min-width: 120px;\n width: auto;\n}\n\n/* Add timeout status icon */\n.cell-status.status-timeout {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-status.status-pending {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.cell-human {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n font-size: 10px;\n}\n\n.cell-auto {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-auto.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-none-indicator {\n color: var(--test-text-muted);\n opacity: 0.5;\n}\n\n.matrix-info {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.matrix-info i {\n color: var(--test-primary);\n}\n\n/* ===========================\n Chart View\n =========================== */\n.chart-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.chart-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.chart-header h3 {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.chart-header h3 i {\n color: var(--test-primary);\n}\n\n.chart-legend {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.chart-legend .legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.chart-legend .legend-item.chart-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.chart-legend .legend-item.chart-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.chart-legend .legend-item.chart-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.chart-legend .legend-item.chart-skipped {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-disabled);\n}\n\n.chart-container {\n min-height: 500px;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.d3-chart {\n width: 100%;\n height: 500px;\n}\n\n.d3-chart svg {\n width: 100%;\n height: 100%;\n}\n\n/* D3 Chart Node Styles */\n.d3-chart .node {\n cursor: pointer;\n transition: transform 0.2s ease;\n}\n\n.d3-chart .node:hover {\n transform: scale(1.05);\n}\n\n.d3-chart .node-label {\n font-size: 11px;\n font-weight: 500;\n fill: var(--test-text);\n pointer-events: none;\n}\n\n.d3-chart .link {\n fill: none;\n stroke-opacity: 0.4;\n transition: stroke-opacity 0.2s ease;\n}\n\n.d3-chart .link:hover {\n stroke-opacity: 0.8;\n}\n\n.d3-chart .tooltip {\n position: absolute;\n padding: 10px 14px;\n background: var(--mj-bg-overlay);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 12px;\n pointer-events: none;\n z-index: 100;\n box-shadow: var(--mj-shadow-lg);\n max-width: 250px;\n}\n\n.d3-chart .tooltip-title {\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n.d3-chart .tooltip-value {\n opacity: 0.8;\n}\n\n.chart-info {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n margin-top: 16px;\n}\n\n.chart-info i {\n color: var(--test-primary);\n}\n\n/* ===========================\n Compare Tab\n =========================== */\n.compare-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n.compare-selection {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 24px;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.compare-run-selector {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-run-selector h4 {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.run-selector-list {\n max-height: 200px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.run-selector-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.run-selector-item:hover {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-selector-item.selected {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.run-selector-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.selector-status {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.selector-content {\n flex: 1;\n min-width: 0;\n}\n\n.selector-date {\n font-size: 12px;\n font-weight: 500;\n color: var(--test-text);\n}\n\n.selector-rate {\n font-size: 11px;\n color: var(--test-text-secondary);\n}\n\n.selector-tags {\n display: flex;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.selected-run-preview {\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-sm);\n border: 1px solid var(--test-border);\n}\n\n.preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.preview-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n}\n\n.clear-btn {\n padding: 4px 8px;\n border: none;\n background: transparent;\n color: var(--test-error);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.clear-btn:hover { text-decoration: underline; }\n\n.preview-details {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--test-text);\n}\n\n.preview-rate {\n font-weight: 600;\n color: var(--test-success);\n}\n\n.compare-vs {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--test-bg);\n border-radius: 50%;\n color: var(--test-text-muted);\n font-size: 16px;\n align-self: center;\n margin-top: 60px;\n}\n\n/* Compare Results */\n.compare-results {\n animation: fadeIn 0.3s ease-out;\n}\n\n.compare-summary {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.compare-summary-card {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n text-align: center;\n}\n\n.compare-summary-card .summary-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n margin-bottom: 8px;\n}\n\n.compare-summary-card .summary-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.compare-summary-card .summary-value.positive { color: var(--test-success); }\n.compare-summary-card .summary-value.negative { color: var(--test-error); }\n\n.compare-summary-card.improved {\n border-left: 4px solid var(--test-success);\n}\n\n.compare-summary-card.improved .summary-value { color: var(--test-success); }\n\n.compare-summary-card.regressed {\n border-left: 4px solid var(--test-error);\n}\n\n.compare-summary-card.regressed .summary-value { color: var(--test-error); }\n\n/* Compare Table */\n.compare-table-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-table-section h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.compare-table-section h3 i {\n color: var(--test-primary);\n}\n\n.compare-table-wrapper {\n overflow-x: auto;\n}\n\n.compare-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.compare-table th {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.compare-table td {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.compare-table tbody tr.improved {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.compare-table tbody tr.regressed {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.test-name-cell {\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.positive { color: var(--test-success); }\n.negative { color: var(--test-error); }\n.muted { color: var(--test-text-muted); }\n\n.change-indicator {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.change-indicator.improved {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.change-indicator.regressed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.change-indicator.unchanged {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-muted);\n}\n\n/* Compare Empty State */\n.compare-empty {\n text-align: center;\n padding: 60px 24px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n margin-top: 24px;\n}\n\n.compare-empty-icon {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n margin: 0 auto 20px;\n}\n\n.compare-empty-icon i {\n font-size: 32px;\n color: var(--test-text-muted);\n}\n\n.compare-empty h4 {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.compare-empty p {\n margin: 0;\n font-size: 14px;\n color: var(--test-text-secondary);\n max-width: 400px;\n margin: 0 auto;\n}\n\n/* Small empty state variant */\n.empty-state.small {\n padding: 32px 16px;\n}\n\n.empty-state.small p {\n margin: 0;\n}\n\n/* ===========================\n Responsive Analytics/Compare\n =========================== */\n@media (max-width: 1024px) {\n .compare-selection {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n .compare-vs {\n margin: 0;\n align-self: center;\n justify-self: center;\n }\n\n .analytics-kpis {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .filter-buttons {\n flex-direction: column;\n }\n\n .filter-btn {\n width: 100%;\n text-align: center;\n }\n\n .analytics-kpis {\n grid-template-columns: 1fr;\n }\n\n .kpi-card {\n padding: 16px;\n }\n\n .kpi-value {\n font-size: 20px;\n }\n\n .compare-summary {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .analytics-table-wrapper,\n .compare-table-wrapper {\n margin: 0 -20px;\n padding: 0 20px;\n }\n\n .run-selector-list {\n max-height: 150px;\n }\n}\n\n@media (max-width: 480px) {\n .compare-summary {\n grid-template-columns: 1fr;\n }\n\n .compare-summary-card .summary-value {\n font-size: 20px;\n }\n\n .analytics-table th,\n .analytics-table td,\n .compare-table th,\n .compare-table td {\n padding: 10px 12px;\n font-size: 12px;\n }\n}\n\n/* ===========================\n Matrix Evaluation Indicators\n =========================== */\n\n/* Human Feedback Indicators */\n.cell-human {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-human.no-feedback {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-human.no-feedback i {\n font-size: 11px;\n}\n\n.cell-human.has-feedback {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-human.has-feedback i {\n font-size: 9px;\n}\n\n.cell-human.has-feedback .rating-value {\n font-weight: 700;\n font-size: 11px;\n}\n\n/* Human rating color coding: red \u22644, yellow 5-6, light-green 7-8, green 9-10 */\n.cell-human.rating-low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-human.rating-medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-human.rating-good {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-human.rating-excellent {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n/* Auto Score Indicators */\n.cell-auto {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-auto.no-score {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-auto.no-score i {\n font-size: 11px;\n}\n\n.cell-auto.has-score {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-auto.has-score i {\n font-size: 9px;\n}\n\n.cell-auto.has-score .score-value {\n font-weight: 700;\n font-size: 10px;\n}\n\n/* Auto score color coding (0-100%): red <50, yellow 50-69, light-green 70-84, green 85+ */\n.cell-auto.score-low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-auto.score-medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.score-good {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.score-excellent {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n/* Status indicators in matrix cells */\n.cell-status {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-timeout {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped,\n.cell-status.status-pending {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n/* Not-run / Skipped cells with hatch pattern */\n.result-cell.cell-not-run {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--mj-text-disabled);\n}\n\n.result-cell.cell-not-run .cell-eval-stack {\n opacity: 0.6;\n}\n\n.cell-not-run-indicator {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n color: var(--mj-text-disabled);\n font-size: 11px;\n}\n\n/* ===========================\n Matrix Totals Footer Row\n =========================== */\n.test-matrix tfoot {\n position: sticky;\n bottom: 0;\n z-index: 2;\n}\n\n.totals-row {\n background: var(--mj-bg-surface-sunken);\n border-top: 2px solid var(--test-border);\n}\n\n.totals-row td {\n padding: 10px 12px;\n font-weight: 600;\n}\n\n.totals-row .totals-label {\n background: var(--mj-bg-surface-sunken);\n font-size: 12px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.totals-row .totals-cell {\n background: var(--mj-bg-surface-sunken);\n}\n\n.totals-stack {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.totals-status,\n.totals-human,\n.totals-auto {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.totals-status {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.totals-status .pass-count {\n font-weight: 700;\n}\n\n.totals-human {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.totals-human .avg-label {\n font-weight: 700;\n}\n\n.totals-human .count-label {\n font-size: 10px;\n opacity: 0.8;\n}\n\n.totals-auto {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.totals-auto .avg-label {\n font-weight: 700;\n}\n\n.totals-auto .count-label {\n font-size: 10px;\n opacity: 0.8;\n}\n"] }]
|
|
4393
|
+
args: [{ standalone: false, selector: 'mj-test-suite-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"test-suite-form\">\n <!-- Header Section -->\n <div class=\"suite-header\">\n <!-- Breadcrumb Navigation -->\n <nav class=\"breadcrumb\" aria-label=\"Breadcrumb\">\n <ol>\n <li>\n <a href=\"javascript:void(0)\" (click)=\"navigateToTestingDashboard()\">\n <i class=\"fas fa-vial\"></i>\n <span class=\"breadcrumb-text\">Testing</span>\n </a>\n </li>\n <li class=\"current\">\n <i class=\"fas fa-chevron-right separator\"></i>\n <i class=\"fas fa-layer-group\"></i>\n <span>{{ record.Name }}</span>\n </li>\n </ol>\n </nav>\n\n <div class=\"header-content\">\n <div class=\"header-left\">\n <div class=\"suite-icon\" [style.background-color]=\"getStatusColor()\">\n <i class=\"fas fa-layer-group\"></i>\n </div>\n <div class=\"suite-info\">\n <h1>\n {{ record.Name }}\n @if (isDirty) {\n <span class=\"dirty-indicator\" title=\"You have unsaved changes\" aria-label=\"Unsaved changes\">\u25CF</span>\n }\n </h1>\n <div class=\"suite-meta\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass()\">\n <i class=\"fas\" [ngClass]=\"record.Status === 'Active' ? 'fa-circle-check' : 'fa-circle-pause'\"></i>\n {{ record.Status }}\n </span>\n @if (testsLoaded) {\n <span class=\"test-count\">\n <i class=\"fas fa-flask\"></i>\n {{ suiteTests.length }} tests\n </span>\n }\n @if (isDirty) {\n <span class=\"unsaved-pill\" title=\"You have unsaved changes\">\n <i class=\"fas fa-circle\"></i> Unsaved\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"header-actions\">\n <app-evaluation-mode-toggle></app-evaluation-mode-toggle>\n <button mjButton (click)=\"exportToExcel()\" title=\"Export to CSV\">\n <i class=\"fas fa-file-excel\"></i> Export\n </button>\n <button mjButton (click)=\"runSuite()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Suite\n </button>\n <button mjButton (click)=\"refresh()\" [disabled]=\"isRefreshing\">\n <i class=\"fas\" [ngClass]=\"isRefreshing ? 'fa-sync fa-spin' : 'fa-sync'\"></i>\n {{ isRefreshing ? 'Refreshing...' : 'Refresh' }}\n </button>\n </div>\n </div>\n @if (record.Description) {\n <div class=\"suite-description\">\n <p>{{ record.Description }}</p>\n </div>\n }\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs-container\">\n <div class=\"tabs\" role=\"tablist\">\n <button class=\"tab\"\n [class.active]=\"activeTab === 'overview'\"\n (click)=\"changeTab('overview')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'overview'\">\n <i class=\"fas fa-th-large\"></i> Overview\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'tests'\"\n (click)=\"changeTab('tests')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'tests'\">\n <i class=\"fas fa-flask\"></i> Tests\n @if (testsLoaded) {\n <span class=\"tab-badge\">{{ suiteTests.length }}</span>\n }\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'runs'\"\n (click)=\"changeTab('runs')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'runs'\">\n <i class=\"fas fa-history\"></i> Runs\n @if (runsLoaded) {\n <span class=\"tab-badge\">{{ suiteRuns.length }}</span>\n }\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'analytics'\"\n (click)=\"changeTab('analytics')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'analytics'\">\n <i class=\"fas fa-chart-line\"></i> Analytics\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'compare'\"\n (click)=\"changeTab('compare')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'compare'\">\n <i class=\"fas fa-balance-scale\"></i> Compare\n </button>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tab-content\" [class.has-savebar]=\"isDirty\">\n <!-- Overview Tab -->\n @if (activeTab === 'overview') {\n <div class=\"overview-tab\">\n <!-- Editable Details -->\n <section class=\"edit-section\">\n <header class=\"edit-section-header\">\n <h3><i class=\"fas fa-pen-to-square\"></i> Details</h3>\n <p class=\"edit-section-sub\">Edit any field \u2014 changes are saved with the bar at the bottom.</p>\n </header>\n <div class=\"edit-grid\">\n <div class=\"edit-field edit-field--full\">\n <label for=\"suite-name\">Name <span class=\"required\">*</span></label>\n <input\n id=\"suite-name\"\n type=\"text\"\n class=\"config-input\"\n placeholder=\"e.g., Core Agent Test Suite\"\n [(ngModel)]=\"record.Name\"\n />\n </div>\n\n <div class=\"edit-field edit-field--full\">\n <label for=\"suite-description\">Description</label>\n <textarea\n id=\"suite-description\"\n class=\"config-input config-textarea\"\n rows=\"3\"\n placeholder=\"What does this suite cover?\"\n [ngModel]=\"record.Description\"\n (ngModelChange)=\"record.Description = $event || null\"\n ></textarea>\n </div>\n\n <div class=\"edit-field\">\n <label for=\"suite-status\">Status</label>\n <div class=\"select-wrapper\">\n <select\n id=\"suite-status\"\n class=\"config-input\"\n [(ngModel)]=\"record.Status\"\n >\n @for (opt of statusOptions; track opt) {\n <option [ngValue]=\"opt\">{{ opt }}</option>\n }\n </select>\n </div>\n </div>\n\n <div class=\"edit-field\">\n <label for=\"suite-parent\">Parent Suite</label>\n <select\n id=\"suite-parent\"\n class=\"config-input\"\n [ngModel]=\"record.ParentID\"\n (ngModelChange)=\"record.ParentID = $event || null\"\n >\n <option [ngValue]=\"null\">\u2014 None (top-level) \u2014</option>\n @for (s of parentSuiteOptions; track s.ID) {\n <option [ngValue]=\"s.ID\">{{ s.Name }}</option>\n }\n </select>\n </div>\n\n <div class=\"edit-field edit-field--full\">\n <label for=\"suite-tags\">Tags</label>\n <div class=\"tag-editor\" (click)=\"tagInput.focus()\">\n @for (tag of tags; track tag) {\n <span class=\"tag-chip-editable\">\n {{ tag }}\n <button type=\"button\" class=\"tag-remove\" (click)=\"removeTag(tag); $event.stopPropagation()\" [attr.aria-label]=\"'Remove tag ' + tag\">\n <i class=\"fas fa-times\"></i>\n </button>\n </span>\n }\n <input\n #tagInput\n id=\"suite-tags\"\n type=\"text\"\n class=\"tag-input-inline\"\n [placeholder]=\"tags.length === 0 ? 'Add tags, press Enter or comma...' : ''\"\n [(ngModel)]=\"tagDraft\"\n (keydown)=\"onTagInputKeydown($event)\"\n (blur)=\"addTagFromDraft()\"\n />\n </div>\n <span class=\"config-hint\">Press Enter or comma to add a tag. Backspace on empty input removes the last tag.</span>\n </div>\n </div>\n </section>\n\n <!-- Execution Settings -->\n <section class=\"edit-section\">\n <header class=\"edit-section-header\">\n <h3><i class=\"fas fa-cogs\"></i> Execution Settings</h3>\n </header>\n <div class=\"edit-grid\">\n <div class=\"edit-field\">\n <label for=\"suite-timeout\">Max Execution Time (ms)</label>\n <input\n id=\"suite-timeout\"\n type=\"number\"\n class=\"config-input\"\n placeholder=\"Default: 300000 (5 min)\"\n [ngModel]=\"record.MaxExecutionTimeMS\"\n (ngModelChange)=\"record.MaxExecutionTimeMS = $event === '' || $event === null ? null : +$event\"\n />\n <span class=\"config-hint\">Default timeout for tests in this suite. Currently: {{ formatTimeout(record.MaxExecutionTimeMS) }}</span>\n </div>\n </div>\n </section>\n\n <!-- Metadata (read-only) -->\n <section class=\"meta-section\">\n <div class=\"meta-grid\">\n <div class=\"meta-item\">\n <div class=\"meta-label\">Created</div>\n <div class=\"meta-value\">{{ record.__mj_CreatedAt | date:'medium' }}</div>\n </div>\n <div class=\"meta-item\">\n <div class=\"meta-label\">Last updated</div>\n <div class=\"meta-value\">{{ record.__mj_UpdatedAt | date:'medium' }}</div>\n </div>\n <div class=\"meta-item\">\n <div class=\"meta-label\">Suite ID</div>\n <div class=\"meta-value meta-mono\">{{ record.ID }}</div>\n </div>\n </div>\n </section>\n </div>\n }\n\n <!-- Tests Tab -->\n @if (activeTab === 'tests') {\n <div class=\"tests-tab\">\n <!-- Header: action bar -->\n <div class=\"tests-actionbar\">\n <div class=\"tests-actionbar-text\">\n <strong>Suite tests</strong>\n @if (testsLoaded) {\n <span class=\"tests-actionbar-count\">{{ suiteTests.length }}</span>\n }\n <span class=\"tests-actionbar-hint\">Drag to reorder \u00B7 Hover a row to remove</span>\n </div>\n <div class=\"tests-actionbar-actions\">\n <button mjButton variant=\"primary\" (click)=\"openAddTestsDialog()\" [disabled]=\"isReorderingTests\">\n <i class=\"fas fa-plus\"></i> Add tests\n </button>\n </div>\n </div>\n\n <!-- Loading State -->\n @if (loadingTests) {\n <div class=\"loading-state\">\n <div class=\"skeleton-list\">\n @for (i of [1,2,3,4,5]; track i) {\n <div class=\"skeleton-card\">\n <div class=\"skeleton-sequence\"></div>\n <div class=\"skeleton-icon\"></div>\n <div class=\"skeleton-content\">\n <div class=\"skeleton-line wide\"></div>\n <div class=\"skeleton-line narrow\"></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Tests List -->\n @if (!loadingTests && suiteTests.length > 0) {\n <div class=\"tests-list\" cdkDropList (cdkDropListDropped)=\"onTestDrop($event)\">\n @for (test of suiteTests; track test.ID) {\n <div class=\"test-item\" cdkDrag [cdkDragDisabled]=\"isReorderingTests || isRemovingTest\">\n <span class=\"test-drag-handle\" cdkDragHandle title=\"Drag to reorder\" aria-label=\"Drag to reorder\">\n <i class=\"fas fa-grip-vertical\"></i>\n </span>\n <div class=\"test-sequence\">{{ test.Sequence }}</div>\n <div class=\"test-icon\"><i class=\"fas fa-flask\"></i></div>\n <div class=\"test-content\" (click)=\"openTest(test.TestID)\">\n <div class=\"test-name\">{{ test.Test }}</div>\n <div class=\"test-status\">\n @if (test.Status) {\n <span><i class=\"fas fa-info-circle\"></i> {{ test.Status }}</span>\n }\n </div>\n </div>\n <!-- Inline remove confirm OR hover-reveal X -->\n @if (confirmingRemoveSuiteTestId === test.ID) {\n <div class=\"test-remove-confirm\" (click)=\"$event.stopPropagation()\">\n <span class=\"test-remove-confirm-text\">Remove from suite?</span>\n <button\n type=\"button\"\n class=\"test-remove-confirm-btn test-remove-confirm-btn--danger\"\n (click)=\"confirmRemoveTest(test, $event)\"\n [disabled]=\"isRemovingTest\"\n >\n @if (isRemovingTest) {\n <i class=\"fas fa-spinner fa-spin\"></i>\n } @else {\n Remove\n }\n </button>\n <button\n type=\"button\"\n class=\"test-remove-confirm-btn test-remove-confirm-btn--ghost\"\n (click)=\"cancelRemoveTest($event)\"\n [disabled]=\"isRemovingTest\"\n >\n Cancel\n </button>\n </div>\n } @else {\n <button\n type=\"button\"\n class=\"test-remove-btn\"\n title=\"Remove from suite\"\n aria-label=\"Remove from suite\"\n (click)=\"requestRemoveTest(test, $event)\"\n >\n <i class=\"fas fa-times\"></i>\n </button>\n <i class=\"fas fa-chevron-right test-chevron\" (click)=\"openTest(test.TestID)\"></i>\n }\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (testsLoaded && !loadingTests && suiteTests.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-flask\"></i>\n </div>\n <h4>No Tests in Suite</h4>\n <p>Add tests to this suite to start running them together.</p>\n <button mjButton variant=\"primary\" (click)=\"openAddTestsDialog()\">\n <i class=\"fas fa-plus\"></i> Add tests\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Runs Tab -->\n @if (activeTab === 'runs') {\n <div class=\"runs-tab\">\n <!-- Loading State -->\n @if (loadingRuns) {\n <div class=\"loading-state\">\n <div class=\"skeleton-list\">\n @for (i of [1,2,3]; track i) {\n <div class=\"skeleton-card\">\n <div class=\"skeleton-icon\"></div>\n <div class=\"skeleton-content\">\n <div class=\"skeleton-line wide\"></div>\n <div class=\"skeleton-line narrow\"></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Runs List -->\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"runs-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-item\" (click)=\"openSuiteRun(run.ID)\">\n <div class=\"run-icon\" [style.background-color]=\"getRunStatusColor(run.Status)\">\n <i class=\"fas\"\n [class.fa-check]=\"run.Status === 'Completed'\"\n [class.fa-times]=\"run.Status === 'Failed'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"\n [class.fa-ban]=\"run.Status === 'Cancelled'\"></i>\n </div>\n <div class=\"run-content\">\n <div class=\"run-header\">\n <span class=\"run-id\">Run #{{ run.ID.substring(0, 8) }}</span>\n <span class=\"run-status\" [style.color]=\"getRunStatusColor(run.Status)\">{{ run.Status }}</span>\n </div>\n <div class=\"run-meta\">\n <span><i class=\"fas fa-calendar\"></i> {{ getRelativeTime(run.StartedAt) }}</span>\n @if (run.TotalTests) {\n <span>\n <i class=\"fas fa-check-circle\"></i> {{ run.PassedTests }}/{{ run.TotalTests }}\n ({{ getPassRate(run).toFixed(0) }}%)\n </span>\n }\n </div>\n <!-- Evaluation metrics row -->\n <div class=\"run-eval-metrics\">\n <!-- Status badge -->\n @if (evalPreferences.showExecution) {\n <span class=\"eval-metric status\" [class]=\"'status-' + run.Status.toLowerCase()\">\n <i class=\"fas\"\n [class.fa-circle-check]=\"run.Status === 'Completed'\"\n [class.fa-circle-xmark]=\"run.Status === 'Failed'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"\n [class.fa-ban]=\"run.Status === 'Cancelled'\"></i>\n </span>\n }\n <!-- Human score (placeholder - need avg from suite run) -->\n @if (evalPreferences.showHuman) {\n <span class=\"eval-metric human\" title=\"Human evaluation\">\n <i class=\"fas fa-user\"></i>\n <span class=\"eval-pending\"><i class=\"fas fa-clock\"></i></span>\n </span>\n }\n <!-- Auto score (pass rate as proxy) -->\n @if (evalPreferences.showAuto && run.TotalTests) {\n <span class=\"eval-metric auto\"\n [class.high]=\"getPassRate(run) >= 80\"\n [class.medium]=\"getPassRate(run) >= 50 && getPassRate(run) < 80\"\n [class.low]=\"getPassRate(run) < 50\"\n title=\"Auto score (pass rate)\">\n <i class=\"fas fa-robot\"></i>\n <span>{{ getPassRate(run).toFixed(0) }}%</span>\n </span>\n }\n </div>\n <!-- Tags display -->\n @if (getRunTags(run).length > 0) {\n <div class=\"run-tags\">\n @for (tag of getRunTags(run); track tag) {\n <span class=\"tag-chip\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n <i class=\"fas fa-chevron-right\"></i>\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (runsLoaded && !loadingRuns && suiteRuns.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-play-circle\"></i>\n </div>\n <h4>No Suite Runs Yet</h4>\n <p>Run this suite to see execution history and results here.</p>\n <button mjButton (click)=\"runSuite()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Suite Now\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Analytics Tab -->\n @if (activeTab === 'analytics') {\n <div class=\"analytics-tab\">\n <!-- Loading State -->\n @if (loadingAnalytics) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading analytics data...\"></mj-loading>\n </div>\n }\n @if (!loadingAnalytics && analyticsLoaded) {\n <!-- View Toggle Sub-nav -->\n <div class=\"analytics-subnav\">\n <div class=\"subnav-tabs\">\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'summary'\"\n (click)=\"setAnalyticsView('summary')\">\n <i class=\"fas fa-chart-bar\"></i>\n <span>Summary</span>\n </button>\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'matrix'\"\n (click)=\"setAnalyticsView('matrix')\">\n <i class=\"fas fa-th\"></i>\n <span>Matrix</span>\n </button>\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'chart'\"\n (click)=\"setAnalyticsView('chart')\">\n <i class=\"fas fa-project-diagram\"></i>\n <span>Chart</span>\n </button>\n </div>\n </div>\n <!-- Collapsible Filters (shared by both views) -->\n <div class=\"analytics-filters\" [class.collapsed]=\"filtersCollapsed\">\n <div class=\"filters-header\" (click)=\"toggleFilters()\">\n <span class=\"filters-title\">\n <i class=\"fas fa-filter\"></i>\n Filters\n @if (filtersCollapsed) {\n <span class=\"filter-summary\">\n {{ analyticsTimeRange === 'all' ? 'All Time' : analyticsTimeRange }}\n @if (selectedTags.length > 0) {\n <span> \u00B7 {{ selectedTags.length }} tags</span>\n }\n </span>\n }\n </span>\n <i class=\"fas\" [ngClass]=\"filtersCollapsed ? 'fa-chevron-down' : 'fa-chevron-up'\"></i>\n </div>\n @if (!filtersCollapsed) {\n <div class=\"filters-content\">\n <div class=\"filter-group\">\n <label>Time Range</label>\n <div class=\"filter-buttons\">\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '7d'\" (click)=\"setTimeRange('7d')\">7 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '30d'\" (click)=\"setTimeRange('30d')\">30 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '90d'\" (click)=\"setTimeRange('90d')\">90 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === 'all'\" (click)=\"setTimeRange('all')\">All Time</button>\n </div>\n </div>\n @if (uniqueTags.length > 0) {\n <div class=\"filter-group\">\n <label>Filter by Tag @if (selectedTags.length > 0) {\n <span class=\"filter-hint\">({{ selectedTags.length }} selected)</span>\n }</label>\n <div class=\"filter-buttons tag-filters\">\n <button class=\"filter-btn tag-btn all-tags-btn\"\n [class.active]=\"selectedTags.length === 0\"\n (click)=\"toggleTagFilter(null)\">\n <i class=\"fas fa-layer-group\"></i> All Tags\n </button>\n @for (tag of uniqueTags; track tag) {\n <button class=\"filter-btn tag-btn\"\n [class.active]=\"isTagSelected(tag)\"\n (click)=\"toggleTagFilter(tag)\">\n @if (isTagSelected(tag)) {\n <i class=\"fas fa-check\"></i>\n }\n {{ tag }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n <!-- Summary View -->\n @if (analyticsView === 'summary') {\n <!-- KPI Cards -->\n <div class=\"analytics-kpis\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\"><i class=\"fas fa-play-circle\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ getTotalRuns() }}</div>\n <div class=\"kpi-label\">Total Runs</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon success\"><i class=\"fas fa-check-circle\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ getAveragePassRate().toFixed(1) }}%</div>\n <div class=\"kpi-label\">Avg Pass Rate</div>\n <div class=\"kpi-trend\" [ngClass]=\"{'trend-up': getPassRateTrend().direction === 'up', 'trend-down': getPassRateTrend().direction === 'down'}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-up': getPassRateTrend().direction === 'up', 'fa-arrow-down': getPassRateTrend().direction === 'down', 'fa-minus': getPassRateTrend().direction === 'stable'}\"></i>\n {{ getPassRateTrend().value.toFixed(1) }}%\n </div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon info\"><i class=\"fas fa-clock\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatDuration(getAverageDuration()) }}</div>\n <div class=\"kpi-label\">Avg Duration</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon warning\"><i class=\"fas fa-dollar-sign\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatCost(getTotalCost()) }}</div>\n <div class=\"kpi-label\">Total Cost</div>\n </div>\n </div>\n </div>\n <!-- Runs Table -->\n <div class=\"analytics-table-section\">\n <h3><i class=\"fas fa-table\"></i> Run History</h3>\n <div class=\"analytics-table-wrapper\">\n <table class=\"analytics-table\">\n <thead>\n <tr>\n <th>Date</th>\n <th>Status</th>\n <th>Pass Rate</th>\n <th>Tests</th>\n <th>Duration</th>\n <th>Cost</th>\n <th>Tags</th>\n </tr>\n </thead>\n <tbody>\n @for (dp of getFilteredAnalyticsData(); track dp) {\n <tr (click)=\"openSuiteRun(dp.runId)\" class=\"clickable-row\">\n <td>{{ dp.date | date:'short' }}</td>\n <td>\n <span class=\"status-chip\" [ngClass]=\"'status-' + dp.status.toLowerCase()\">{{ dp.status }}</span>\n </td>\n <td>\n <div class=\"pass-rate-cell\">\n <div class=\"pass-rate-bar\" [style.width.%]=\"dp.passRate\" [ngClass]=\"{'high': dp.passRate >= 80, 'medium': dp.passRate >= 50 && dp.passRate < 80, 'low': dp.passRate < 50}\"></div>\n <span>{{ dp.passRate.toFixed(0) }}%</span>\n </div>\n </td>\n <td>{{ dp.passedTests }}/{{ dp.totalTests }}</td>\n <td>{{ formatDuration(dp.duration) }}</td>\n <td>{{ formatCost(dp.cost) }}</td>\n <td>\n <div class=\"tag-cell\">\n @for (tag of dp.tags.slice(0, 2); track tag) {\n <span class=\"tag-chip-table\">{{ tag }}</span>\n }\n @if (dp.tags.length > 2) {\n <span class=\"tag-more\">+{{ dp.tags.length - 2 }}</span>\n }\n </div>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n @if (getFilteredAnalyticsData().length === 0) {\n <div class=\"empty-state small\">\n <p>No runs match the current filters.</p>\n </div>\n }\n </div>\n }\n <!-- Matrix View -->\n @if (analyticsView === 'matrix') {\n <!-- Loading Matrix -->\n @if (loadingMatrix) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading test matrix...\"></mj-loading>\n </div>\n }\n <!-- Matrix Content -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length > 0) {\n <div class=\"matrix-section\">\n <div class=\"matrix-header\">\n <h3><i class=\"fas fa-th\"></i> Test Results Matrix</h3>\n <div class=\"matrix-header-right\">\n <div class=\"matrix-filter-input\">\n <i class=\"fas fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Filter tests...\"\n [value]=\"matrixTestFilter\"\n (input)=\"onMatrixFilterInput($event)\"\n class=\"filter-input\">\n @if (matrixTestFilter) {\n <button class=\"clear-filter-btn\" (click)=\"clearMatrixFilter()\" title=\"Clear filter\">\n <i class=\"fas fa-times\"></i>\n </button>\n }\n </div>\n <span class=\"matrix-run-count\">{{ matrixData.length }} runs \u00B7 {{ getUniqueTestsFromMatrix().length }} tests</span>\n <button mjButton (click)=\"exportMatrixToCSV()\" [disabled]=\"matrixData.length === 0\" title=\"Export matrix to CSV\">\n <i class=\"fas fa-download\"></i> Export\n </button>\n </div>\n </div>\n <div class=\"matrix-scroll-container\">\n <table class=\"test-matrix\">\n <thead>\n <tr>\n <th class=\"seq-header\" (click)=\"toggleMatrixSort('sequence')\" title=\"Sort by sequence\">\n #\n <i class=\"fas\" [ngClass]=\"matrixSortBy === 'sequence' ? (matrixSortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort'\"></i>\n </th>\n <th class=\"test-name-header\" (click)=\"toggleMatrixSort('name')\" title=\"Sort by name\">\n Test\n <i class=\"fas\" [ngClass]=\"matrixSortBy === 'name' ? (matrixSortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort'\"></i>\n </th>\n @for (run of matrixData; track run) {\n <th class=\"run-header\" (click)=\"openSuiteRun(run.runId)\" [title]=\"'Click to view suite run - ' + (run.date | date:'medium')\">\n <div class=\"run-header-content\">\n @if (run.tags.length > 0) {\n <div class=\"run-tags-header\">\n @for (tag of run.tags.slice(0, 2); track tag) {\n <span class=\"tag-chip-header\">{{ tag }}</span>\n }\n @if (run.tags.length > 2) {\n <span class=\"tag-more-header\">+{{ run.tags.length - 2 }}</span>\n }\n </div>\n }\n <div class=\"run-date\">{{ getRelativeTime(run.date) }}</div>\n <div class=\"run-pass-rate\" [ngClass]=\"{'high': run.passRate >= 80, 'medium': run.passRate >= 50 && run.passRate < 80, 'low': run.passRate < 50}\">\n {{ run.passRate.toFixed(0) }}%\n </div>\n </div>\n </th>\n }\n <th class=\"spacer-header\"></th>\n </tr>\n </thead>\n <tbody>\n @for (test of getUniqueTestsFromMatrix(); track test) {\n <tr\n [class.row-selected]=\"selectedMatrixTestId === test.testId\"\n (click)=\"selectMatrixRow(test.testId)\">\n <td class=\"seq-cell\">{{ test.sequence }}</td>\n <td class=\"test-name-cell\">\n <span class=\"test-name\" [title]=\"test.testName\">{{ test.testName }}</span>\n </td>\n @for (run of matrixData; track run) {\n <td class=\"result-cell\"\n [ngClass]=\"getMatrixCellClass(getTestResultForRun(run.runId, test.testId))\"\n [class.clickable]=\"getTestResultForRun(run.runId, test.testId)\"\n [class.cell-not-run]=\"!getTestResultForRun(run.runId, test.testId)\"\n [title]=\"getTestResultForRun(run.runId, test.testId)?.status + ' - Click to view test run' || 'Not Run'\"\n (click)=\"onMatrixCellClick(getTestResultForRun(run.runId, test.testId), $event)\">\n @if (getTestResultForRun(run.runId, test.testId); as result) {\n <div class=\"cell-eval-stack\">\n <!-- Status indicator -->\n @if (evalPreferences.showExecution) {\n <span class=\"cell-status\"\n [ngClass]=\"'status-' + result.status.toLowerCase()\"\n [class.cell-skipped-status]=\"result.status === 'Skipped' || result.status === 'Pending'\"\n [title]=\"getStatusTooltip(result.status)\">\n <i class=\"fas\"\n [class.fa-check]=\"result.status === 'Passed'\"\n [class.fa-times]=\"result.status === 'Failed'\"\n [class.fa-exclamation]=\"result.status === 'Error'\"\n [class.fa-hourglass-end]=\"result.status === 'Timeout'\"\n [class.fa-forward]=\"result.status === 'Skipped'\"\n [class.fa-spinner]=\"result.status === 'Running'\"\n [class.fa-clock]=\"result.status === 'Pending'\"></i>\n </span>\n }\n <!-- Human score - slashed icon if no feedback, colored by rating if has feedback -->\n @if (evalPreferences.showHuman && !result.humanRating) {\n <span class=\"cell-human no-feedback\"\n title=\"Human Review: No rating submitted yet\">\n <i class=\"fas fa-user-slash\"></i>\n </span>\n }\n @if (evalPreferences.showHuman && result.humanRating) {\n <span class=\"cell-human has-feedback\"\n [class.rating-low]=\"result.humanRating <= 4\"\n [class.rating-medium]=\"result.humanRating >= 5 && result.humanRating <= 6\"\n [class.rating-good]=\"result.humanRating >= 7 && result.humanRating <= 8\"\n [class.rating-excellent]=\"result.humanRating >= 9\"\n [title]=\"getHumanTooltip(result.humanRating, result.humanComments)\">\n <i class=\"fas fa-user\"></i>\n <span class=\"rating-value\">{{ result.humanRating }}</span>\n </span>\n }\n <!-- Auto score - colored by percentage -->\n @if (evalPreferences.showAuto && result.score != null) {\n <span class=\"cell-auto has-score\"\n [class.score-low]=\"result.score < 0.5\"\n [class.score-medium]=\"result.score >= 0.5 && result.score < 0.7\"\n [class.score-good]=\"result.score >= 0.7 && result.score < 0.85\"\n [class.score-excellent]=\"result.score >= 0.85\"\n [title]=\"'Auto Score: ' + (result.score * 100).toFixed(0) + '% automated evaluation'\">\n <i class=\"fas fa-robot\"></i>\n <span class=\"score-value\">{{ (result.score * 100).toFixed(0) }}</span>\n </span>\n }\n @if (evalPreferences.showAuto && result.score == null) {\n <span class=\"cell-auto no-score\"\n title=\"Auto Score: No automated score available\">\n <i class=\"fas fa-robot\"></i>\n </span>\n }\n </div>\n }\n @if (!getTestResultForRun(run.runId, test.testId)) {\n <span class=\"cell-not-run-indicator\">\n <i class=\"fas fa-minus\"></i>\n </span>\n }\n </td>\n }\n <td class=\"spacer-cell\"></td>\n </tr>\n }\n </tbody>\n <!-- Footer row with totals -->\n <tfoot>\n <tr class=\"totals-row\">\n <td class=\"seq-cell totals-label\"></td>\n <td class=\"test-name-cell totals-label\">\n <strong>Totals</strong>\n </td>\n @for (run of matrixData; track run) {\n <td class=\"result-cell totals-cell\">\n <div class=\"cell-eval-stack totals-stack\">\n <!-- Status totals -->\n @if (evalPreferences.showExecution) {\n <span class=\"totals-status\">\n <span class=\"pass-count\">{{ getRunPassedCount(run) }}/{{ getRunTotalCount(run) }}</span>\n </span>\n }\n <!-- Human totals -->\n @if (evalPreferences.showHuman) {\n <span class=\"totals-human\">\n @if (getRunHumanAvg(run) != null) {\n <span class=\"avg-label\">{{ getRunHumanAvg(run)?.toFixed(1) }}</span>\n }\n <span class=\"count-label\">({{ getRunHumanCount(run) }})</span>\n </span>\n }\n <!-- Auto totals -->\n @if (evalPreferences.showAuto) {\n <span class=\"totals-auto\">\n @if (getRunAutoAvg(run) != null) {\n <span class=\"avg-label\">{{ (getRunAutoAvg(run)! * 100).toFixed(0) }}%</span>\n }\n <span class=\"count-label\">({{ getRunAutoCount(run) }})</span>\n </span>\n }\n </div>\n </td>\n }\n <td class=\"spacer-cell\"></td>\n </tr>\n </tfoot>\n </table>\n </div>\n </div>\n }\n <!-- Empty Matrix State -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-th\"></i>\n </div>\n <h4>No Matrix Data</h4>\n <p>No suite runs match the current filters.</p>\n </div>\n }\n }\n <!-- Chart View -->\n @if (analyticsView === 'chart') {\n <!-- Loading Chart -->\n @if (loadingMatrix) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading chart data...\"></mj-loading>\n </div>\n }\n <!-- Chart Content -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length > 0) {\n <div class=\"chart-section\">\n <div class=\"chart-header\">\n <h3><i class=\"fas fa-project-diagram\"></i> Test Results Flow</h3>\n <div class=\"chart-legend\">\n <span class=\"legend-item chart-passed\"><i class=\"fas fa-check\"></i> Passed</span>\n <span class=\"legend-item chart-failed\"><i class=\"fas fa-times\"></i> Failed</span>\n <span class=\"legend-item chart-error\"><i class=\"fas fa-exclamation\"></i> Error</span>\n <span class=\"legend-item chart-skipped\"><i class=\"fas fa-forward\"></i> Skipped</span>\n </div>\n </div>\n <div class=\"chart-container\">\n <div #chartContainer class=\"d3-chart\"></div>\n </div>\n <div class=\"chart-info\">\n <i class=\"fas fa-info-circle\"></i>\n Interactive visualization showing test results across {{ matrixData.length }} runs.\n Hover over elements for details, click nodes to navigate.\n </div>\n </div>\n }\n <!-- Empty Chart State -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-project-diagram\"></i>\n </div>\n <h4>No Chart Data</h4>\n <p>No suite runs match the current filters.</p>\n </div>\n }\n }\n }\n <!-- Empty State -->\n @if (!loadingAnalytics && analyticsLoaded && analyticsData.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-chart-line\"></i>\n </div>\n <h4>No Analytics Data</h4>\n <p>Run this suite to start collecting analytics data.</p>\n <button mjButton (click)=\"runSuite()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Suite Now\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Compare Tab -->\n @if (activeTab === 'compare') {\n <div class=\"compare-tab\">\n <!-- Run Selection -->\n <div class=\"compare-selection\">\n <div class=\"compare-run-selector\">\n <h4>Run A (Baseline)</h4>\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"run-selector-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-selector-item\"\n [class.selected]=\"IsCompareRunA(run)\"\n (click)=\"selectCompareRunA(run)\">\n <div class=\"selector-status\" [style.background-color]=\"getRunStatusColor(run.Status)\"></div>\n <div class=\"selector-content\">\n <div class=\"selector-date\">{{ run.StartedAt | date:'short' }}</div>\n <div class=\"selector-rate\">{{ getPassRate(run).toFixed(0) }}% pass</div>\n </div>\n @if (getRunTags(run).length > 0) {\n <div class=\"selector-tags\">\n @for (tag of getRunTags(run).slice(0, 2); track tag) {\n <span class=\"tag-mini\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (compareRunA) {\n <div class=\"selected-run-preview\">\n <div class=\"preview-header\">\n <span class=\"preview-label\">Selected:</span>\n <button class=\"clear-btn\" (click)=\"compareRunA = null; compareResults = []\">Clear</button>\n </div>\n <div class=\"preview-details\">\n <span>{{ compareRunA.StartedAt | date:'medium' }}</span>\n <span class=\"preview-rate\">{{ getPassRate(compareRunA).toFixed(1) }}%</span>\n </div>\n </div>\n }\n </div>\n <div class=\"compare-vs\"><i class=\"fas fa-exchange-alt\"></i></div>\n <div class=\"compare-run-selector\">\n <h4>Run B (Compare)</h4>\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"run-selector-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-selector-item\"\n [class.selected]=\"IsCompareRunB(run)\"\n [class.disabled]=\"IsCompareRunA(run)\"\n (click)=\"!IsCompareRunA(run) && selectCompareRunB(run)\">\n <div class=\"selector-status\" [style.background-color]=\"getRunStatusColor(run.Status)\"></div>\n <div class=\"selector-content\">\n <div class=\"selector-date\">{{ run.StartedAt | date:'short' }}</div>\n <div class=\"selector-rate\">{{ getPassRate(run).toFixed(0) }}% pass</div>\n </div>\n @if (getRunTags(run).length > 0) {\n <div class=\"selector-tags\">\n @for (tag of getRunTags(run).slice(0, 2); track tag) {\n <span class=\"tag-mini\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (compareRunB) {\n <div class=\"selected-run-preview\">\n <div class=\"preview-header\">\n <span class=\"preview-label\">Selected:</span>\n <button class=\"clear-btn\" (click)=\"compareRunB = null; compareResults = []\">Clear</button>\n </div>\n <div class=\"preview-details\">\n <span>{{ compareRunB.StartedAt | date:'medium' }}</span>\n <span class=\"preview-rate\">{{ getPassRate(compareRunB).toFixed(1) }}%</span>\n </div>\n </div>\n }\n </div>\n </div>\n <!-- Comparison Results -->\n @if (compareRunA && compareRunB && !loadingCompare) {\n <div class=\"compare-results\">\n <!-- Summary Cards -->\n <div class=\"compare-summary\">\n <div class=\"compare-summary-card\">\n <div class=\"summary-label\">Pass Rate Change</div>\n <div class=\"summary-value\" [ngClass]=\"{'positive': getComparePassRateDiff()! > 0, 'negative': getComparePassRateDiff()! < 0}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-up': getComparePassRateDiff()! > 0, 'fa-arrow-down': getComparePassRateDiff()! < 0, 'fa-minus': getComparePassRateDiff() === 0}\"></i>\n {{ getComparePassRateDiff()! > 0 ? '+' : '' }}{{ getComparePassRateDiff()?.toFixed(1) }}%\n </div>\n </div>\n <div class=\"compare-summary-card\">\n <div class=\"summary-label\">Duration Change</div>\n <div class=\"summary-value\" [ngClass]=\"{'positive': getCompareDurationDiff()! < 0, 'negative': getCompareDurationDiff()! > 0}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-down': getCompareDurationDiff()! < 0, 'fa-arrow-up': getCompareDurationDiff()! > 0, 'fa-minus': getCompareDurationDiff() === 0}\"></i>\n {{ formatDuration(getAbsCompareDurationDiff()) }}\n </div>\n </div>\n <div class=\"compare-summary-card improved\">\n <div class=\"summary-label\">Improved</div>\n <div class=\"summary-value\">{{ getCompareImprovedCount() }}</div>\n </div>\n <div class=\"compare-summary-card regressed\">\n <div class=\"summary-label\">Regressed</div>\n <div class=\"summary-value\">{{ getCompareRegressedCount() }}</div>\n </div>\n </div>\n <!-- Detailed Comparison Table -->\n <div class=\"compare-table-section\">\n <h3><i class=\"fas fa-list\"></i> Test-by-Test Comparison</h3>\n <div class=\"compare-table-wrapper\">\n <table class=\"compare-table\">\n <thead>\n <tr>\n <th>Test</th>\n <th>Run A Status</th>\n <th>Run B Status</th>\n <th>Score Diff</th>\n <th>Duration Diff</th>\n <th>Change</th>\n </tr>\n </thead>\n <tbody>\n @for (result of compareResults; track result) {\n <tr [ngClass]=\"{'improved': result.runA && result.runB && result.runA.status !== 'Passed' && result.runB.status === 'Passed', 'regressed': result.runA && result.runB && result.runA.status === 'Passed' && result.runB.status !== 'Passed'}\">\n <td class=\"test-name-cell\">{{ result.testName }}</td>\n <td>\n @if (result.runA) {\n <span class=\"status-chip\" [ngClass]=\"'status-' + result.runA.status.toLowerCase()\">{{ result.runA.status }}</span>\n }\n @if (!result.runA) {\n <span class=\"status-chip status-missing\">N/A</span>\n }\n </td>\n <td>\n @if (result.runB) {\n <span class=\"status-chip\" [ngClass]=\"'status-' + result.runB.status.toLowerCase()\">{{ result.runB.status }}</span>\n }\n @if (!result.runB) {\n <span class=\"status-chip status-missing\">N/A</span>\n }\n </td>\n <td>\n @if (result.scoreDiff != null) {\n <span [ngClass]=\"{'positive': result.scoreDiff > 0, 'negative': result.scoreDiff < 0}\">\n {{ result.scoreDiff > 0 ? '+' : '' }}{{ (result.scoreDiff * 100).toFixed(1) }}%\n </span>\n }\n @if (result.scoreDiff == null) {\n <span class=\"muted\">-</span>\n }\n </td>\n <td>\n @if (result.durationDiff != null) {\n <span [ngClass]=\"{'positive': result.durationDiff < 0, 'negative': result.durationDiff > 0}\">\n {{ result.durationDiff > 0 ? '+' : '' }}{{ result.durationDiff.toFixed(1) }}s\n </span>\n }\n @if (result.durationDiff == null) {\n <span class=\"muted\">-</span>\n }\n </td>\n <td>\n @if (result.runA && result.runB && result.runA.status !== 'Passed' && result.runB.status === 'Passed') {\n <span class=\"change-indicator improved\">\n <i class=\"fas fa-arrow-up\"></i> Fixed\n </span>\n }\n @if (result.runA && result.runB && result.runA.status === 'Passed' && result.runB.status !== 'Passed') {\n <span class=\"change-indicator regressed\">\n <i class=\"fas fa-arrow-down\"></i> Broke\n </span>\n }\n @if (!result.statusChanged) {\n <span class=\"change-indicator unchanged\">\n <i class=\"fas fa-minus\"></i>\n </span>\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </div>\n }\n <!-- Loading State for Compare -->\n @if (loadingCompare) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading comparison data...\"></mj-loading>\n </div>\n }\n <!-- Empty State -->\n @if (!compareRunA || !compareRunB) {\n <div class=\"compare-empty\">\n <div class=\"compare-empty-icon\">\n <i class=\"fas fa-balance-scale\"></i>\n </div>\n <h4>Select Two Runs to Compare</h4>\n <p>Choose a baseline run (A) and a comparison run (B) from the lists above to see a detailed side-by-side comparison.</p>\n </div>\n }\n <!-- No Runs State -->\n @if (runsLoaded && suiteRuns.length < 2) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-balance-scale\"></i>\n </div>\n <h4>Not Enough Runs to Compare</h4>\n <p>You need at least 2 suite runs to use the comparison feature.</p>\n <button mjButton (click)=\"runSuite()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Suite Now\n </button>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Keyboard Shortcuts Toggle Button -->\n <button class=\"shortcuts-toggle\" (click)=\"toggleShortcuts()\" [title]=\"showShortcuts ? 'Hide keyboard shortcuts' : 'Show keyboard shortcuts'\">\n <i class=\"fas fa-keyboard\"></i>\n </button>\n\n <!-- Keyboard Shortcuts Hint (Desktop Only) -->\n @if (showShortcuts) {\n <div class=\"keyboard-shortcuts\">\n <div class=\"shortcuts-header\">\n <i class=\"fas fa-keyboard\"></i>\n Shortcuts\n <button class=\"shortcuts-close\" (click)=\"toggleShortcuts()\" title=\"Hide shortcuts\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n <div class=\"shortcut-list\">\n <div class=\"shortcut-item\">\n <span>Save changes</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>S</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Refresh</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>R</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Run Suite</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>Enter</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Switch Tabs</span>\n <span class=\"shortcut-keys\"><kbd>1</kbd>-<kbd>5</kbd></span>\n </div>\n </div>\n </div>\n }\n\n <!-- Slide Panel for Suite Execution -->\n @if (testingDialogService.IsPanelOpen) {\n <mj-slide-panel\n Mode=\"slide\"\n [Title]=\"testingDialogService.PanelOptions?.suiteId ? 'Suite Execution' : 'Run Suite'\"\n [Resizable]=\"true\"\n (Closed)=\"OnPanelClosed()\">\n <app-test-run-dialog\n [PanelMode]=\"true\"\n [selectedTestId]=\"testingDialogService.PanelOptions?.testId ?? null\"\n [selectedSuiteId]=\"testingDialogService.PanelOptions?.suiteId ?? null\"\n [runMode]=\"testingDialogService.PanelOptions?.mode ?? 'suite'\"\n (PanelClose)=\"OnPanelClosed()\">\n </app-test-run-dialog>\n </mj-slide-panel>\n }\n\n <!-- Add Tests Picker Dialog -->\n @if (showAddTestsDialog) {\n <div class=\"picker-backdrop\" (click)=\"closeAddTestsDialog()\"></div>\n <div class=\"picker-dialog\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"add-tests-dialog-title\" (click)=\"$event.stopPropagation()\">\n <div class=\"picker-header\">\n <h2 id=\"add-tests-dialog-title\" class=\"picker-title\">\n <i class=\"fas fa-plus-circle\"></i> Add tests to suite\n </h2>\n <button type=\"button\" class=\"picker-close\" (click)=\"closeAddTestsDialog()\" [disabled]=\"isAddingTests\" aria-label=\"Close\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n\n <div class=\"picker-search\">\n <i class=\"fas fa-search picker-search-icon\"></i>\n <input\n #pickerSearch\n type=\"text\"\n class=\"picker-search-input\"\n placeholder=\"Search tests by name, description, or type...\"\n [(ngModel)]=\"addTestsSearch\"\n autofocus\n />\n @if (addTestsSearch) {\n <button type=\"button\" class=\"picker-search-clear\" (click)=\"addTestsSearch = ''\" aria-label=\"Clear search\">\n <i class=\"fas fa-times\"></i>\n </button>\n }\n </div>\n\n <div class=\"picker-toolbar\">\n <span class=\"picker-toolbar-status\">\n @if (selectedTestIdsToAdd.size > 0) {\n <strong>{{ selectedTestIdsToAdd.size }}</strong> selected\n } @else if (!loadingAvailableTests) {\n {{ filteredAvailableTests.length }} test{{ filteredAvailableTests.length === 1 ? '' : 's' }} available\n }\n </span>\n <div class=\"picker-toolbar-actions\">\n <button type=\"button\" class=\"picker-link-btn\" (click)=\"selectAllFiltered()\" [disabled]=\"loadingAvailableTests || filteredAvailableTests.length === 0\">\n Select all\n </button>\n <button type=\"button\" class=\"picker-link-btn\" (click)=\"clearAddSelection()\" [disabled]=\"selectedTestIdsToAdd.size === 0\">\n Clear\n </button>\n </div>\n </div>\n\n <div class=\"picker-body\">\n @if (loadingAvailableTests) {\n <div class=\"picker-loading\">\n <mj-loading text=\"Loading tests...\"></mj-loading>\n </div>\n } @else if (filteredAvailableTests.length === 0) {\n <div class=\"picker-empty\">\n @if (availableTests.length === 0) {\n <i class=\"fas fa-check-circle\"></i>\n <h4>Everything's already in the suite</h4>\n <p>This suite contains every available test. Create a new test first to add more.</p>\n } @else {\n <i class=\"fas fa-search\"></i>\n <h4>No matches</h4>\n <p>No tests match \"{{ addTestsSearch }}\".</p>\n }\n </div>\n } @else {\n <ul class=\"picker-list\">\n @for (t of filteredAvailableTests; track t.ID) {\n <li\n class=\"picker-row\"\n [class.picker-row--selected]=\"isAddSelected(t.ID)\"\n (click)=\"toggleAddSelection(t.ID)\"\n role=\"checkbox\"\n [attr.aria-checked]=\"isAddSelected(t.ID)\"\n tabindex=\"0\"\n >\n <span class=\"picker-check\">\n @if (isAddSelected(t.ID)) {\n <i class=\"fas fa-check\"></i>\n }\n </span>\n <div class=\"picker-row-main\">\n <div class=\"picker-row-name\">{{ t.Name }}</div>\n @if (t.Description) {\n <div class=\"picker-row-desc\">{{ t.Description }}</div>\n }\n </div>\n <div class=\"picker-row-meta\">\n @if (t.Type) {\n <span class=\"picker-row-pill\">{{ t.Type }}</span>\n }\n <span class=\"picker-row-pill picker-row-pill--status\" [attr.data-status]=\"t.Status?.toLowerCase()\">{{ t.Status }}</span>\n </div>\n </li>\n }\n </ul>\n }\n </div>\n\n <div class=\"picker-footer\">\n <button\n type=\"button\"\n class=\"picker-btn picker-btn--primary\"\n (click)=\"confirmAddTests()\"\n [disabled]=\"selectedTestIdsToAdd.size === 0 || isAddingTests\"\n >\n @if (isAddingTests) {\n <i class=\"fas fa-spinner fa-spin\"></i> Adding\u2026\n } @else {\n <i class=\"fas fa-check\"></i>\n @if (selectedTestIdsToAdd.size === 0) {\n Add tests\n } @else if (selectedTestIdsToAdd.size === 1) {\n Add 1 test\n } @else {\n Add {{ selectedTestIdsToAdd.size }} tests\n }\n }\n </button>\n <button\n type=\"button\"\n class=\"picker-btn picker-btn--ghost\"\n (click)=\"closeAddTestsDialog()\"\n [disabled]=\"isAddingTests\"\n >\n Cancel\n </button>\n </div>\n </div>\n }\n\n <!-- Sticky Save Bar \u2014 always in the DOM so CSS transitions can fire reliably.\n Visibility is controlled by the .save-bar--visible class, driven by isDirty. -->\n <div\n class=\"save-bar\"\n [class.save-bar--visible]=\"isDirty\"\n [attr.aria-hidden]=\"!isDirty\"\n role=\"region\"\n aria-label=\"Unsaved changes\"\n >\n <div class=\"save-bar-message\">\n <span class=\"save-bar-dot\" aria-hidden=\"true\">\u25CF</span>\n <span class=\"save-bar-text\">\n <strong>Unsaved changes</strong>\n <span class=\"save-bar-fields\">\n @if (dirtyFieldNames.length === 1) {\n {{ dirtyFieldNames[0] }} edited\n } @else if (dirtyFieldNames.length > 1) {\n {{ dirtyFieldNames.length }} fields edited\n }\n </span>\n </span>\n </div>\n <div class=\"save-bar-actions\">\n <button\n type=\"button\"\n class=\"save-bar-btn save-bar-btn--primary\"\n (click)=\"saveChanges()\"\n [disabled]=\"isSaving || !isDirty\"\n [attr.tabindex]=\"isDirty ? 0 : -1\"\n title=\"Save changes (\u2318S)\"\n >\n @if (isSaving) {\n <i class=\"fas fa-spinner fa-spin\"></i> Saving\u2026\n } @else {\n <i class=\"fas fa-check\"></i> Save changes\n <span class=\"save-bar-kbd\"><kbd>\u2318</kbd><kbd>S</kbd></span>\n }\n </button>\n <button\n type=\"button\"\n class=\"save-bar-btn save-bar-btn--ghost\"\n (click)=\"discardChanges()\"\n [disabled]=\"isSaving || !isDirty\"\n [attr.tabindex]=\"isDirty ? 0 : -1\"\n title=\"Discard changes\"\n >\n <i class=\"fas fa-undo\"></i> Discard\n </button>\n </div>\n </div>\n</div>\n", styles: ["/* ===========================\n Test Suite Form - World-Class UX\n =========================== */\n\n/* CSS Custom Properties for Theming - using :host for Angular encapsulation */\n:host {\n --test-primary: var(--mj-brand-primary);\n --test-primary-light: var(--mj-brand-primary);\n --test-success: var(--mj-status-success);\n --test-error: var(--mj-status-error);\n --test-warning: var(--mj-status-warning);\n --test-disabled: var(--mj-text-muted);\n --test-bg: var(--mj-bg-surface-card);\n --test-surface: var(--mj-bg-surface);\n --test-border: var(--mj-border-default);\n --test-text: var(--mj-text-primary);\n --test-text-secondary: var(--mj-text-secondary);\n --test-text-muted: var(--mj-text-disabled);\n --test-radius-sm: 6px;\n --test-radius-md: 10px;\n --test-radius-lg: 16px;\n --test-shadow-sm: var(--mj-shadow-sm);\n --test-shadow-md: var(--mj-shadow-md);\n --test-shadow-lg: var(--mj-shadow-lg);\n --test-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: block;\n height: 100%;\n}\n\n.test-suite-form {\n position: relative;\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--test-bg);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n/* Breadcrumb */\n.breadcrumb {\n margin-bottom: 16px;\n}\n\n.breadcrumb ol {\n display: flex;\n align-items: center;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n font-size: 13px;\n}\n\n.breadcrumb li {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.breadcrumb a {\n color: var(--test-primary);\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 6px;\n transition: background 0.15s;\n}\n\n.breadcrumb a:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n text-decoration: none;\n}\n\n.breadcrumb .separator {\n font-size: 10px;\n color: var(--test-text-muted);\n margin: 0 4px;\n}\n\n.breadcrumb .current {\n color: var(--test-text-secondary);\n font-weight: 500;\n}\n\n.breadcrumb-text {\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Header */\n.suite-header {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n padding: 20px;\n}\n\n.header-content {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 16px;\n gap: 16px;\n}\n\n.header-left {\n display: flex;\n gap: 16px;\n flex: 1;\n min-width: 0;\n}\n\n.suite-icon {\n width: 56px;\n height: 56px;\n border-radius: var(--test-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-size: 24px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.suite-icon:hover { transform: scale(1.05); }\n\n.suite-info { flex: 1; min-width: 0; }\n\n.suite-info h1 {\n margin: 0 0 8px 0;\n font-size: clamp(18px, 4vw, 24px);\n font-weight: 700;\n color: var(--test-text);\n word-wrap: break-word;\n}\n\n.suite-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: 20px;\n color: var(--mj-text-inverse);\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-active { background: var(--test-success); }\n.status-badge.status-disabled { background: var(--test-disabled); }\n.status-badge.status-pending { background: var(--test-warning); }\n\n.status-badge-inline {\n display: inline-flex;\n padding: 2px 10px;\n border-radius: 10px;\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n}\n\n.status-badge-inline.status-active { background: var(--test-success); }\n.status-badge-inline.status-disabled { background: var(--test-disabled); }\n.status-badge-inline.status-pending { background: var(--test-warning); }\n\n.test-count {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n color: var(--test-text-secondary);\n padding: 4px 10px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.suite-description {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.suite-description p {\n margin: 0;\n color: var(--test-text-secondary);\n line-height: 1.6;\n font-size: 14px;\n}\n\n/* Tabs */\n.tabs-container {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n\n.tabs {\n display: flex;\n padding: 0 20px;\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.tabs::-webkit-scrollbar { display: none; }\n\n.tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 18px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: var(--test-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n white-space: nowrap;\n}\n\n.tab:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.tab.active {\n color: var(--test-primary);\n border-bottom-color: var(--test-primary);\n font-weight: 600;\n}\n\n.tab-badge {\n background: var(--test-border);\n color: var(--test-text-secondary);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active .tab-badge {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--test-primary);\n}\n\n.tab-shortcut {\n font-size: 10px;\n color: var(--test-text-muted);\n background: var(--test-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n/* Tab Content */\n.tab-content {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n/* Overview Tab */\n.overview-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: fadeIn 0.3s ease-out;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; transform: translateY(10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.info-section, .config-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.info-section h3, .config-section h3 {\n margin: 0 0 20px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.info-section h3 i, .config-section h3 i {\n color: var(--test-primary);\n}\n\n.info-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n.info-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.info-value {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 500;\n}\n\n.config-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.config-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.config-item label {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.config-input {\n padding: 10px 14px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.config-input:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.config-hint {\n font-size: 11px;\n color: var(--test-text-muted);\n}\n\n/* Tests Tab */\n.tests-tab, .runs-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n.loading-state { padding: 0; }\n\n.skeleton-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.skeleton-card {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.skeleton-sequence {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-icon {\n width: 40px;\n height: 40px;\n border-radius: var(--test-radius-md);\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.skeleton-line {\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-line.wide { width: 70%; }\n.skeleton-line.narrow { width: 40%; }\n\n@keyframes shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n.tests-list, .runs-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.test-item, .run-item {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.test-item:hover, .run-item:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n}\n\n.test-sequence {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n font-size: 14px;\n font-weight: 700;\n color: var(--test-text-secondary);\n flex-shrink: 0;\n}\n\n.test-icon, .run-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 18px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-sm);\n}\n\n.test-icon {\n background: var(--test-primary);\n}\n\n.test-content, .run-content { flex: 1; min-width: 0; }\n\n.test-name, .run-header {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-header {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.run-id { font-weight: 600; }\n\n.run-status {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.test-status, .run-meta {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.test-status span, .run-meta span {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.test-item > i, .run-item > i {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.test-item:hover > i, .run-item:hover > i {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n/* Empty States */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 24px;\n text-align: center;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n}\n\n.empty-icon {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n margin-bottom: 20px;\n}\n\n.empty-icon i {\n font-size: 36px;\n color: var(--test-text-muted);\n}\n\n.empty-state h4 {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.empty-state p {\n margin: 0 0 20px 0;\n font-size: 14px;\n color: var(--test-text-secondary);\n max-width: 300px;\n}\n\n/* Keyboard Shortcuts */\n/* Keyboard shortcuts toggle button - visible when shortcuts are hidden */\n.shortcuts-toggle {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n box-shadow: var(--test-shadow-md);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--test-text-secondary);\n font-size: 14px;\n z-index: 99;\n transition: var(--test-transition);\n opacity: 0.7;\n}\n\n.shortcuts-toggle:hover {\n opacity: 1;\n transform: scale(1.1);\n color: var(--test-primary);\n border-color: var(--test-primary);\n}\n\n.keyboard-shortcuts {\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 12px 16px;\n box-shadow: var(--test-shadow-lg);\n font-size: 12px;\n z-index: 100;\n max-width: 260px;\n}\n\n.shortcuts-header {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text);\n}\n\n.shortcuts-close {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--test-text-muted);\n font-size: 12px;\n padding: 2px 4px;\n border-radius: 4px;\n transition: var(--test-transition);\n}\n\n.shortcuts-close:hover {\n color: var(--test-text);\n background: var(--test-border);\n}\n\n.shortcut-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.shortcut-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n color: var(--test-text-secondary);\n}\n\n.shortcut-keys {\n display: flex;\n gap: 4px;\n}\n\n.shortcut-keys kbd {\n background: var(--test-bg);\n border: 1px solid var(--test-border);\n border-radius: 4px;\n padding: 2px 6px;\n font-size: 11px;\n color: var(--test-text);\n}\n\n/* Responsive */\n@media (max-width: 1024px) {\n .keyboard-shortcuts, .shortcuts-toggle { display: none; }\n}\n\n@media (max-width: 768px) {\n .suite-header { padding: 16px; }\n\n .header-content {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions button { flex: 1; }\n\n .tab-shortcut { display: none; }\n\n .info-grid { grid-template-columns: 1fr; }\n\n .test-item, .run-item { padding: 14px; }\n}\n\n@media (max-width: 480px) {\n .suite-icon {\n width: 40px;\n height: 40px;\n font-size: 18px;\n }\n\n .suite-info h1 { font-size: 16px; }\n\n .tab-badge { display: none; }\n\n .test-sequence { display: none; }\n}\n\n@media (hover: none) and (pointer: coarse) {\n .test-item:active, .run-item:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n transform: scale(0.98);\n }\n\n .tab { min-height: 48px; }\n .test-item, .run-item { min-height: 64px; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n@media print {\n .header-actions, .tabs-container, .keyboard-shortcuts {\n display: none !important;\n }\n}\n\n/* ===========================\n Tags UI\n =========================== */\n.run-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 8px;\n}\n\n.tag-chip {\n display: inline-flex;\n align-items: center;\n padding: 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-mini {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.tag-more {\n font-size: 10px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n/* Evaluation metrics row for Runs list */\n.run-eval-metrics {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n}\n\n.eval-metric {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.eval-metric.status {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-metric.status.status-completed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.eval-metric.status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.eval-metric.status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.status.status-pending {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-warning);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human .eval-pending {\n font-size: 9px;\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.auto.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n color: var(--mj-status-success);\n}\n\n.eval-metric.auto.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n color: var(--mj-status-error);\n}\n\n.tag-cell {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.tag-chip-table {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 80px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* ===========================\n Analytics Tab\n =========================== */\n.analytics-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n/* Collapsible filters */\n.analytics-filters {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n margin-bottom: 16px;\n box-shadow: var(--test-shadow-sm);\n overflow: hidden;\n}\n\n.analytics-filters.collapsed {\n margin-bottom: 12px;\n}\n\n.filters-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s ease;\n}\n\n.filters-header:hover {\n background: var(--test-bg);\n}\n\n.filters-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text-secondary);\n}\n\n.filters-title i {\n color: var(--test-primary);\n}\n\n.filter-summary {\n font-weight: 400;\n color: var(--test-text-muted);\n margin-left: 8px;\n}\n\n.filters-header > i {\n color: var(--test-text-muted);\n font-size: 12px;\n}\n\n.filters-content {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 16px 16px 16px;\n border-top: 1px solid var(--test-border);\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.filter-group label {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.filter-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.filter-btn {\n padding: 8px 16px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.filter-btn:hover {\n border-color: var(--test-primary);\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.filter-btn.active {\n background: var(--test-primary);\n border-color: var(--test-primary);\n color: var(--mj-text-inverse);\n}\n\n.filter-btn.tag-btn {\n padding: 6px 12px;\n font-size: 12px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.filter-btn.tag-btn i.fa-check {\n font-size: 10px;\n}\n\n.filter-btn.tag-btn.all-tags-btn {\n font-weight: 600;\n}\n\n.filter-btn.tag-btn.all-tags-btn i {\n font-size: 11px;\n}\n\n.filter-hint {\n font-weight: 400;\n font-size: 10px;\n color: var(--test-primary);\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-filters {\n max-height: 120px;\n overflow-y: auto;\n}\n\n/* KPI Cards */\n.analytics-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n gap: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.kpi-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.kpi-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: var(--test-radius-md);\n color: var(--test-primary);\n font-size: 20px;\n}\n\n.kpi-icon.success {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-icon.info {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.kpi-icon.warning {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n line-height: 1.2;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--test-text-secondary);\n margin-top: 2px;\n}\n\n.kpi-trend {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n font-weight: 600;\n margin-top: 4px;\n padding: 2px 8px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-secondary);\n}\n\n.kpi-trend.trend-up {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-trend.trend-down {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n/* Analytics Table */\n.analytics-table-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.analytics-table-section h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.analytics-table-section h3 i {\n color: var(--test-primary);\n}\n\n.analytics-table-wrapper {\n overflow-x: auto;\n margin: 0 -24px;\n padding: 0 24px;\n}\n\n.analytics-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.analytics-table th {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.analytics-table td {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.analytics-table tbody tr.clickable-row {\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.analytics-table tbody tr.clickable-row:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.status-chip {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-chip.status-completed { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-passed { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-failed { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--test-error); }\n.status-chip.status-error { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-running { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--test-primary); }\n.status-chip.status-pending { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-chip.status-cancelled { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n.status-chip.status-missing { background: var(--mj-bg-surface-sunken); color: var(--test-text-muted); }\n.status-chip.status-timeout { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-skipped { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n\n.pass-rate-cell {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 100px;\n}\n\n.pass-rate-bar {\n height: 6px;\n border-radius: 3px;\n background: var(--test-success);\n transition: width 0.3s ease;\n max-width: 60px;\n}\n\n.pass-rate-bar.medium { background: var(--test-warning); }\n.pass-rate-bar.low { background: var(--test-error); }\n\n/* Analytics Sub-navigation */\n.analytics-subnav {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 8px;\n margin-bottom: 20px;\n box-shadow: var(--test-shadow-sm);\n display: inline-flex;\n}\n\n.subnav-tabs {\n display: flex;\n gap: 4px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n}\n\n.subnav-tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border: none;\n border-radius: var(--test-radius-sm);\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.subnav-tab:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.subnav-tab.active {\n background: var(--test-surface);\n color: var(--test-primary);\n box-shadow: var(--test-shadow-sm);\n}\n\n.subnav-tab i {\n font-size: 14px;\n}\n\n/* Matrix View */\n.matrix-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 16px;\n box-shadow: var(--test-shadow-sm);\n display: flex;\n flex-direction: column;\n max-height: calc(100vh - 280px);\n min-height: 300px;\n}\n\n.matrix-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--test-border);\n flex-shrink: 0;\n}\n\n.matrix-header-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.matrix-header h3 {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.matrix-header h3 i {\n color: var(--test-primary);\n}\n\n.matrix-run-count {\n font-size: 12px;\n color: var(--test-text-muted);\n font-weight: 500;\n}\n\n/* Matrix filter input */\n.matrix-filter-input {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--test-border);\n border-radius: 6px;\n padding: 4px 10px;\n min-width: 180px;\n}\n\n.matrix-filter-input i.fa-search {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.matrix-filter-input .filter-input {\n border: none;\n background: transparent;\n outline: none;\n font-size: 12px;\n color: var(--test-text);\n width: 100%;\n}\n\n.matrix-filter-input .filter-input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.clear-filter-btn {\n border: none;\n background: none;\n padding: 2px 4px;\n cursor: pointer;\n color: var(--mj-text-disabled);\n font-size: 10px;\n border-radius: 3px;\n transition: all 0.15s ease;\n}\n\n.clear-filter-btn:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n}\n\n/* Scrollable matrix container with fixed height */\n.matrix-scroll-container {\n flex: 1;\n overflow: auto;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n}\n\n.test-matrix {\n display: table;\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.test-matrix thead {\n display: table-header-group;\n}\n\n.test-matrix thead tr {\n display: table-row;\n}\n\n.test-matrix tbody {\n display: table-row-group;\n}\n\n.test-matrix tbody tr {\n display: table-row;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.test-matrix tbody tr:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.test-matrix tbody tr.row-selected {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix tbody tr.row-selected td {\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.test-matrix tbody tr.row-selected .seq-cell,\n.test-matrix tbody tr.row-selected .test-name-cell {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix tfoot {\n display: table-footer-group;\n}\n\n.test-matrix th,\n.test-matrix td {\n display: table-cell;\n border: 1px solid var(--test-border);\n padding: 8px 12px;\n text-align: center;\n vertical-align: middle;\n}\n\n.test-matrix th {\n background: var(--test-bg);\n font-weight: 600;\n font-size: 11px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n position: sticky;\n top: 0;\n z-index: 10;\n border-bottom: 3px solid var(--mj-text-secondary) !important;\n}\n\n/* Sequence column - shared styles */\n.test-matrix .seq-header,\n.test-matrix .seq-cell {\n width: 36px;\n min-width: 36px;\n max-width: 36px;\n text-align: center;\n position: sticky;\n left: 0;\n font-size: 11px;\n color: var(--mj-text-muted);\n border-right: 1px solid var(--test-border);\n padding: 6px 4px !important;\n}\n\n/* Seq header - sticky top AND left, highest z-index */\n.test-matrix .seq-header {\n cursor: pointer;\n font-weight: 600;\n background: var(--test-bg);\n z-index: 12; /* Higher than other headers */\n top: 0;\n}\n\n/* Seq body cells - sticky left only, lower z-index */\n.test-matrix .seq-cell {\n background: var(--test-surface);\n z-index: 2;\n}\n\n.test-matrix .seq-header i {\n font-size: 9px;\n margin-left: 2px;\n opacity: 0.6;\n}\n\n.test-matrix .seq-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix .test-name-header {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-bg);\n z-index: 11;\n border-right: 2px solid var(--test-border);\n cursor: pointer;\n}\n\n.test-matrix .test-name-header i {\n font-size: 9px;\n margin-left: 4px;\n opacity: 0.6;\n}\n\n.test-matrix .test-name-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix .run-header {\n min-width: 120px;\n width: 120px;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n/* Spacer column absorbs extra width */\n.test-matrix .spacer-header,\n.test-matrix .spacer-cell {\n width: 100%;\n min-width: 20px;\n background: var(--test-bg);\n border: none;\n}\n\n.test-matrix .spacer-cell {\n background: var(--test-surface);\n}\n\n.test-matrix .run-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-header-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.run-date {\n font-size: 12px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-pass-rate {\n font-size: 11px;\n font-weight: 700;\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.run-pass-rate.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.run-pass-rate.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.run-pass-rate.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.run-tags {\n display: flex;\n gap: 4px;\n}\n\n.tag-tiny {\n font-size: 9px;\n padding: 2px 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--test-primary);\n border-radius: 8px;\n white-space: nowrap;\n max-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Matrix column header tags - emphasized */\n.run-tags-header {\n display: flex;\n flex-wrap: wrap;\n gap: 3px;\n justify-content: center;\n margin-bottom: 4px;\n}\n\n.tag-chip-header {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 70px;\n overflow: hidden;\n text-overflow: ellipsis;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-more-header {\n font-size: 9px;\n color: var(--test-text-secondary);\n padding: 2px 4px;\n}\n\n.test-matrix .test-name-cell {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-surface);\n z-index: 2;\n border-right: 2px solid var(--test-border);\n padding: 6px 10px !important;\n}\n\n.test-name {\n display: block;\n white-space: nowrap;\n font-weight: 500;\n color: var(--test-text);\n font-size: 12px;\n}\n\n.result-cell {\n position: relative;\n min-width: 120px;\n width: 120px;\n transition: var(--test-transition);\n}\n\n.result-cell.clickable {\n cursor: pointer;\n}\n\n.result-cell.clickable:hover {\n transform: scale(1.1);\n box-shadow: var(--mj-shadow-md);\n z-index: 5;\n}\n\n.result-cell i {\n font-size: 14px;\n}\n\n/* Completed cells have neutral white background - pills tell the story */\n.result-cell.cell-passed,\n.result-cell.cell-failed,\n.result-cell.cell-error,\n.result-cell.cell-timeout,\n.result-cell.cell-running,\n.result-cell.cell-pending {\n background: var(--mj-bg-surface);\n color: var(--test-text);\n}\n\n/* Skipped/not-run cells get hatched background */\n.result-cell.cell-skipped {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--test-disabled);\n}\n\n.result-cell.cell-none {\n background: var(--mj-bg-surface-card);\n color: var(--test-text-muted);\n}\n\n.cell-score {\n display: block;\n font-size: 10px;\n font-weight: 600;\n margin-top: 2px;\n}\n\n/* Matrix cell evaluation stack - shows multiple eval types horizontally */\n.cell-eval-stack {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n flex-wrap: nowrap;\n}\n\n.result-cell.multi-eval {\n min-width: 120px;\n width: auto;\n}\n\n/* Add timeout status icon */\n.cell-status.status-timeout {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-status.status-pending {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.cell-human {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n font-size: 10px;\n}\n\n.cell-auto {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-auto.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-none-indicator {\n color: var(--test-text-muted);\n opacity: 0.5;\n}\n\n.matrix-info {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.matrix-info i {\n color: var(--test-primary);\n}\n\n/* ===========================\n Chart View\n =========================== */\n.chart-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.chart-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.chart-header h3 {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.chart-header h3 i {\n color: var(--test-primary);\n}\n\n.chart-legend {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.chart-legend .legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.chart-legend .legend-item.chart-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.chart-legend .legend-item.chart-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.chart-legend .legend-item.chart-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.chart-legend .legend-item.chart-skipped {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-disabled);\n}\n\n.chart-container {\n min-height: 500px;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.d3-chart {\n width: 100%;\n height: 500px;\n}\n\n.d3-chart svg {\n width: 100%;\n height: 100%;\n}\n\n/* D3 Chart Node Styles */\n.d3-chart .node {\n cursor: pointer;\n transition: transform 0.2s ease;\n}\n\n.d3-chart .node:hover {\n transform: scale(1.05);\n}\n\n.d3-chart .node-label {\n font-size: 11px;\n font-weight: 500;\n fill: var(--test-text);\n pointer-events: none;\n}\n\n.d3-chart .link {\n fill: none;\n stroke-opacity: 0.4;\n transition: stroke-opacity 0.2s ease;\n}\n\n.d3-chart .link:hover {\n stroke-opacity: 0.8;\n}\n\n.d3-chart .tooltip {\n position: absolute;\n padding: 10px 14px;\n background: var(--mj-bg-overlay);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 12px;\n pointer-events: none;\n z-index: 100;\n box-shadow: var(--mj-shadow-lg);\n max-width: 250px;\n}\n\n.d3-chart .tooltip-title {\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n.d3-chart .tooltip-value {\n opacity: 0.8;\n}\n\n.chart-info {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n margin-top: 16px;\n}\n\n.chart-info i {\n color: var(--test-primary);\n}\n\n/* ===========================\n Compare Tab\n =========================== */\n.compare-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n.compare-selection {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 24px;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.compare-run-selector {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-run-selector h4 {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.run-selector-list {\n max-height: 200px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.run-selector-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.run-selector-item:hover {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-selector-item.selected {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.run-selector-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.selector-status {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.selector-content {\n flex: 1;\n min-width: 0;\n}\n\n.selector-date {\n font-size: 12px;\n font-weight: 500;\n color: var(--test-text);\n}\n\n.selector-rate {\n font-size: 11px;\n color: var(--test-text-secondary);\n}\n\n.selector-tags {\n display: flex;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.selected-run-preview {\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-sm);\n border: 1px solid var(--test-border);\n}\n\n.preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.preview-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n}\n\n.clear-btn {\n padding: 4px 8px;\n border: none;\n background: transparent;\n color: var(--test-error);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.clear-btn:hover { text-decoration: underline; }\n\n.preview-details {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--test-text);\n}\n\n.preview-rate {\n font-weight: 600;\n color: var(--test-success);\n}\n\n.compare-vs {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--test-bg);\n border-radius: 50%;\n color: var(--test-text-muted);\n font-size: 16px;\n align-self: center;\n margin-top: 60px;\n}\n\n/* Compare Results */\n.compare-results {\n animation: fadeIn 0.3s ease-out;\n}\n\n.compare-summary {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.compare-summary-card {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n text-align: center;\n}\n\n.compare-summary-card .summary-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n margin-bottom: 8px;\n}\n\n.compare-summary-card .summary-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.compare-summary-card .summary-value.positive { color: var(--test-success); }\n.compare-summary-card .summary-value.negative { color: var(--test-error); }\n\n.compare-summary-card.improved {\n border-left: 4px solid var(--test-success);\n}\n\n.compare-summary-card.improved .summary-value { color: var(--test-success); }\n\n.compare-summary-card.regressed {\n border-left: 4px solid var(--test-error);\n}\n\n.compare-summary-card.regressed .summary-value { color: var(--test-error); }\n\n/* Compare Table */\n.compare-table-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-table-section h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.compare-table-section h3 i {\n color: var(--test-primary);\n}\n\n.compare-table-wrapper {\n overflow-x: auto;\n}\n\n.compare-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.compare-table th {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.compare-table td {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.compare-table tbody tr.improved {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.compare-table tbody tr.regressed {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.test-name-cell {\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.positive { color: var(--test-success); }\n.negative { color: var(--test-error); }\n.muted { color: var(--test-text-muted); }\n\n.change-indicator {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.change-indicator.improved {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.change-indicator.regressed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.change-indicator.unchanged {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-muted);\n}\n\n/* Compare Empty State */\n.compare-empty {\n text-align: center;\n padding: 60px 24px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n margin-top: 24px;\n}\n\n.compare-empty-icon {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n margin: 0 auto 20px;\n}\n\n.compare-empty-icon i {\n font-size: 32px;\n color: var(--test-text-muted);\n}\n\n.compare-empty h4 {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.compare-empty p {\n margin: 0;\n font-size: 14px;\n color: var(--test-text-secondary);\n max-width: 400px;\n margin: 0 auto;\n}\n\n/* Small empty state variant */\n.empty-state.small {\n padding: 32px 16px;\n}\n\n.empty-state.small p {\n margin: 0;\n}\n\n/* ===========================\n Responsive Analytics/Compare\n =========================== */\n@media (max-width: 1024px) {\n .compare-selection {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n .compare-vs {\n margin: 0;\n align-self: center;\n justify-self: center;\n }\n\n .analytics-kpis {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .filter-buttons {\n flex-direction: column;\n }\n\n .filter-btn {\n width: 100%;\n text-align: center;\n }\n\n .analytics-kpis {\n grid-template-columns: 1fr;\n }\n\n .kpi-card {\n padding: 16px;\n }\n\n .kpi-value {\n font-size: 20px;\n }\n\n .compare-summary {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .analytics-table-wrapper,\n .compare-table-wrapper {\n margin: 0 -20px;\n padding: 0 20px;\n }\n\n .run-selector-list {\n max-height: 150px;\n }\n}\n\n@media (max-width: 480px) {\n .compare-summary {\n grid-template-columns: 1fr;\n }\n\n .compare-summary-card .summary-value {\n font-size: 20px;\n }\n\n .analytics-table th,\n .analytics-table td,\n .compare-table th,\n .compare-table td {\n padding: 10px 12px;\n font-size: 12px;\n }\n}\n\n/* ===========================\n Matrix Evaluation Indicators\n =========================== */\n\n/* Human Feedback Indicators */\n.cell-human {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-human.no-feedback {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-human.no-feedback i {\n font-size: 11px;\n}\n\n.cell-human.has-feedback {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-human.has-feedback i {\n font-size: 9px;\n}\n\n.cell-human.has-feedback .rating-value {\n font-weight: 700;\n font-size: 11px;\n}\n\n/* Human rating color coding: red \u22644, yellow 5-6, light-green 7-8, green 9-10 */\n.cell-human.rating-low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-human.rating-medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-human.rating-good {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-human.rating-excellent {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n/* Auto Score Indicators */\n.cell-auto {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-auto.no-score {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-auto.no-score i {\n font-size: 11px;\n}\n\n.cell-auto.has-score {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-auto.has-score i {\n font-size: 9px;\n}\n\n.cell-auto.has-score .score-value {\n font-weight: 700;\n font-size: 10px;\n}\n\n/* Auto score color coding (0-100%): red <50, yellow 50-69, light-green 70-84, green 85+ */\n.cell-auto.score-low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-auto.score-medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.score-good {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.score-excellent {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n/* Status indicators in matrix cells */\n.cell-status {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-timeout {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped,\n.cell-status.status-pending {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n/* Not-run / Skipped cells with hatch pattern */\n.result-cell.cell-not-run {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--mj-text-disabled);\n}\n\n.result-cell.cell-not-run .cell-eval-stack {\n opacity: 0.6;\n}\n\n.cell-not-run-indicator {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n color: var(--mj-text-disabled);\n font-size: 11px;\n}\n\n/* ===========================\n Matrix Totals Footer Row\n =========================== */\n.test-matrix tfoot {\n position: sticky;\n bottom: 0;\n z-index: 2;\n}\n\n.totals-row {\n background: var(--mj-bg-surface-sunken);\n border-top: 2px solid var(--test-border);\n}\n\n.totals-row td {\n padding: 10px 12px;\n font-weight: 600;\n}\n\n.totals-row .totals-label {\n background: var(--mj-bg-surface-sunken);\n font-size: 12px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.totals-row .totals-cell {\n background: var(--mj-bg-surface-sunken);\n}\n\n.totals-stack {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.totals-status,\n.totals-human,\n.totals-auto {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.totals-status {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.totals-status .pass-count {\n font-weight: 700;\n}\n\n.totals-human {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.totals-human .avg-label {\n font-weight: 700;\n}\n\n.totals-human .count-label {\n font-size: 10px;\n opacity: 0.8;\n}\n\n.totals-auto {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.totals-auto .avg-label {\n font-weight: 700;\n}\n\n.totals-auto .count-label {\n font-size: 10px;\n opacity: 0.8;\n}\n\n/* ===========================\n Editable Overview Form\n =========================== */\n\n.edit-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.edit-section-header {\n margin: 0 0 18px 0;\n}\n\n.edit-section-header h3 {\n margin: 0 0 4px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.edit-section-header h3 i {\n color: var(--test-primary);\n}\n\n.edit-section-sub {\n margin: 0;\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.edit-grid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 18px;\n}\n\n@media (max-width: 720px) {\n .edit-grid {\n grid-template-columns: 1fr;\n }\n}\n\n.edit-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.edit-field--full {\n grid-column: 1 / -1;\n}\n\n.edit-field label {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.edit-field .required {\n color: var(--mj-status-error);\n margin-left: 2px;\n}\n\n.config-textarea {\n resize: vertical;\n min-height: 72px;\n font-family: inherit;\n line-height: 1.5;\n}\n\n.select-wrapper {\n position: relative;\n}\n\n.select-wrapper select.config-input {\n padding-right: 36px;\n appearance: none;\n background-color: var(--test-surface);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%2364748b' d='M1.41 0L6 4.59 10.59 0 12 1.41l-6 6-6-6z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 14px center;\n background-size: 10px 7px;\n}\n\n/* Tag editor (chips + inline input) */\n.tag-editor {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 8px 10px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n transition: var(--test-transition);\n cursor: text;\n min-height: 42px;\n align-items: center;\n}\n\n.tag-editor:focus-within {\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.tag-chip-editable {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 4px 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n border-radius: 999px;\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.tag-chip-editable .tag-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: 10px;\n transition: background 0.15s;\n}\n\n.tag-chip-editable .tag-remove:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-input-inline {\n flex: 1;\n min-width: 140px;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: var(--test-text);\n padding: 4px 2px;\n}\n\n.tag-input-inline::placeholder {\n color: var(--test-text-muted);\n}\n\n/* Read-only metadata section */\n.meta-section {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--test-radius-md);\n padding: 14px 18px;\n border: 1px solid var(--test-border);\n}\n\n.meta-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 14px;\n}\n\n.meta-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.meta-label {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.meta-value {\n font-size: 12px;\n color: var(--test-text-secondary);\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.meta-mono {\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n font-size: 11px;\n}\n\n/* Dirty indicator next to the title */\n.dirty-indicator {\n display: inline-block;\n margin-left: 8px;\n font-size: 14px;\n color: var(--mj-status-warning);\n line-height: 1;\n animation: pulseDot 1.8s ease-in-out infinite;\n vertical-align: middle;\n}\n\n@keyframes pulseDot {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.85); }\n}\n\n.unsaved-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n}\n\n.unsaved-pill i {\n font-size: 6px;\n animation: pulseDot 1.8s ease-in-out infinite;\n}\n\n/* Pad the bottom of the tab content when the save bar is visible\n so the bar doesn't cover the last form field. */\n.tab-content.has-savebar {\n padding-bottom: 84px;\n}\n\n/* ===========================\n Sticky Save Bar\n =========================== */\n\n.save-bar {\n position: absolute;\n left: 16px;\n right: 96px; /* leaves room for the bottom-right chat launcher */\n bottom: 16px;\n z-index: 50;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 12px 16px 12px 20px;\n background: var(--mj-bg-surface-elevated, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--test-border));\n border-radius: 14px;\n box-shadow: 0 12px 32px color-mix(in srgb, var(--mj-status-warning) 10%, rgba(15, 23, 42, 0.18));\n backdrop-filter: blur(8px);\n /* Hidden / off-screen state by default. The .save-bar--visible class\n animates it up into view. Using `transition` (not `animation`)\n guarantees the change runs every time isDirty toggles. */\n opacity: 0;\n transform: translateY(calc(100% + 32px));\n pointer-events: none;\n transition:\n transform 420ms cubic-bezier(0.16, 1, 0.3, 1),\n opacity 260ms cubic-bezier(0.16, 1, 0.3, 1);\n will-change: transform, opacity;\n}\n\n.save-bar--visible {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .save-bar {\n transition: opacity 180ms ease-out;\n transform: none;\n }\n .save-bar--visible {\n transform: none;\n }\n}\n\n.save-bar-message {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.save-bar-dot {\n color: var(--mj-status-warning);\n font-size: 12px;\n line-height: 1;\n animation: pulseDot 1.8s ease-in-out infinite;\n}\n\n.save-bar-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.save-bar-text strong {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.save-bar-fields {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.save-bar-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.save-bar-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n transition: var(--test-transition);\n font-family: inherit;\n}\n\n.save-bar-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.save-bar-btn--primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n}\n\n.save-bar-btn--primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 45%, transparent);\n}\n\n.save-bar-btn--primary:active:not(:disabled) {\n transform: translateY(0);\n}\n\n.save-bar-btn--ghost {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.save-bar-btn--ghost:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n border-color: var(--test-text-muted);\n}\n\n.save-bar-kbd {\n display: inline-flex;\n gap: 3px;\n margin-left: 6px;\n opacity: 0.85;\n}\n\n.save-bar-kbd kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n font-size: 10px;\n font-weight: 600;\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n background: color-mix(in srgb, white 18%, transparent);\n border: 1px solid color-mix(in srgb, white 35%, transparent);\n border-radius: 4px;\n color: inherit;\n}\n\n@media (max-width: 640px) {\n .save-bar {\n left: 8px;\n right: 8px;\n bottom: 88px; /* push above the chat launcher on small screens */\n flex-direction: column;\n align-items: stretch;\n padding: 12px;\n }\n .save-bar-actions {\n justify-content: space-between;\n }\n .save-bar-kbd {\n display: none;\n }\n}\n\n/* ===========================\n Tests Tab \u2014 Action Bar + Drag/Remove\n =========================== */\n\n.tests-actionbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n}\n\n.tests-actionbar-text {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n min-width: 0;\n}\n\n.tests-actionbar-text strong {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.tests-actionbar-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 8px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n font-size: 12px;\n font-weight: 700;\n}\n\n.tests-actionbar-hint {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.tests-actionbar-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n/* Override the default test-item hover translate so drag transforms don't fight it. */\n.tests-list[cdk-drop-list] .test-item:hover,\n.tests-list .test-item.cdk-drag:hover {\n transform: none;\n}\n\n/* The whole row is draggable. .test-content keeps the click-to-open behavior. */\n.test-item.cdk-drag {\n position: relative;\n}\n\n.test-item .test-content {\n cursor: pointer;\n}\n\n/* Drag handle */\n.test-drag-handle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 28px;\n border-radius: 4px;\n color: var(--test-text-muted);\n cursor: grab;\n flex-shrink: 0;\n transition: background 0.15s, color 0.15s;\n user-select: none;\n}\n\n.test-drag-handle:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n}\n\n.test-drag-handle:active,\n.cdk-drag-preview .test-drag-handle {\n cursor: grabbing;\n}\n\n/* Remove (X) button \u2014 hover-revealed */\n.test-remove-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 0.15s, background 0.15s, color 0.15s;\n}\n\n.test-item:hover .test-remove-btn,\n.test-remove-btn:focus-visible {\n opacity: 1;\n}\n\n.test-remove-btn:hover {\n background: color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n color: var(--mj-status-error);\n}\n\n.test-chevron {\n cursor: pointer;\n}\n\n/* Inline remove-confirm */\n.test-remove-confirm {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 4px 8px 4px 12px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n flex-shrink: 0;\n}\n\n.test-remove-confirm-text {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-error-text, var(--mj-status-error));\n}\n\n.test-remove-confirm-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 4px 10px;\n border-radius: 6px;\n border: 1px solid transparent;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.test-remove-confirm-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.test-remove-confirm-btn--danger {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse, white);\n}\n\n.test-remove-confirm-btn--danger:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 88%, black);\n}\n\n.test-remove-confirm-btn--ghost {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.test-remove-confirm-btn--ghost:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n/* CDK drag-drop visuals */\n.cdk-drag-preview {\n box-shadow: 0 12px 32px rgba(15, 23, 42, 0.25);\n border-radius: var(--test-radius-md);\n background: var(--test-surface);\n opacity: 0.95;\n}\n\n.cdk-drag-placeholder {\n opacity: 0;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border: 2px dashed var(--test-primary);\n border-radius: var(--test-radius-md);\n}\n\n.cdk-drag-placeholder * {\n visibility: hidden;\n}\n\n.cdk-drag-animating {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.tests-list.cdk-drop-list-dragging .test-item:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n/* ===========================\n Add Tests Picker Dialog\n =========================== */\n\n.picker-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(15, 23, 42, 0.45);\n z-index: 200;\n animation: pickerFadeIn 180ms ease-out;\n backdrop-filter: blur(2px);\n}\n\n@keyframes pickerFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.picker-dialog {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: min(720px, calc(100vw - 32px));\n max-height: min(80vh, 720px);\n z-index: 201;\n display: flex;\n flex-direction: column;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n box-shadow: 0 24px 64px rgba(15, 23, 42, 0.28);\n animation: pickerSlideUp 220ms cubic-bezier(0.16, 1, 0.3, 1);\n overflow: hidden;\n}\n\n@keyframes pickerSlideUp {\n from {\n opacity: 0;\n transform: translate(-50%, calc(-50% + 16px));\n }\n to {\n opacity: 1;\n transform: translate(-50%, -50%);\n }\n}\n\n.picker-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-title {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.picker-title i {\n color: var(--test-primary);\n}\n\n.picker-close {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 14px;\n transition: background 0.15s, color 0.15s;\n}\n\n.picker-close:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-close:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.picker-search {\n position: relative;\n padding: 14px 20px 0 20px;\n}\n\n.picker-search-icon {\n position: absolute;\n top: 50%;\n left: 32px;\n transform: translateY(-30%);\n color: var(--test-text-muted);\n font-size: 13px;\n pointer-events: none;\n}\n\n.picker-search-input {\n width: 100%;\n padding: 10px 36px 10px 36px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n font-size: 14px;\n color: var(--test-text);\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-search-input:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-search-clear {\n position: absolute;\n top: 50%;\n right: 32px;\n transform: translateY(-30%);\n width: 22px;\n height: 22px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 11px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.picker-search-clear:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-toolbar-status {\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.picker-toolbar-status strong {\n color: var(--mj-brand-primary-hover);\n font-weight: 700;\n}\n\n.picker-toolbar-actions {\n display: flex;\n gap: 14px;\n}\n\n.picker-link-btn {\n border: none;\n background: transparent;\n color: var(--test-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n padding: 0;\n font-family: inherit;\n}\n\n.picker-link-btn:hover:not(:disabled) {\n text-decoration: underline;\n}\n\n.picker-link-btn:disabled {\n color: var(--test-text-muted);\n cursor: not-allowed;\n}\n\n.picker-body {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n min-height: 200px;\n}\n\n.picker-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.picker-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n padding: 40px 20px;\n color: var(--test-text-muted);\n}\n\n.picker-empty i {\n font-size: 32px;\n margin-bottom: 14px;\n color: var(--test-text-muted);\n}\n\n.picker-empty h4 {\n margin: 0 0 6px 0;\n font-size: 15px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.picker-empty p {\n margin: 0;\n font-size: 13px;\n}\n\n.picker-list {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.picker-row {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.12s, border-color 0.12s;\n border: 1px solid transparent;\n}\n\n.picker-row:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n}\n\n.picker-row:focus-visible {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-row--selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--test-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.picker-row--selected:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--test-surface));\n}\n\n.picker-check {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 1.5px solid var(--test-border);\n background: var(--test-surface);\n color: var(--mj-text-inverse, white);\n font-size: 11px;\n flex-shrink: 0;\n transition: background 0.12s, border-color 0.12s;\n}\n\n.picker-row--selected .picker-check {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-row-main {\n flex: 1;\n min-width: 0;\n}\n\n.picker-row-name {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.picker-row-desc {\n font-size: 12px;\n color: var(--test-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: 2px;\n}\n\n.picker-row-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.picker-row-pill {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: 999px;\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-secondary);\n border: 1px solid var(--test-border);\n}\n\n.picker-row-pill--status[data-status=\"active\"] {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n}\n\n.picker-row-pill--status[data-status=\"disabled\"] {\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-muted);\n}\n\n.picker-row-pill--status[data-status=\"pending\"] {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n}\n\n.picker-footer {\n display: flex;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--test-border);\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n}\n\n.picker-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.picker-btn--primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-btn--primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n}\n\n.picker-btn--ghost {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.picker-btn--ghost:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n@media (max-width: 640px) {\n .picker-dialog {\n width: calc(100vw - 16px);\n max-height: calc(100vh - 32px);\n }\n .tests-actionbar {\n flex-direction: column;\n align-items: stretch;\n }\n .tests-actionbar-actions {\n justify-content: flex-end;\n }\n .test-remove-btn {\n opacity: 1; /* always visible on touch */\n }\n}\n\n"] }]
|
|
3538
4394
|
}], null, { chartContainer: [{
|
|
3539
4395
|
type: ViewChild,
|
|
3540
4396
|
args: ['chartContainer']
|
|
3541
4397
|
}], handleKeyboardShortcut: [{
|
|
3542
4398
|
type: HostListener,
|
|
3543
4399
|
args: ['document:keydown', ['$event']]
|
|
4400
|
+
}], handleBeforeUnload: [{
|
|
4401
|
+
type: HostListener,
|
|
4402
|
+
args: ['window:beforeunload', ['$event']]
|
|
3544
4403
|
}] }); })();
|
|
3545
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJTestSuiteFormComponentExtended, { className: "MJTestSuiteFormComponentExtended", filePath: "src/lib/custom/Tests/test-suite-form.component.ts", lineNumber:
|
|
4404
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJTestSuiteFormComponentExtended, { className: "MJTestSuiteFormComponentExtended", filePath: "src/lib/custom/Tests/test-suite-form.component.ts", lineNumber: 32 }); })();
|
|
3546
4405
|
//# sourceMappingURL=test-suite-form.component.js.map
|