@memberjunction/ng-core-entity-forms 5.24.0 → 5.26.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/Entities/entity-form.component.js +177 -152
- package/dist/lib/custom/Entities/entity-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.d.ts +3 -2
- package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.js +260 -233
- package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts +3 -2
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.js +358 -331
- package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
- package/dist/lib/custom/custom-forms.module.d.ts +2 -1
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +7 -3
- package/dist/lib/custom/custom-forms.module.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js +127 -119
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentCategory/mjaiagentcategory.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentCategory/mjaiagentcategory.form.component.js +22 -14
- package/dist/lib/generated/Entities/MJAIAgentCategory/mjaiagentcategory.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentType/mjaiagenttype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentType/mjaiagenttype.form.component.js +17 -9
- package/dist/lib/generated/Entities/MJAIAgentType/mjaiagenttype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.js +26 -8
- package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJApplicationRole/mjapplicationrole.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJApplicationRole/mjapplicationrole.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJApplicationRole/mjapplicationrole.form.component.js +65 -0
- package/dist/lib/generated/Entities/MJApplicationRole/mjapplicationrole.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJArtifactType/mjartifacttype.form.component.js +39 -37
- 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 +43 -27
- package/dist/lib/generated/Entities/MJArtifactVersion/mjartifactversion.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCountry/mjcountry.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJCountry/mjcountry.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJCountry/mjcountry.form.component.js +109 -0
- package/dist/lib/generated/Entities/MJCountry/mjcountry.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js +54 -18
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +335 -297
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js +26 -24
- package/dist/lib/generated/Entities/MJEntityField/mjentityfield.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js +25 -7
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFileStorageAccount/mjfilestorageaccount.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJFileStorageAccount/mjfilestorageaccount.form.component.js +84 -10
- package/dist/lib/generated/Entities/MJFileStorageAccount/mjfilestorageaccount.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFileStorageAccountPermission/mjfilestorageaccountpermission.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJFileStorageAccountPermission/mjfilestorageaccountpermission.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJFileStorageAccountPermission/mjfilestorageaccountpermission.form.component.js +69 -0
- package/dist/lib/generated/Entities/MJFileStorageAccountPermission/mjfilestorageaccountpermission.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJInstanceConfiguration/mjinstanceconfiguration.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJInstanceConfiguration/mjinstanceconfiguration.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJInstanceConfiguration/mjinstanceconfiguration.form.component.js +71 -0
- package/dist/lib/generated/Entities/MJInstanceConfiguration/mjinstanceconfiguration.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRecordGeoCode/mjrecordgeocode.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRecordGeoCode/mjrecordgeocode.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRecordGeoCode/mjrecordgeocode.form.component.js +91 -0
- package/dist/lib/generated/Entities/MJRecordGeoCode/mjrecordgeocode.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js +48 -12
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJSearchProvider/mjsearchprovider.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSearchProvider/mjsearchprovider.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSearchProvider/mjsearchprovider.form.component.js +87 -0
- package/dist/lib/generated/Entities/MJSearchProvider/mjsearchprovider.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJStateProvince/mjstateprovince.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJStateProvince/mjstateprovince.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJStateProvince/mjstateprovince.form.component.js +91 -0
- package/dist/lib/generated/Entities/MJStateProvince/mjstateprovince.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js +130 -112
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJVectorDatabase/mjvectordatabase.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJVectorDatabase/mjvectordatabase.form.component.js +22 -14
- package/dist/lib/generated/Entities/MJVectorDatabase/mjvectordatabase.form.component.js.map +1 -1
- package/dist/lib/generated/generated-forms.module.d.ts +254 -242
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
- package/dist/lib/generated/generated-forms.module.js +167 -116
- package/dist/lib/generated/generated-forms.module.js.map +1 -1
- package/package.json +36 -33
|
@@ -23,12 +23,13 @@ import * as i3 from "@memberjunction/ng-ui-components";
|
|
|
23
23
|
import * as i4 from "@memberjunction/ng-code-editor";
|
|
24
24
|
import * as i5 from "@memberjunction/ng-testing";
|
|
25
25
|
import * as i6 from "@memberjunction/ng-shared-generic";
|
|
26
|
-
import * as i7 from "
|
|
26
|
+
import * as i7 from "@memberjunction/ng-versions";
|
|
27
|
+
import * as i8 from "./entity-link-pill.component";
|
|
27
28
|
const _c0 = () => [1, 2, 3, 4, 5];
|
|
28
29
|
const _c1 = () => [1, 2, 3];
|
|
29
30
|
function MJTestFormComponentExtended_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
30
31
|
i0.ɵɵelementStart(0, "span", 16);
|
|
31
|
-
i0.ɵɵelement(1, "i",
|
|
32
|
+
i0.ɵɵelement(1, "i", 42);
|
|
32
33
|
i0.ɵɵtext(2);
|
|
33
34
|
i0.ɵɵelementEnd();
|
|
34
35
|
} if (rf & 2) {
|
|
@@ -46,31 +47,31 @@ function MJTestFormComponentExtended_Conditional_34_Template(rf, ctx) { if (rf &
|
|
|
46
47
|
i0.ɵɵtextInterpolate(ctx_r0.record.Description);
|
|
47
48
|
} }
|
|
48
49
|
function MJTestFormComponentExtended_Conditional_35_Template(rf, ctx) { if (rf & 1) {
|
|
49
|
-
i0.ɵɵelementStart(0, "div", 22)(1, "div",
|
|
50
|
+
i0.ɵɵelementStart(0, "div", 22)(1, "div", 43)(2, "div", 44);
|
|
50
51
|
i0.ɵɵtext(3, "Total Runs");
|
|
51
52
|
i0.ɵɵelementEnd();
|
|
52
|
-
i0.ɵɵelementStart(4, "div",
|
|
53
|
+
i0.ɵɵelementStart(4, "div", 45);
|
|
53
54
|
i0.ɵɵtext(5);
|
|
54
55
|
i0.ɵɵelementEnd()();
|
|
55
|
-
i0.ɵɵelementStart(6, "div",
|
|
56
|
+
i0.ɵɵelementStart(6, "div", 43)(7, "div", 44);
|
|
56
57
|
i0.ɵɵtext(8, "Pass Rate");
|
|
57
58
|
i0.ɵɵelementEnd();
|
|
58
|
-
i0.ɵɵelementStart(9, "div",
|
|
59
|
+
i0.ɵɵelementStart(9, "div", 45);
|
|
59
60
|
i0.ɵɵtext(10);
|
|
60
61
|
i0.ɵɵelementEnd();
|
|
61
|
-
i0.ɵɵelementStart(11, "div",
|
|
62
|
-
i0.ɵɵelement(12, "div",
|
|
62
|
+
i0.ɵɵelementStart(11, "div", 46);
|
|
63
|
+
i0.ɵɵelement(12, "div", 47);
|
|
63
64
|
i0.ɵɵelementEnd()();
|
|
64
|
-
i0.ɵɵelementStart(13, "div",
|
|
65
|
+
i0.ɵɵelementStart(13, "div", 43)(14, "div", 44);
|
|
65
66
|
i0.ɵɵtext(15, "Avg Cost");
|
|
66
67
|
i0.ɵɵelementEnd();
|
|
67
|
-
i0.ɵɵelementStart(16, "div",
|
|
68
|
+
i0.ɵɵelementStart(16, "div", 45);
|
|
68
69
|
i0.ɵɵtext(17);
|
|
69
70
|
i0.ɵɵelementEnd()();
|
|
70
|
-
i0.ɵɵelementStart(18, "div",
|
|
71
|
+
i0.ɵɵelementStart(18, "div", 43)(19, "div", 44);
|
|
71
72
|
i0.ɵɵtext(20, "Avg Duration");
|
|
72
73
|
i0.ɵɵelementEnd();
|
|
73
|
-
i0.ɵɵelementStart(21, "div",
|
|
74
|
+
i0.ɵɵelementStart(21, "div", 45);
|
|
74
75
|
i0.ɵɵtext(22);
|
|
75
76
|
i0.ɵɵelementEnd()()();
|
|
76
77
|
} if (rf & 2) {
|
|
@@ -106,98 +107,98 @@ function MJTestFormComponentExtended_Conditional_55_Template(rf, ctx) { if (rf &
|
|
|
106
107
|
} }
|
|
107
108
|
function MJTestFormComponentExtended_Conditional_61_Template(rf, ctx) { if (rf & 1) {
|
|
108
109
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
109
|
-
i0.ɵɵelementStart(0, "div", 33)(1, "div",
|
|
110
|
-
i0.ɵɵelement(3, "i",
|
|
110
|
+
i0.ɵɵelementStart(0, "div", 33)(1, "div", 48)(2, "h3");
|
|
111
|
+
i0.ɵɵelement(3, "i", 49);
|
|
111
112
|
i0.ɵɵtext(4, " Test Information");
|
|
112
113
|
i0.ɵɵelementEnd();
|
|
113
|
-
i0.ɵɵelementStart(5, "div",
|
|
114
|
+
i0.ɵɵelementStart(5, "div", 50)(6, "div", 51)(7, "div", 52);
|
|
114
115
|
i0.ɵɵtext(8, "Name");
|
|
115
116
|
i0.ɵɵelementEnd();
|
|
116
|
-
i0.ɵɵelementStart(9, "div",
|
|
117
|
+
i0.ɵɵelementStart(9, "div", 53);
|
|
117
118
|
i0.ɵɵtext(10);
|
|
118
119
|
i0.ɵɵelementEnd()();
|
|
119
|
-
i0.ɵɵelementStart(11, "div",
|
|
120
|
+
i0.ɵɵelementStart(11, "div", 51)(12, "div", 52);
|
|
120
121
|
i0.ɵɵtext(13, "Type");
|
|
121
122
|
i0.ɵɵelementEnd();
|
|
122
|
-
i0.ɵɵelementStart(14, "div",
|
|
123
|
+
i0.ɵɵelementStart(14, "div", 53);
|
|
123
124
|
i0.ɵɵtext(15);
|
|
124
125
|
i0.ɵɵelementEnd()();
|
|
125
|
-
i0.ɵɵelementStart(16, "div",
|
|
126
|
+
i0.ɵɵelementStart(16, "div", 51)(17, "div", 52);
|
|
126
127
|
i0.ɵɵtext(18, "Status");
|
|
127
128
|
i0.ɵɵelementEnd();
|
|
128
|
-
i0.ɵɵelementStart(19, "div",
|
|
129
|
+
i0.ɵɵelementStart(19, "div", 53)(20, "span", 54);
|
|
129
130
|
i0.ɵɵtext(21);
|
|
130
131
|
i0.ɵɵelementEnd()()();
|
|
131
|
-
i0.ɵɵelementStart(22, "div",
|
|
132
|
+
i0.ɵɵelementStart(22, "div", 51)(23, "div", 52);
|
|
132
133
|
i0.ɵɵtext(24, "Priority");
|
|
133
134
|
i0.ɵɵelementEnd();
|
|
134
|
-
i0.ɵɵelementStart(25, "div",
|
|
135
|
+
i0.ɵɵelementStart(25, "div", 53);
|
|
135
136
|
i0.ɵɵtext(26);
|
|
136
137
|
i0.ɵɵelementEnd()();
|
|
137
|
-
i0.ɵɵelementStart(27, "div",
|
|
138
|
+
i0.ɵɵelementStart(27, "div", 51)(28, "div", 52);
|
|
138
139
|
i0.ɵɵtext(29, "Estimated Duration");
|
|
139
140
|
i0.ɵɵelementEnd();
|
|
140
|
-
i0.ɵɵelementStart(30, "div",
|
|
141
|
+
i0.ɵɵelementStart(30, "div", 53);
|
|
141
142
|
i0.ɵɵtext(31);
|
|
142
143
|
i0.ɵɵelementEnd()();
|
|
143
|
-
i0.ɵɵelementStart(32, "div",
|
|
144
|
+
i0.ɵɵelementStart(32, "div", 51)(33, "div", 52);
|
|
144
145
|
i0.ɵɵtext(34, "Estimated Cost");
|
|
145
146
|
i0.ɵɵelementEnd();
|
|
146
|
-
i0.ɵɵelementStart(35, "div",
|
|
147
|
+
i0.ɵɵelementStart(35, "div", 53);
|
|
147
148
|
i0.ɵɵtext(36);
|
|
148
149
|
i0.ɵɵelementEnd()();
|
|
149
|
-
i0.ɵɵelementStart(37, "div",
|
|
150
|
+
i0.ɵɵelementStart(37, "div", 51)(38, "div", 52);
|
|
150
151
|
i0.ɵɵtext(39, "Repeat Count");
|
|
151
152
|
i0.ɵɵelementEnd();
|
|
152
|
-
i0.ɵɵelementStart(40, "div",
|
|
153
|
+
i0.ɵɵelementStart(40, "div", 53);
|
|
153
154
|
i0.ɵɵtext(41);
|
|
154
155
|
i0.ɵɵelementEnd()();
|
|
155
|
-
i0.ɵɵelementStart(42, "div",
|
|
156
|
+
i0.ɵɵelementStart(42, "div", 51)(43, "div", 52);
|
|
156
157
|
i0.ɵɵtext(44, "Max Execution Time");
|
|
157
158
|
i0.ɵɵelementEnd();
|
|
158
|
-
i0.ɵɵelementStart(45, "div",
|
|
159
|
+
i0.ɵɵelementStart(45, "div", 53);
|
|
159
160
|
i0.ɵɵtext(46);
|
|
160
161
|
i0.ɵɵelementEnd()();
|
|
161
|
-
i0.ɵɵelementStart(47, "div",
|
|
162
|
+
i0.ɵɵelementStart(47, "div", 51)(48, "div", 52);
|
|
162
163
|
i0.ɵɵtext(49, "Created");
|
|
163
164
|
i0.ɵɵelementEnd();
|
|
164
|
-
i0.ɵɵelementStart(50, "div",
|
|
165
|
+
i0.ɵɵelementStart(50, "div", 53);
|
|
165
166
|
i0.ɵɵtext(51);
|
|
166
167
|
i0.ɵɵpipe(52, "date");
|
|
167
168
|
i0.ɵɵelementEnd()();
|
|
168
|
-
i0.ɵɵelementStart(53, "div",
|
|
169
|
+
i0.ɵɵelementStart(53, "div", 51)(54, "div", 52);
|
|
169
170
|
i0.ɵɵtext(55, "Updated");
|
|
170
171
|
i0.ɵɵelementEnd();
|
|
171
|
-
i0.ɵɵelementStart(56, "div",
|
|
172
|
+
i0.ɵɵelementStart(56, "div", 53);
|
|
172
173
|
i0.ɵɵtext(57);
|
|
173
174
|
i0.ɵɵpipe(58, "date");
|
|
174
175
|
i0.ɵɵelementEnd()()()();
|
|
175
|
-
i0.ɵɵelementStart(59, "div",
|
|
176
|
-
i0.ɵɵelement(61, "i",
|
|
176
|
+
i0.ɵɵelementStart(59, "div", 55)(60, "h3");
|
|
177
|
+
i0.ɵɵelement(61, "i", 56);
|
|
177
178
|
i0.ɵɵtext(62, " Test Definition");
|
|
178
179
|
i0.ɵɵelementEnd();
|
|
179
|
-
i0.ɵɵelementStart(63, "div",
|
|
180
|
+
i0.ɵɵelementStart(63, "div", 57)(64, "button", 58);
|
|
180
181
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_61_Template_button_click_64_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.setJsonView("input")); });
|
|
181
|
-
i0.ɵɵelement(65, "i",
|
|
182
|
+
i0.ɵɵelement(65, "i", 59);
|
|
182
183
|
i0.ɵɵtext(66, " Input Definition ");
|
|
183
184
|
i0.ɵɵelementEnd();
|
|
184
|
-
i0.ɵɵelementStart(67, "button",
|
|
185
|
+
i0.ɵɵelementStart(67, "button", 58);
|
|
185
186
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_61_Template_button_click_67_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.setJsonView("expected")); });
|
|
186
|
-
i0.ɵɵelement(68, "i",
|
|
187
|
+
i0.ɵɵelement(68, "i", 60);
|
|
187
188
|
i0.ɵɵtext(69, " Expected Outcomes ");
|
|
188
189
|
i0.ɵɵelementEnd();
|
|
189
|
-
i0.ɵɵelementStart(70, "button",
|
|
190
|
+
i0.ɵɵelementStart(70, "button", 58);
|
|
190
191
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_61_Template_button_click_70_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.setJsonView("config")); });
|
|
191
|
-
i0.ɵɵelement(71, "i",
|
|
192
|
+
i0.ɵɵelement(71, "i", 61);
|
|
192
193
|
i0.ɵɵtext(72, " Configuration ");
|
|
193
194
|
i0.ɵɵelementEnd();
|
|
194
|
-
i0.ɵɵelementStart(73, "button",
|
|
195
|
+
i0.ɵɵelementStart(73, "button", 58);
|
|
195
196
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_61_Template_button_click_73_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.setJsonView("tags")); });
|
|
196
|
-
i0.ɵɵelement(74, "i",
|
|
197
|
+
i0.ɵɵelement(74, "i", 62);
|
|
197
198
|
i0.ɵɵtext(75, " Tags ");
|
|
198
199
|
i0.ɵɵelementEnd()();
|
|
199
|
-
i0.ɵɵelementStart(76, "div",
|
|
200
|
-
i0.ɵɵelement(77, "mj-code-editor",
|
|
200
|
+
i0.ɵɵelementStart(76, "div", 63);
|
|
201
|
+
i0.ɵɵelement(77, "mj-code-editor", 64);
|
|
201
202
|
i0.ɵɵelementEnd()()();
|
|
202
203
|
} if (rf & 2) {
|
|
203
204
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -236,69 +237,69 @@ function MJTestFormComponentExtended_Conditional_61_Template(rf, ctx) { if (rf &
|
|
|
236
237
|
} }
|
|
237
238
|
function MJTestFormComponentExtended_Conditional_62_Template(rf, ctx) { if (rf & 1) {
|
|
238
239
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
239
|
-
i0.ɵɵelementStart(0, "div", 34)(1, "div",
|
|
240
|
-
i0.ɵɵelement(3, "i",
|
|
240
|
+
i0.ɵɵelementStart(0, "div", 34)(1, "div", 65)(2, "h3");
|
|
241
|
+
i0.ɵɵelement(3, "i", 66);
|
|
241
242
|
i0.ɵɵtext(4, " Execution Settings");
|
|
242
243
|
i0.ɵɵelementEnd();
|
|
243
|
-
i0.ɵɵelementStart(5, "div",
|
|
244
|
+
i0.ɵɵelementStart(5, "div", 67)(6, "div", 68)(7, "label");
|
|
244
245
|
i0.ɵɵtext(8, "Priority");
|
|
245
246
|
i0.ɵɵelementEnd();
|
|
246
|
-
i0.ɵɵelementStart(9, "input",
|
|
247
|
+
i0.ɵɵelementStart(9, "input", 69);
|
|
247
248
|
i0.ɵɵtwoWayListener("ngModelChange", function MJTestFormComponentExtended_Conditional_62_Template_input_ngModelChange_9_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.record.Priority, $event) || (ctx_r0.record.Priority = $event); return i0.ɵɵresetView($event); });
|
|
248
249
|
i0.ɵɵelementEnd()();
|
|
249
|
-
i0.ɵɵelementStart(10, "div",
|
|
250
|
+
i0.ɵɵelementStart(10, "div", 68)(11, "label");
|
|
250
251
|
i0.ɵɵtext(12, "Repeat Count");
|
|
251
252
|
i0.ɵɵelementEnd();
|
|
252
|
-
i0.ɵɵelementStart(13, "input",
|
|
253
|
+
i0.ɵɵelementStart(13, "input", 70);
|
|
253
254
|
i0.ɵɵtwoWayListener("ngModelChange", function MJTestFormComponentExtended_Conditional_62_Template_input_ngModelChange_13_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.record.RepeatCount, $event) || (ctx_r0.record.RepeatCount = $event); return i0.ɵɵresetView($event); });
|
|
254
255
|
i0.ɵɵelementEnd()();
|
|
255
|
-
i0.ɵɵelementStart(14, "div",
|
|
256
|
+
i0.ɵɵelementStart(14, "div", 68)(15, "label");
|
|
256
257
|
i0.ɵɵtext(16, "Estimated Duration (seconds)");
|
|
257
258
|
i0.ɵɵelementEnd();
|
|
258
|
-
i0.ɵɵelementStart(17, "input",
|
|
259
|
+
i0.ɵɵelementStart(17, "input", 71);
|
|
259
260
|
i0.ɵɵtwoWayListener("ngModelChange", function MJTestFormComponentExtended_Conditional_62_Template_input_ngModelChange_17_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.record.EstimatedDurationSeconds, $event) || (ctx_r0.record.EstimatedDurationSeconds = $event); return i0.ɵɵresetView($event); });
|
|
260
261
|
i0.ɵɵelementEnd()();
|
|
261
|
-
i0.ɵɵelementStart(18, "div",
|
|
262
|
+
i0.ɵɵelementStart(18, "div", 68)(19, "label");
|
|
262
263
|
i0.ɵɵtext(20, "Estimated Cost (USD)");
|
|
263
264
|
i0.ɵɵelementEnd();
|
|
264
|
-
i0.ɵɵelementStart(21, "input",
|
|
265
|
+
i0.ɵɵelementStart(21, "input", 72);
|
|
265
266
|
i0.ɵɵtwoWayListener("ngModelChange", function MJTestFormComponentExtended_Conditional_62_Template_input_ngModelChange_21_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.record.EstimatedCostUSD, $event) || (ctx_r0.record.EstimatedCostUSD = $event); return i0.ɵɵresetView($event); });
|
|
266
267
|
i0.ɵɵelementEnd()();
|
|
267
|
-
i0.ɵɵelementStart(22, "div",
|
|
268
|
+
i0.ɵɵelementStart(22, "div", 73)(23, "label");
|
|
268
269
|
i0.ɵɵtext(24, "Max Execution Time (ms)");
|
|
269
270
|
i0.ɵɵelementEnd();
|
|
270
|
-
i0.ɵɵelementStart(25, "input",
|
|
271
|
+
i0.ɵɵelementStart(25, "input", 74);
|
|
271
272
|
i0.ɵɵtwoWayListener("ngModelChange", function MJTestFormComponentExtended_Conditional_62_Template_input_ngModelChange_25_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.record.MaxExecutionTimeMS, $event) || (ctx_r0.record.MaxExecutionTimeMS = $event); return i0.ɵɵresetView($event); });
|
|
272
273
|
i0.ɵɵelementEnd();
|
|
273
|
-
i0.ɵɵelementStart(26, "span",
|
|
274
|
+
i0.ɵɵelementStart(26, "span", 75);
|
|
274
275
|
i0.ɵɵtext(27, "Leave empty for default 5 minute timeout");
|
|
275
276
|
i0.ɵɵelementEnd()()()();
|
|
276
|
-
i0.ɵɵelementStart(28, "div",
|
|
277
|
-
i0.ɵɵelement(30, "i",
|
|
277
|
+
i0.ɵɵelementStart(28, "div", 65)(29, "h3");
|
|
278
|
+
i0.ɵɵelement(30, "i", 59);
|
|
278
279
|
i0.ɵɵtext(31, " Input Definition (JSON)");
|
|
279
280
|
i0.ɵɵelementEnd();
|
|
280
|
-
i0.ɵɵelementStart(32, "div",
|
|
281
|
+
i0.ɵɵelementStart(32, "div", 76)(33, "mj-code-editor", 77);
|
|
281
282
|
i0.ɵɵlistener("change", function MJTestFormComponentExtended_Conditional_62_Template_mj_code_editor_change_33_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.record.InputDefinition = $event); });
|
|
282
283
|
i0.ɵɵelementEnd()()();
|
|
283
|
-
i0.ɵɵelementStart(34, "div",
|
|
284
|
-
i0.ɵɵelement(36, "i",
|
|
284
|
+
i0.ɵɵelementStart(34, "div", 65)(35, "h3");
|
|
285
|
+
i0.ɵɵelement(36, "i", 60);
|
|
285
286
|
i0.ɵɵtext(37, " Expected Outcomes (JSON)");
|
|
286
287
|
i0.ɵɵelementEnd();
|
|
287
|
-
i0.ɵɵelementStart(38, "div",
|
|
288
|
+
i0.ɵɵelementStart(38, "div", 76)(39, "mj-code-editor", 77);
|
|
288
289
|
i0.ɵɵlistener("change", function MJTestFormComponentExtended_Conditional_62_Template_mj_code_editor_change_39_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.record.ExpectedOutcomes = $event); });
|
|
289
290
|
i0.ɵɵelementEnd()()();
|
|
290
|
-
i0.ɵɵelementStart(40, "div",
|
|
291
|
-
i0.ɵɵelement(42, "i",
|
|
291
|
+
i0.ɵɵelementStart(40, "div", 65)(41, "h3");
|
|
292
|
+
i0.ɵɵelement(42, "i", 61);
|
|
292
293
|
i0.ɵɵtext(43, " Configuration (JSON)");
|
|
293
294
|
i0.ɵɵelementEnd();
|
|
294
|
-
i0.ɵɵelementStart(44, "div",
|
|
295
|
+
i0.ɵɵelementStart(44, "div", 76)(45, "mj-code-editor", 77);
|
|
295
296
|
i0.ɵɵlistener("change", function MJTestFormComponentExtended_Conditional_62_Template_mj_code_editor_change_45_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.record.Configuration = $event); });
|
|
296
297
|
i0.ɵɵelementEnd()()();
|
|
297
|
-
i0.ɵɵelementStart(46, "div",
|
|
298
|
-
i0.ɵɵelement(48, "i",
|
|
298
|
+
i0.ɵɵelementStart(46, "div", 65)(47, "h3");
|
|
299
|
+
i0.ɵɵelement(48, "i", 62);
|
|
299
300
|
i0.ɵɵtext(49, " Tags (JSON Array)");
|
|
300
301
|
i0.ɵɵelementEnd();
|
|
301
|
-
i0.ɵɵelementStart(50, "div",
|
|
302
|
+
i0.ɵɵelementStart(50, "div", 78)(51, "mj-code-editor", 77);
|
|
302
303
|
i0.ɵɵlistener("change", function MJTestFormComponentExtended_Conditional_62_Template_mj_code_editor_change_51_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.record.Tags = $event); });
|
|
303
304
|
i0.ɵɵelementEnd()()()();
|
|
304
305
|
} if (rf & 2) {
|
|
@@ -323,15 +324,15 @@ function MJTestFormComponentExtended_Conditional_62_Template(rf, ctx) { if (rf &
|
|
|
323
324
|
i0.ɵɵproperty("value", ctx_r0.record.Tags || "[]")("readonly", false)("lineWrapping", true);
|
|
324
325
|
} }
|
|
325
326
|
function MJTestFormComponentExtended_Conditional_63_Conditional_1_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
326
|
-
i0.ɵɵelementStart(0, "div",
|
|
327
|
-
i0.ɵɵelement(1, "div",
|
|
328
|
-
i0.ɵɵelementStart(2, "div",
|
|
329
|
-
i0.ɵɵelement(3, "div",
|
|
327
|
+
i0.ɵɵelementStart(0, "div", 83);
|
|
328
|
+
i0.ɵɵelement(1, "div", 84);
|
|
329
|
+
i0.ɵɵelementStart(2, "div", 85);
|
|
330
|
+
i0.ɵɵelement(3, "div", 86)(4, "div", 87);
|
|
330
331
|
i0.ɵɵelementEnd()();
|
|
331
332
|
} }
|
|
332
333
|
function MJTestFormComponentExtended_Conditional_63_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
333
|
-
i0.ɵɵelementStart(0, "div",
|
|
334
|
-
i0.ɵɵrepeaterCreate(2, MJTestFormComponentExtended_Conditional_63_Conditional_1_For_3_Template, 5, 0, "div",
|
|
334
|
+
i0.ɵɵelementStart(0, "div", 79)(1, "div", 82);
|
|
335
|
+
i0.ɵɵrepeaterCreate(2, MJTestFormComponentExtended_Conditional_63_Conditional_1_For_3_Template, 5, 0, "div", 83, i0.ɵɵrepeaterTrackByIdentity);
|
|
335
336
|
i0.ɵɵelementEnd()();
|
|
336
337
|
} if (rf & 2) {
|
|
337
338
|
i0.ɵɵadvance(2);
|
|
@@ -339,7 +340,7 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_1_Template(rf, c
|
|
|
339
340
|
} }
|
|
340
341
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
341
342
|
i0.ɵɵelementStart(0, "span");
|
|
342
|
-
i0.ɵɵelement(1, "i",
|
|
343
|
+
i0.ɵɵelement(1, "i", 103);
|
|
343
344
|
i0.ɵɵtext(2);
|
|
344
345
|
i0.ɵɵelementEnd();
|
|
345
346
|
} if (rf & 2) {
|
|
@@ -350,7 +351,7 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditio
|
|
|
350
351
|
} }
|
|
351
352
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
352
353
|
i0.ɵɵelementStart(0, "span");
|
|
353
|
-
i0.ɵɵelement(1, "i",
|
|
354
|
+
i0.ɵɵelement(1, "i", 104);
|
|
354
355
|
i0.ɵɵtext(2);
|
|
355
356
|
i0.ɵɵelementEnd();
|
|
356
357
|
} if (rf & 2) {
|
|
@@ -360,14 +361,14 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditio
|
|
|
360
361
|
i0.ɵɵtextInterpolate1(" ", ctx_r0.formatCost(run_r5.CostUSD));
|
|
361
362
|
} }
|
|
362
363
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
363
|
-
i0.ɵɵelement(0, "mj-entity-link-pill",
|
|
364
|
+
i0.ɵɵelement(0, "mj-entity-link-pill", 98);
|
|
364
365
|
} if (rf & 2) {
|
|
365
366
|
const run_r5 = i0.ɵɵnextContext().$implicit;
|
|
366
367
|
i0.ɵɵproperty("entityName", run_r5.TargetLogEntity)("recordId", run_r5.TargetLogID);
|
|
367
368
|
} }
|
|
368
369
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
369
|
-
i0.ɵɵelementStart(0, "span",
|
|
370
|
-
i0.ɵɵelement(1, "i",
|
|
370
|
+
i0.ɵɵelementStart(0, "span", 100);
|
|
371
|
+
i0.ɵɵelement(1, "i", 91);
|
|
371
372
|
i0.ɵɵelementStart(2, "span");
|
|
372
373
|
i0.ɵɵtext(3);
|
|
373
374
|
i0.ɵɵelementEnd()();
|
|
@@ -381,13 +382,13 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditio
|
|
|
381
382
|
i0.ɵɵtextInterpolate(run_r5.Status);
|
|
382
383
|
} }
|
|
383
384
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
384
|
-
i0.ɵɵelementStart(0, "span",
|
|
385
|
-
i0.ɵɵelement(1, "i",
|
|
385
|
+
i0.ɵɵelementStart(0, "span", 105);
|
|
386
|
+
i0.ɵɵelement(1, "i", 107);
|
|
386
387
|
i0.ɵɵelementEnd();
|
|
387
388
|
} }
|
|
388
389
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
389
|
-
i0.ɵɵelementStart(0, "span",
|
|
390
|
-
i0.ɵɵelement(1, "i",
|
|
390
|
+
i0.ɵɵelementStart(0, "span", 108);
|
|
391
|
+
i0.ɵɵelement(1, "i", 109);
|
|
391
392
|
i0.ɵɵelementStart(2, "span");
|
|
392
393
|
i0.ɵɵtext(3);
|
|
393
394
|
i0.ɵɵelementEnd()();
|
|
@@ -402,8 +403,8 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditio
|
|
|
402
403
|
i0.ɵɵtextInterpolate(rating_r6);
|
|
403
404
|
} }
|
|
404
405
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
405
|
-
i0.ɵɵconditionalCreate(0, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_Conditional_0_Template, 2, 0, "span",
|
|
406
|
-
i0.ɵɵconditionalCreate(1, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_Conditional_1_Template, 4, 10, "span",
|
|
406
|
+
i0.ɵɵconditionalCreate(0, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_Conditional_0_Template, 2, 0, "span", 105);
|
|
407
|
+
i0.ɵɵconditionalCreate(1, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_Conditional_1_Template, 4, 10, "span", 106);
|
|
407
408
|
} if (rf & 2) {
|
|
408
409
|
let tmp_13_0;
|
|
409
410
|
let tmp_14_0;
|
|
@@ -414,13 +415,13 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditio
|
|
|
414
415
|
i0.ɵɵconditional((tmp_14_0 = (tmp_14_0 = ctx_r0.getFeedbackForRun(run_r5.ID)) == null ? null : tmp_14_0.Rating) ? 1 : -1, tmp_14_0);
|
|
415
416
|
} }
|
|
416
417
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_19_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
417
|
-
i0.ɵɵelementStart(0, "span",
|
|
418
|
-
i0.ɵɵelement(1, "i",
|
|
418
|
+
i0.ɵɵelementStart(0, "span", 110);
|
|
419
|
+
i0.ɵɵelement(1, "i", 112);
|
|
419
420
|
i0.ɵɵelementEnd();
|
|
420
421
|
} }
|
|
421
422
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_19_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
422
|
-
i0.ɵɵelementStart(0, "span",
|
|
423
|
-
i0.ɵɵelement(1, "i",
|
|
423
|
+
i0.ɵɵelementStart(0, "span", 113);
|
|
424
|
+
i0.ɵɵelement(1, "i", 112);
|
|
424
425
|
i0.ɵɵelementStart(2, "span");
|
|
425
426
|
i0.ɵɵtext(3);
|
|
426
427
|
i0.ɵɵelementEnd()();
|
|
@@ -432,8 +433,8 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditio
|
|
|
432
433
|
i0.ɵɵtextInterpolate1("", (run_r5.Score * 100).toFixed(0), "%");
|
|
433
434
|
} }
|
|
434
435
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
435
|
-
i0.ɵɵconditionalCreate(0, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_19_Conditional_0_Template, 2, 0, "span",
|
|
436
|
-
i0.ɵɵconditionalCreate(1, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_19_Conditional_1_Template, 4, 10, "span",
|
|
436
|
+
i0.ɵɵconditionalCreate(0, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_19_Conditional_0_Template, 2, 0, "span", 110);
|
|
437
|
+
i0.ɵɵconditionalCreate(1, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_19_Conditional_1_Template, 4, 10, "span", 111);
|
|
437
438
|
} if (rf & 2) {
|
|
438
439
|
const run_r5 = i0.ɵɵnextContext().$implicit;
|
|
439
440
|
i0.ɵɵconditional(run_r5.Score == null ? 0 : -1);
|
|
@@ -441,7 +442,7 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditio
|
|
|
441
442
|
i0.ɵɵconditional(run_r5.Score != null ? 1 : -1);
|
|
442
443
|
} }
|
|
443
444
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_20_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
444
|
-
i0.ɵɵelementStart(0, "span",
|
|
445
|
+
i0.ɵɵelementStart(0, "span", 114);
|
|
445
446
|
i0.ɵɵtext(1);
|
|
446
447
|
i0.ɵɵelementEnd();
|
|
447
448
|
} if (rf & 2) {
|
|
@@ -450,7 +451,7 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditio
|
|
|
450
451
|
i0.ɵɵtextInterpolate(tag_r7);
|
|
451
452
|
} }
|
|
452
453
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_20_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
453
|
-
i0.ɵɵelementStart(0, "span",
|
|
454
|
+
i0.ɵɵelementStart(0, "span", 115);
|
|
454
455
|
i0.ɵɵtext(1);
|
|
455
456
|
i0.ɵɵelementEnd();
|
|
456
457
|
} if (rf & 2) {
|
|
@@ -460,9 +461,9 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditio
|
|
|
460
461
|
i0.ɵɵtextInterpolate1("+", ctx_r0.getRunTags(run_r5).length - 3);
|
|
461
462
|
} }
|
|
462
463
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
463
|
-
i0.ɵɵelementStart(0, "div",
|
|
464
|
-
i0.ɵɵrepeaterCreate(1, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_20_For_2_Template, 2, 1, "span",
|
|
465
|
-
i0.ɵɵconditionalCreate(3, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_20_Conditional_3_Template, 2, 1, "span",
|
|
464
|
+
i0.ɵɵelementStart(0, "div", 101);
|
|
465
|
+
i0.ɵɵrepeaterCreate(1, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_20_For_2_Template, 2, 1, "span", 114, i0.ɵɵrepeaterTrackByIdentity);
|
|
466
|
+
i0.ɵɵconditionalCreate(3, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_20_Conditional_3_Template, 2, 1, "span", 115);
|
|
466
467
|
i0.ɵɵelementEnd();
|
|
467
468
|
} if (rf & 2) {
|
|
468
469
|
const run_r5 = i0.ɵɵnextContext().$implicit;
|
|
@@ -474,33 +475,33 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditio
|
|
|
474
475
|
} }
|
|
475
476
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
476
477
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
477
|
-
i0.ɵɵelementStart(0, "div",
|
|
478
|
+
i0.ɵɵelementStart(0, "div", 89);
|
|
478
479
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Template_div_click_0_listener() { const run_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.openTestRun(run_r5.ID)); });
|
|
479
|
-
i0.ɵɵelementStart(1, "div",
|
|
480
|
-
i0.ɵɵelement(2, "i",
|
|
480
|
+
i0.ɵɵelementStart(1, "div", 90);
|
|
481
|
+
i0.ɵɵelement(2, "i", 91);
|
|
481
482
|
i0.ɵɵelementEnd();
|
|
482
|
-
i0.ɵɵelementStart(3, "div",
|
|
483
|
+
i0.ɵɵelementStart(3, "div", 92)(4, "div", 93)(5, "span", 94);
|
|
483
484
|
i0.ɵɵtext(6);
|
|
484
485
|
i0.ɵɵelementEnd();
|
|
485
|
-
i0.ɵɵelementStart(7, "span",
|
|
486
|
+
i0.ɵɵelementStart(7, "span", 95);
|
|
486
487
|
i0.ɵɵtext(8);
|
|
487
488
|
i0.ɵɵelementEnd()();
|
|
488
|
-
i0.ɵɵelementStart(9, "div",
|
|
489
|
-
i0.ɵɵelement(11, "i",
|
|
489
|
+
i0.ɵɵelementStart(9, "div", 96)(10, "span");
|
|
490
|
+
i0.ɵɵelement(11, "i", 97);
|
|
490
491
|
i0.ɵɵtext(12);
|
|
491
492
|
i0.ɵɵelementEnd();
|
|
492
493
|
i0.ɵɵconditionalCreate(13, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_13_Template, 3, 1, "span");
|
|
493
494
|
i0.ɵɵconditionalCreate(14, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_14_Template, 3, 1, "span");
|
|
494
|
-
i0.ɵɵconditionalCreate(15, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_15_Template, 1, 2, "mj-entity-link-pill",
|
|
495
|
+
i0.ɵɵconditionalCreate(15, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_15_Template, 1, 2, "mj-entity-link-pill", 98);
|
|
495
496
|
i0.ɵɵelementEnd();
|
|
496
|
-
i0.ɵɵelementStart(16, "div",
|
|
497
|
-
i0.ɵɵconditionalCreate(17, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_17_Template, 4, 17, "span",
|
|
497
|
+
i0.ɵɵelementStart(16, "div", 99);
|
|
498
|
+
i0.ɵɵconditionalCreate(17, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_17_Template, 4, 17, "span", 100);
|
|
498
499
|
i0.ɵɵconditionalCreate(18, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_Template, 2, 2);
|
|
499
500
|
i0.ɵɵconditionalCreate(19, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_19_Template, 2, 2);
|
|
500
501
|
i0.ɵɵelementEnd();
|
|
501
|
-
i0.ɵɵconditionalCreate(20, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_20_Template, 4, 1, "div",
|
|
502
|
+
i0.ɵɵconditionalCreate(20, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_20_Template, 4, 1, "div", 101);
|
|
502
503
|
i0.ɵɵelementEnd();
|
|
503
|
-
i0.ɵɵelement(21, "i",
|
|
504
|
+
i0.ɵɵelement(21, "i", 102);
|
|
504
505
|
i0.ɵɵelementEnd();
|
|
505
506
|
} if (rf & 2) {
|
|
506
507
|
const run_r5 = ctx.$implicit;
|
|
@@ -533,8 +534,8 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Template
|
|
|
533
534
|
i0.ɵɵconditional(ctx_r0.getRunTags(run_r5).length > 0 ? 20 : -1);
|
|
534
535
|
} }
|
|
535
536
|
function MJTestFormComponentExtended_Conditional_63_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
536
|
-
i0.ɵɵelementStart(0, "div",
|
|
537
|
-
i0.ɵɵrepeaterCreate(1, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Template, 22, 26, "div",
|
|
537
|
+
i0.ɵɵelementStart(0, "div", 80);
|
|
538
|
+
i0.ɵɵrepeaterCreate(1, MJTestFormComponentExtended_Conditional_63_Conditional_2_For_2_Template, 22, 26, "div", 88, i0.ɵɵrepeaterTrackByIdentity);
|
|
538
539
|
i0.ɵɵelementEnd();
|
|
539
540
|
} if (rf & 2) {
|
|
540
541
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
@@ -543,8 +544,8 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_2_Template(rf, c
|
|
|
543
544
|
} }
|
|
544
545
|
function MJTestFormComponentExtended_Conditional_63_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
545
546
|
const _r8 = i0.ɵɵgetCurrentView();
|
|
546
|
-
i0.ɵɵelementStart(0, "div",
|
|
547
|
-
i0.ɵɵelement(2, "i",
|
|
547
|
+
i0.ɵɵelementStart(0, "div", 81)(1, "div", 116);
|
|
548
|
+
i0.ɵɵelement(2, "i", 117);
|
|
548
549
|
i0.ɵɵelementEnd();
|
|
549
550
|
i0.ɵɵelementStart(3, "h4");
|
|
550
551
|
i0.ɵɵtext(4, "No Test Runs Yet");
|
|
@@ -560,9 +561,9 @@ function MJTestFormComponentExtended_Conditional_63_Conditional_3_Template(rf, c
|
|
|
560
561
|
} }
|
|
561
562
|
function MJTestFormComponentExtended_Conditional_63_Template(rf, ctx) { if (rf & 1) {
|
|
562
563
|
i0.ɵɵelementStart(0, "div", 35);
|
|
563
|
-
i0.ɵɵconditionalCreate(1, MJTestFormComponentExtended_Conditional_63_Conditional_1_Template, 4, 1, "div",
|
|
564
|
-
i0.ɵɵconditionalCreate(2, MJTestFormComponentExtended_Conditional_63_Conditional_2_Template, 3, 0, "div",
|
|
565
|
-
i0.ɵɵconditionalCreate(3, MJTestFormComponentExtended_Conditional_63_Conditional_3_Template, 10, 0, "div",
|
|
564
|
+
i0.ɵɵconditionalCreate(1, MJTestFormComponentExtended_Conditional_63_Conditional_1_Template, 4, 1, "div", 79);
|
|
565
|
+
i0.ɵɵconditionalCreate(2, MJTestFormComponentExtended_Conditional_63_Conditional_2_Template, 3, 0, "div", 80);
|
|
566
|
+
i0.ɵɵconditionalCreate(3, MJTestFormComponentExtended_Conditional_63_Conditional_3_Template, 10, 0, "div", 81);
|
|
566
567
|
i0.ɵɵelementEnd();
|
|
567
568
|
} if (rf & 2) {
|
|
568
569
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -574,15 +575,15 @@ function MJTestFormComponentExtended_Conditional_63_Template(rf, ctx) { if (rf &
|
|
|
574
575
|
i0.ɵɵconditional(ctx_r0.testRunsLoaded && !ctx_r0.loadingRuns && ctx_r0.testRuns.length === 0 ? 3 : -1);
|
|
575
576
|
} }
|
|
576
577
|
function MJTestFormComponentExtended_Conditional_64_Conditional_1_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
577
|
-
i0.ɵɵelementStart(0, "div",
|
|
578
|
-
i0.ɵɵelement(1, "div",
|
|
579
|
-
i0.ɵɵelementStart(2, "div",
|
|
580
|
-
i0.ɵɵelement(3, "div",
|
|
578
|
+
i0.ɵɵelementStart(0, "div", 83);
|
|
579
|
+
i0.ɵɵelement(1, "div", 84);
|
|
580
|
+
i0.ɵɵelementStart(2, "div", 85);
|
|
581
|
+
i0.ɵɵelement(3, "div", 86)(4, "div", 87);
|
|
581
582
|
i0.ɵɵelementEnd()();
|
|
582
583
|
} }
|
|
583
584
|
function MJTestFormComponentExtended_Conditional_64_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
584
|
-
i0.ɵɵelementStart(0, "div",
|
|
585
|
-
i0.ɵɵrepeaterCreate(2, MJTestFormComponentExtended_Conditional_64_Conditional_1_For_3_Template, 5, 0, "div",
|
|
585
|
+
i0.ɵɵelementStart(0, "div", 79)(1, "div", 82);
|
|
586
|
+
i0.ɵɵrepeaterCreate(2, MJTestFormComponentExtended_Conditional_64_Conditional_1_For_3_Template, 5, 0, "div", 83, i0.ɵɵrepeaterTrackByIdentity);
|
|
586
587
|
i0.ɵɵelementEnd()();
|
|
587
588
|
} if (rf & 2) {
|
|
588
589
|
i0.ɵɵadvance(2);
|
|
@@ -590,7 +591,7 @@ function MJTestFormComponentExtended_Conditional_64_Conditional_1_Template(rf, c
|
|
|
590
591
|
} }
|
|
591
592
|
function MJTestFormComponentExtended_Conditional_64_Conditional_2_For_2_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
592
593
|
i0.ɵɵelementStart(0, "span");
|
|
593
|
-
i0.ɵɵelement(1, "i",
|
|
594
|
+
i0.ɵɵelement(1, "i", 49);
|
|
594
595
|
i0.ɵɵtext(2);
|
|
595
596
|
i0.ɵɵelementEnd();
|
|
596
597
|
} if (rf & 2) {
|
|
@@ -600,21 +601,21 @@ function MJTestFormComponentExtended_Conditional_64_Conditional_2_For_2_Conditio
|
|
|
600
601
|
} }
|
|
601
602
|
function MJTestFormComponentExtended_Conditional_64_Conditional_2_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
602
603
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
603
|
-
i0.ɵɵelementStart(0, "div",
|
|
604
|
+
i0.ɵɵelementStart(0, "div", 120);
|
|
604
605
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_64_Conditional_2_For_2_Template_div_click_0_listener() { const suiteTest_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.openTestSuite(suiteTest_r10.SuiteID)); });
|
|
605
|
-
i0.ɵɵelementStart(1, "div",
|
|
606
|
+
i0.ɵɵelementStart(1, "div", 121);
|
|
606
607
|
i0.ɵɵelement(2, "i", 30);
|
|
607
608
|
i0.ɵɵelementEnd();
|
|
608
|
-
i0.ɵɵelementStart(3, "div",
|
|
609
|
+
i0.ɵɵelementStart(3, "div", 122)(4, "div", 123);
|
|
609
610
|
i0.ɵɵtext(5);
|
|
610
611
|
i0.ɵɵelementEnd();
|
|
611
|
-
i0.ɵɵelementStart(6, "div",
|
|
612
|
-
i0.ɵɵelement(8, "i",
|
|
612
|
+
i0.ɵɵelementStart(6, "div", 124)(7, "span");
|
|
613
|
+
i0.ɵɵelement(8, "i", 125);
|
|
613
614
|
i0.ɵɵtext(9);
|
|
614
615
|
i0.ɵɵelementEnd();
|
|
615
616
|
i0.ɵɵconditionalCreate(10, MJTestFormComponentExtended_Conditional_64_Conditional_2_For_2_Conditional_10_Template, 3, 1, "span");
|
|
616
617
|
i0.ɵɵelementEnd()();
|
|
617
|
-
i0.ɵɵelement(11, "i",
|
|
618
|
+
i0.ɵɵelement(11, "i", 102);
|
|
618
619
|
i0.ɵɵelementEnd();
|
|
619
620
|
} if (rf & 2) {
|
|
620
621
|
const suiteTest_r10 = ctx.$implicit;
|
|
@@ -626,8 +627,8 @@ function MJTestFormComponentExtended_Conditional_64_Conditional_2_For_2_Template
|
|
|
626
627
|
i0.ɵɵconditional(suiteTest_r10.Status ? 10 : -1);
|
|
627
628
|
} }
|
|
628
629
|
function MJTestFormComponentExtended_Conditional_64_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
629
|
-
i0.ɵɵelementStart(0, "div",
|
|
630
|
-
i0.ɵɵrepeaterCreate(1, MJTestFormComponentExtended_Conditional_64_Conditional_2_For_2_Template, 12, 3, "div",
|
|
630
|
+
i0.ɵɵelementStart(0, "div", 118);
|
|
631
|
+
i0.ɵɵrepeaterCreate(1, MJTestFormComponentExtended_Conditional_64_Conditional_2_For_2_Template, 12, 3, "div", 119, i0.ɵɵrepeaterTrackByIdentity);
|
|
631
632
|
i0.ɵɵelementEnd();
|
|
632
633
|
} if (rf & 2) {
|
|
633
634
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
@@ -635,8 +636,8 @@ function MJTestFormComponentExtended_Conditional_64_Conditional_2_Template(rf, c
|
|
|
635
636
|
i0.ɵɵrepeater(ctx_r0.suiteTests);
|
|
636
637
|
} }
|
|
637
638
|
function MJTestFormComponentExtended_Conditional_64_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
638
|
-
i0.ɵɵelementStart(0, "div",
|
|
639
|
-
i0.ɵɵelement(2, "i",
|
|
639
|
+
i0.ɵɵelementStart(0, "div", 81)(1, "div", 116);
|
|
640
|
+
i0.ɵɵelement(2, "i", 126);
|
|
640
641
|
i0.ɵɵelementEnd();
|
|
641
642
|
i0.ɵɵelementStart(3, "h4");
|
|
642
643
|
i0.ɵɵtext(4, "Not Part of Any Suite");
|
|
@@ -647,9 +648,9 @@ function MJTestFormComponentExtended_Conditional_64_Conditional_3_Template(rf, c
|
|
|
647
648
|
} }
|
|
648
649
|
function MJTestFormComponentExtended_Conditional_64_Template(rf, ctx) { if (rf & 1) {
|
|
649
650
|
i0.ɵɵelementStart(0, "div", 36);
|
|
650
|
-
i0.ɵɵconditionalCreate(1, MJTestFormComponentExtended_Conditional_64_Conditional_1_Template, 4, 1, "div",
|
|
651
|
-
i0.ɵɵconditionalCreate(2, MJTestFormComponentExtended_Conditional_64_Conditional_2_Template, 3, 0, "div",
|
|
652
|
-
i0.ɵɵconditionalCreate(3, MJTestFormComponentExtended_Conditional_64_Conditional_3_Template, 7, 0, "div",
|
|
651
|
+
i0.ɵɵconditionalCreate(1, MJTestFormComponentExtended_Conditional_64_Conditional_1_Template, 4, 1, "div", 79);
|
|
652
|
+
i0.ɵɵconditionalCreate(2, MJTestFormComponentExtended_Conditional_64_Conditional_2_Template, 3, 0, "div", 118);
|
|
653
|
+
i0.ɵɵconditionalCreate(3, MJTestFormComponentExtended_Conditional_64_Conditional_3_Template, 7, 0, "div", 81);
|
|
653
654
|
i0.ɵɵelementEnd();
|
|
654
655
|
} if (rf & 2) {
|
|
655
656
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -661,19 +662,19 @@ function MJTestFormComponentExtended_Conditional_64_Template(rf, ctx) { if (rf &
|
|
|
661
662
|
i0.ɵɵconditional(ctx_r0.suiteTestsLoaded && !ctx_r0.loadingSuites && ctx_r0.suiteTests.length === 0 ? 3 : -1);
|
|
662
663
|
} }
|
|
663
664
|
function MJTestFormComponentExtended_Conditional_65_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
664
|
-
i0.ɵɵelementStart(0, "div",
|
|
665
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
665
|
+
i0.ɵɵelementStart(0, "div", 79);
|
|
666
|
+
i0.ɵɵelement(1, "mj-loading", 128);
|
|
666
667
|
i0.ɵɵelementEnd();
|
|
667
668
|
} }
|
|
668
669
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_17_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
669
|
-
i0.ɵɵelementStart(0, "div",
|
|
670
|
-
i0.ɵɵelement(2, "i",
|
|
670
|
+
i0.ɵɵelementStart(0, "div", 137)(1, "div", 142);
|
|
671
|
+
i0.ɵɵelement(2, "i", 143);
|
|
671
672
|
i0.ɵɵelementEnd();
|
|
672
|
-
i0.ɵɵelementStart(3, "div",
|
|
673
|
+
i0.ɵɵelementStart(3, "div", 139)(4, "div", 140);
|
|
673
674
|
i0.ɵɵtext(5);
|
|
674
|
-
i0.ɵɵelement(6, "i",
|
|
675
|
+
i0.ɵɵelement(6, "i", 144);
|
|
675
676
|
i0.ɵɵelementEnd();
|
|
676
|
-
i0.ɵɵelementStart(7, "div",
|
|
677
|
+
i0.ɵɵelementStart(7, "div", 141);
|
|
677
678
|
i0.ɵɵtext(8, "Pass Rate");
|
|
678
679
|
i0.ɵɵelementEnd()()();
|
|
679
680
|
} if (rf & 2) {
|
|
@@ -684,13 +685,13 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_17
|
|
|
684
685
|
i0.ɵɵclassProp("fa-arrow-up", ctx_r0.getPassRateTrend() === "up")("fa-arrow-down", ctx_r0.getPassRateTrend() === "down")("fa-minus", ctx_r0.getPassRateTrend() === "stable")("trend-up", ctx_r0.getPassRateTrend() === "up")("trend-down", ctx_r0.getPassRateTrend() === "down");
|
|
685
686
|
} }
|
|
686
687
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_17_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
687
|
-
i0.ɵɵelementStart(0, "div",
|
|
688
|
-
i0.ɵɵelement(2, "i",
|
|
688
|
+
i0.ɵɵelementStart(0, "div", 137)(1, "div", 138);
|
|
689
|
+
i0.ɵɵelement(2, "i", 145);
|
|
689
690
|
i0.ɵɵelementEnd();
|
|
690
|
-
i0.ɵɵelementStart(3, "div",
|
|
691
|
+
i0.ɵɵelementStart(3, "div", 139)(4, "div", 140);
|
|
691
692
|
i0.ɵɵtext(5);
|
|
692
693
|
i0.ɵɵelementEnd();
|
|
693
|
-
i0.ɵɵelementStart(6, "div",
|
|
694
|
+
i0.ɵɵelementStart(6, "div", 141);
|
|
694
695
|
i0.ɵɵtext(7, "Avg Score");
|
|
695
696
|
i0.ɵɵelementEnd()()();
|
|
696
697
|
} if (rf & 2) {
|
|
@@ -699,33 +700,33 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_17
|
|
|
699
700
|
i0.ɵɵtextInterpolate1("", (ctx_r0.getOverallAvgScore() * 100).toFixed(1), "%");
|
|
700
701
|
} }
|
|
701
702
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
702
|
-
i0.ɵɵelementStart(0, "div",
|
|
703
|
-
i0.ɵɵelement(3, "i",
|
|
703
|
+
i0.ɵɵelementStart(0, "div", 135)(1, "div", 137)(2, "div", 138);
|
|
704
|
+
i0.ɵɵelement(3, "i", 117);
|
|
704
705
|
i0.ɵɵelementEnd();
|
|
705
|
-
i0.ɵɵelementStart(4, "div",
|
|
706
|
+
i0.ɵɵelementStart(4, "div", 139)(5, "div", 140);
|
|
706
707
|
i0.ɵɵtext(6);
|
|
707
708
|
i0.ɵɵelementEnd();
|
|
708
|
-
i0.ɵɵelementStart(7, "div",
|
|
709
|
+
i0.ɵɵelementStart(7, "div", 141);
|
|
709
710
|
i0.ɵɵtext(8, "Total Runs");
|
|
710
711
|
i0.ɵɵelementEnd()()();
|
|
711
|
-
i0.ɵɵconditionalCreate(9, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_17_Conditional_9_Template, 9, 11, "div",
|
|
712
|
-
i0.ɵɵconditionalCreate(10, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_17_Conditional_10_Template, 8, 1, "div",
|
|
713
|
-
i0.ɵɵelementStart(11, "div",
|
|
714
|
-
i0.ɵɵelement(13, "i",
|
|
712
|
+
i0.ɵɵconditionalCreate(9, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_17_Conditional_9_Template, 9, 11, "div", 137);
|
|
713
|
+
i0.ɵɵconditionalCreate(10, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_17_Conditional_10_Template, 8, 1, "div", 137);
|
|
714
|
+
i0.ɵɵelementStart(11, "div", 137)(12, "div", 138);
|
|
715
|
+
i0.ɵɵelement(13, "i", 103);
|
|
715
716
|
i0.ɵɵelementEnd();
|
|
716
|
-
i0.ɵɵelementStart(14, "div",
|
|
717
|
+
i0.ɵɵelementStart(14, "div", 139)(15, "div", 140);
|
|
717
718
|
i0.ɵɵtext(16);
|
|
718
719
|
i0.ɵɵelementEnd();
|
|
719
|
-
i0.ɵɵelementStart(17, "div",
|
|
720
|
+
i0.ɵɵelementStart(17, "div", 141);
|
|
720
721
|
i0.ɵɵtext(18, "Avg Duration");
|
|
721
722
|
i0.ɵɵelementEnd()()();
|
|
722
|
-
i0.ɵɵelementStart(19, "div",
|
|
723
|
-
i0.ɵɵelement(21, "i",
|
|
723
|
+
i0.ɵɵelementStart(19, "div", 137)(20, "div", 138);
|
|
724
|
+
i0.ɵɵelement(21, "i", 104);
|
|
724
725
|
i0.ɵɵelementEnd();
|
|
725
|
-
i0.ɵɵelementStart(22, "div",
|
|
726
|
+
i0.ɵɵelementStart(22, "div", 139)(23, "div", 140);
|
|
726
727
|
i0.ɵɵtext(24);
|
|
727
728
|
i0.ɵɵelementEnd();
|
|
728
|
-
i0.ɵɵelementStart(25, "div",
|
|
729
|
+
i0.ɵɵelementStart(25, "div", 141);
|
|
729
730
|
i0.ɵɵtext(26, "Avg Cost");
|
|
730
731
|
i0.ɵɵelementEnd()()()();
|
|
731
732
|
} if (rf & 2) {
|
|
@@ -762,7 +763,7 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18
|
|
|
762
763
|
i0.ɵɵelementEnd();
|
|
763
764
|
} }
|
|
764
765
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
765
|
-
i0.ɵɵelementStart(0, "td",
|
|
766
|
+
i0.ɵɵelementStart(0, "td", 151);
|
|
766
767
|
i0.ɵɵtext(1);
|
|
767
768
|
i0.ɵɵelementEnd();
|
|
768
769
|
} if (rf & 2) {
|
|
@@ -771,7 +772,7 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18
|
|
|
771
772
|
i0.ɵɵtextInterpolate(day_r12.passCount);
|
|
772
773
|
} }
|
|
773
774
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
774
|
-
i0.ɵɵelementStart(0, "td",
|
|
775
|
+
i0.ɵɵelementStart(0, "td", 152);
|
|
775
776
|
i0.ɵɵtext(1);
|
|
776
777
|
i0.ɵɵelementEnd();
|
|
777
778
|
} if (rf & 2) {
|
|
@@ -780,9 +781,9 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18
|
|
|
780
781
|
i0.ɵɵtextInterpolate(day_r12.failCount);
|
|
781
782
|
} }
|
|
782
783
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
783
|
-
i0.ɵɵelementStart(0, "td",
|
|
784
|
-
i0.ɵɵelement(2, "div",
|
|
785
|
-
i0.ɵɵelementStart(3, "span",
|
|
784
|
+
i0.ɵɵelementStart(0, "td", 153)(1, "div", 157);
|
|
785
|
+
i0.ɵɵelement(2, "div", 158);
|
|
786
|
+
i0.ɵɵelementStart(3, "span", 159);
|
|
786
787
|
i0.ɵɵtext(4);
|
|
787
788
|
i0.ɵɵelementEnd()()();
|
|
788
789
|
} if (rf & 2) {
|
|
@@ -793,7 +794,7 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18
|
|
|
793
794
|
i0.ɵɵtextInterpolate1("", day_r12.passRate.toFixed(1), "%");
|
|
794
795
|
} }
|
|
795
796
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
796
|
-
i0.ɵɵelementStart(0, "td",
|
|
797
|
+
i0.ɵɵelementStart(0, "td", 154);
|
|
797
798
|
i0.ɵɵtext(1);
|
|
798
799
|
i0.ɵɵelementEnd();
|
|
799
800
|
} if (rf & 2) {
|
|
@@ -802,21 +803,21 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18
|
|
|
802
803
|
i0.ɵɵtextInterpolate1("", (day_r12.avgScore * 100).toFixed(1), "%");
|
|
803
804
|
} }
|
|
804
805
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Template(rf, ctx) { if (rf & 1) {
|
|
805
|
-
i0.ɵɵelementStart(0, "tr")(1, "td",
|
|
806
|
+
i0.ɵɵelementStart(0, "tr")(1, "td", 149);
|
|
806
807
|
i0.ɵɵtext(2);
|
|
807
808
|
i0.ɵɵpipe(3, "date");
|
|
808
809
|
i0.ɵɵelementEnd();
|
|
809
|
-
i0.ɵɵelementStart(4, "td",
|
|
810
|
+
i0.ɵɵelementStart(4, "td", 150);
|
|
810
811
|
i0.ɵɵtext(5);
|
|
811
812
|
i0.ɵɵelementEnd();
|
|
812
|
-
i0.ɵɵconditionalCreate(6, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_6_Template, 2, 1, "td",
|
|
813
|
-
i0.ɵɵconditionalCreate(7, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_7_Template, 2, 1, "td",
|
|
814
|
-
i0.ɵɵconditionalCreate(8, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_8_Template, 5, 3, "td",
|
|
815
|
-
i0.ɵɵconditionalCreate(9, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_9_Template, 2, 1, "td",
|
|
816
|
-
i0.ɵɵelementStart(10, "td",
|
|
813
|
+
i0.ɵɵconditionalCreate(6, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_6_Template, 2, 1, "td", 151);
|
|
814
|
+
i0.ɵɵconditionalCreate(7, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_7_Template, 2, 1, "td", 152);
|
|
815
|
+
i0.ɵɵconditionalCreate(8, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_8_Template, 5, 3, "td", 153);
|
|
816
|
+
i0.ɵɵconditionalCreate(9, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_For_22_Conditional_9_Template, 2, 1, "td", 154);
|
|
817
|
+
i0.ɵɵelementStart(10, "td", 155);
|
|
817
818
|
i0.ɵɵtext(11);
|
|
818
819
|
i0.ɵɵelementEnd();
|
|
819
|
-
i0.ɵɵelementStart(12, "td",
|
|
820
|
+
i0.ɵɵelementStart(12, "td", 156);
|
|
820
821
|
i0.ɵɵtext(13);
|
|
821
822
|
i0.ɵɵelementEnd()();
|
|
822
823
|
} if (rf & 2) {
|
|
@@ -840,11 +841,11 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18
|
|
|
840
841
|
i0.ɵɵtextInterpolate(ctx_r0.formatCost(day_r12.avgCost));
|
|
841
842
|
} }
|
|
842
843
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
843
|
-
i0.ɵɵelementStart(0, "div",
|
|
844
|
-
i0.ɵɵelement(2, "i",
|
|
844
|
+
i0.ɵɵelementStart(0, "div", 136)(1, "h3");
|
|
845
|
+
i0.ɵɵelement(2, "i", 146);
|
|
845
846
|
i0.ɵɵtext(3, " Daily Performance");
|
|
846
847
|
i0.ɵɵelementEnd();
|
|
847
|
-
i0.ɵɵelementStart(4, "div",
|
|
848
|
+
i0.ɵɵelementStart(4, "div", 147)(5, "table", 148)(6, "thead")(7, "tr")(8, "th");
|
|
848
849
|
i0.ɵɵtext(9, "Date");
|
|
849
850
|
i0.ɵɵelementEnd();
|
|
850
851
|
i0.ɵɵelementStart(10, "th");
|
|
@@ -877,7 +878,7 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18
|
|
|
877
878
|
i0.ɵɵrepeater(ctx_r0.historyData);
|
|
878
879
|
} }
|
|
879
880
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_4_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
880
|
-
i0.ɵɵelementStart(0, "span",
|
|
881
|
+
i0.ɵɵelementStart(0, "span", 171);
|
|
881
882
|
i0.ɵɵtext(1);
|
|
882
883
|
i0.ɵɵelementEnd();
|
|
883
884
|
} if (rf & 2) {
|
|
@@ -886,7 +887,7 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19
|
|
|
886
887
|
i0.ɵɵtextInterpolate(tag_r15);
|
|
887
888
|
} }
|
|
888
889
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_4_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
889
|
-
i0.ɵɵelementStart(0, "span",
|
|
890
|
+
i0.ɵɵelementStart(0, "span", 172);
|
|
890
891
|
i0.ɵɵtext(1);
|
|
891
892
|
i0.ɵɵelementEnd();
|
|
892
893
|
} if (rf & 2) {
|
|
@@ -895,9 +896,9 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19
|
|
|
895
896
|
i0.ɵɵtextInterpolate1("+", suite_r14.tags.length - 3);
|
|
896
897
|
} }
|
|
897
898
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
898
|
-
i0.ɵɵelementStart(0, "div",
|
|
899
|
-
i0.ɵɵrepeaterCreate(1, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_4_For_2_Template, 2, 1, "span",
|
|
900
|
-
i0.ɵɵconditionalCreate(3, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_4_Conditional_3_Template, 2, 1, "span",
|
|
899
|
+
i0.ɵɵelementStart(0, "div", 165);
|
|
900
|
+
i0.ɵɵrepeaterCreate(1, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_4_For_2_Template, 2, 1, "span", 171, i0.ɵɵrepeaterTrackByIdentity);
|
|
901
|
+
i0.ɵɵconditionalCreate(3, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_4_Conditional_3_Template, 2, 1, "span", 172);
|
|
901
902
|
i0.ɵɵelementEnd();
|
|
902
903
|
} if (rf & 2) {
|
|
903
904
|
const suite_r14 = i0.ɵɵnextContext().$implicit;
|
|
@@ -907,10 +908,10 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19
|
|
|
907
908
|
i0.ɵɵconditional(suite_r14.tags.length > 3 ? 3 : -1);
|
|
908
909
|
} }
|
|
909
910
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
910
|
-
i0.ɵɵelementStart(0, "div",
|
|
911
|
+
i0.ɵɵelementStart(0, "div", 167)(1, "span", 173);
|
|
911
912
|
i0.ɵɵtext(2);
|
|
912
913
|
i0.ɵɵelementEnd();
|
|
913
|
-
i0.ɵɵelementStart(3, "span",
|
|
914
|
+
i0.ɵɵelementStart(3, "span", 169);
|
|
914
915
|
i0.ɵɵtext(4, "Pass Rate");
|
|
915
916
|
i0.ɵɵelementEnd()();
|
|
916
917
|
} if (rf & 2) {
|
|
@@ -921,10 +922,10 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19
|
|
|
921
922
|
i0.ɵɵtextInterpolate1(" ", suite_r14.passRate.toFixed(1), "% ");
|
|
922
923
|
} }
|
|
923
924
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
924
|
-
i0.ɵɵelementStart(0, "div",
|
|
925
|
+
i0.ɵɵelementStart(0, "div", 167)(1, "span", 168);
|
|
925
926
|
i0.ɵɵtext(2);
|
|
926
927
|
i0.ɵɵelementEnd();
|
|
927
|
-
i0.ɵɵelementStart(3, "span",
|
|
928
|
+
i0.ɵɵelementStart(3, "span", 169);
|
|
928
929
|
i0.ɵɵtext(4, "Avg Score");
|
|
929
930
|
i0.ɵɵelementEnd()();
|
|
930
931
|
} if (rf & 2) {
|
|
@@ -933,10 +934,10 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19
|
|
|
933
934
|
i0.ɵɵtextInterpolate1("", (suite_r14.avgScore * 100).toFixed(1), "%");
|
|
934
935
|
} }
|
|
935
936
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
936
|
-
i0.ɵɵelementStart(0, "div",
|
|
937
|
+
i0.ɵɵelementStart(0, "div", 167)(1, "span", 168);
|
|
937
938
|
i0.ɵɵtext(2);
|
|
938
939
|
i0.ɵɵelementEnd();
|
|
939
|
-
i0.ɵɵelementStart(3, "span",
|
|
940
|
+
i0.ɵɵelementStart(3, "span", 169);
|
|
940
941
|
i0.ɵɵtext(4, "Last Run");
|
|
941
942
|
i0.ɵɵelementEnd()();
|
|
942
943
|
} if (rf & 2) {
|
|
@@ -947,36 +948,36 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19
|
|
|
947
948
|
} }
|
|
948
949
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Template(rf, ctx) { if (rf & 1) {
|
|
949
950
|
const _r13 = i0.ɵɵgetCurrentView();
|
|
950
|
-
i0.ɵɵelementStart(0, "div",
|
|
951
|
+
i0.ɵɵelementStart(0, "div", 162);
|
|
951
952
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Template_div_click_0_listener() { const suite_r14 = i0.ɵɵrestoreView(_r13).$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.openSuiteFromHistory(suite_r14.suiteId)); });
|
|
952
|
-
i0.ɵɵelementStart(1, "div",
|
|
953
|
+
i0.ɵɵelementStart(1, "div", 163)(2, "div", 164);
|
|
953
954
|
i0.ɵɵtext(3);
|
|
954
955
|
i0.ɵɵelementEnd();
|
|
955
|
-
i0.ɵɵconditionalCreate(4, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_4_Template, 4, 1, "div",
|
|
956
|
+
i0.ɵɵconditionalCreate(4, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_4_Template, 4, 1, "div", 165);
|
|
956
957
|
i0.ɵɵelementEnd();
|
|
957
|
-
i0.ɵɵelementStart(5, "div",
|
|
958
|
+
i0.ɵɵelementStart(5, "div", 166)(6, "div", 167)(7, "span", 168);
|
|
958
959
|
i0.ɵɵtext(8);
|
|
959
960
|
i0.ɵɵelementEnd();
|
|
960
|
-
i0.ɵɵelementStart(9, "span",
|
|
961
|
+
i0.ɵɵelementStart(9, "span", 169);
|
|
961
962
|
i0.ɵɵtext(10, "Runs");
|
|
962
963
|
i0.ɵɵelementEnd()();
|
|
963
|
-
i0.ɵɵconditionalCreate(11, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_11_Template, 5, 5, "div",
|
|
964
|
-
i0.ɵɵconditionalCreate(12, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_12_Template, 5, 1, "div",
|
|
965
|
-
i0.ɵɵelementStart(13, "div",
|
|
964
|
+
i0.ɵɵconditionalCreate(11, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_11_Template, 5, 5, "div", 167);
|
|
965
|
+
i0.ɵɵconditionalCreate(12, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_12_Template, 5, 1, "div", 167);
|
|
966
|
+
i0.ɵɵelementStart(13, "div", 167)(14, "span", 168);
|
|
966
967
|
i0.ɵɵtext(15);
|
|
967
968
|
i0.ɵɵelementEnd();
|
|
968
|
-
i0.ɵɵelementStart(16, "span",
|
|
969
|
+
i0.ɵɵelementStart(16, "span", 169);
|
|
969
970
|
i0.ɵɵtext(17, "Avg Duration");
|
|
970
971
|
i0.ɵɵelementEnd()();
|
|
971
|
-
i0.ɵɵelementStart(18, "div",
|
|
972
|
+
i0.ɵɵelementStart(18, "div", 167)(19, "span", 168);
|
|
972
973
|
i0.ɵɵtext(20);
|
|
973
974
|
i0.ɵɵelementEnd();
|
|
974
|
-
i0.ɵɵelementStart(21, "span",
|
|
975
|
+
i0.ɵɵelementStart(21, "span", 169);
|
|
975
976
|
i0.ɵɵtext(22, "Avg Cost");
|
|
976
977
|
i0.ɵɵelementEnd()();
|
|
977
|
-
i0.ɵɵconditionalCreate(23, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_23_Template, 5, 1, "div",
|
|
978
|
+
i0.ɵɵconditionalCreate(23, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Conditional_23_Template, 5, 1, "div", 167);
|
|
978
979
|
i0.ɵɵelementEnd();
|
|
979
|
-
i0.ɵɵelement(24, "i",
|
|
980
|
+
i0.ɵɵelement(24, "i", 170);
|
|
980
981
|
i0.ɵɵelementEnd();
|
|
981
982
|
} if (rf & 2) {
|
|
982
983
|
const suite_r14 = ctx.$implicit;
|
|
@@ -999,12 +1000,12 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19
|
|
|
999
1000
|
i0.ɵɵconditional(suite_r14.lastRun ? 23 : -1);
|
|
1000
1001
|
} }
|
|
1001
1002
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
1002
|
-
i0.ɵɵelementStart(0, "div",
|
|
1003
|
+
i0.ɵɵelementStart(0, "div", 136)(1, "h3");
|
|
1003
1004
|
i0.ɵɵelement(2, "i", 30);
|
|
1004
1005
|
i0.ɵɵtext(3, " Performance by Suite");
|
|
1005
1006
|
i0.ɵɵelementEnd();
|
|
1006
|
-
i0.ɵɵelementStart(4, "div",
|
|
1007
|
-
i0.ɵɵrepeaterCreate(5, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Template, 25, 8, "div",
|
|
1007
|
+
i0.ɵɵelementStart(4, "div", 160);
|
|
1008
|
+
i0.ɵɵrepeaterCreate(5, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_For_6_Template, 25, 8, "div", 161, i0.ɵɵrepeaterTrackByIdentity);
|
|
1008
1009
|
i0.ɵɵelementEnd()();
|
|
1009
1010
|
} if (rf & 2) {
|
|
1010
1011
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
@@ -1013,7 +1014,7 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19
|
|
|
1013
1014
|
} }
|
|
1014
1015
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
1015
1016
|
const _r16 = i0.ɵɵgetCurrentView();
|
|
1016
|
-
i0.ɵɵelementStart(0, "div",
|
|
1017
|
+
i0.ɵɵelementStart(0, "div", 81)(1, "div", 116);
|
|
1017
1018
|
i0.ɵɵelement(2, "i", 31);
|
|
1018
1019
|
i0.ɵɵelementEnd();
|
|
1019
1020
|
i0.ɵɵelementStart(3, "h4");
|
|
@@ -1030,34 +1031,34 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_20
|
|
|
1030
1031
|
} }
|
|
1031
1032
|
function MJTestFormComponentExtended_Conditional_65_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1032
1033
|
const _r11 = i0.ɵɵgetCurrentView();
|
|
1033
|
-
i0.ɵɵelementStart(0, "div",
|
|
1034
|
+
i0.ɵɵelementStart(0, "div", 127)(1, "div", 129)(2, "div", 130)(3, "span", 131);
|
|
1034
1035
|
i0.ɵɵtext(4, "Time Range:");
|
|
1035
1036
|
i0.ɵɵelementEnd();
|
|
1036
|
-
i0.ɵɵelementStart(5, "button",
|
|
1037
|
+
i0.ɵɵelementStart(5, "button", 132);
|
|
1037
1038
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_65_Conditional_2_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r11); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.setHistoryTimeRange("7d")); });
|
|
1038
1039
|
i0.ɵɵtext(6, "7 Days");
|
|
1039
1040
|
i0.ɵɵelementEnd();
|
|
1040
|
-
i0.ɵɵelementStart(7, "button",
|
|
1041
|
+
i0.ɵɵelementStart(7, "button", 132);
|
|
1041
1042
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_65_Conditional_2_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r11); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.setHistoryTimeRange("30d")); });
|
|
1042
1043
|
i0.ɵɵtext(8, "30 Days");
|
|
1043
1044
|
i0.ɵɵelementEnd();
|
|
1044
|
-
i0.ɵɵelementStart(9, "button",
|
|
1045
|
+
i0.ɵɵelementStart(9, "button", 132);
|
|
1045
1046
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_65_Conditional_2_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r11); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.setHistoryTimeRange("90d")); });
|
|
1046
1047
|
i0.ɵɵtext(10, "90 Days");
|
|
1047
1048
|
i0.ɵɵelementEnd();
|
|
1048
|
-
i0.ɵɵelementStart(11, "button",
|
|
1049
|
+
i0.ɵɵelementStart(11, "button", 132);
|
|
1049
1050
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_65_Conditional_2_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r11); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.setHistoryTimeRange("all")); });
|
|
1050
1051
|
i0.ɵɵtext(12, "All Time");
|
|
1051
1052
|
i0.ɵɵelementEnd()();
|
|
1052
|
-
i0.ɵɵelementStart(13, "div",
|
|
1053
|
+
i0.ɵɵelementStart(13, "div", 133)(14, "button", 20);
|
|
1053
1054
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_65_Conditional_2_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r11); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.exportHistoryToCSV()); });
|
|
1054
|
-
i0.ɵɵelement(15, "i",
|
|
1055
|
+
i0.ɵɵelement(15, "i", 134);
|
|
1055
1056
|
i0.ɵɵtext(16, " Export CSV ");
|
|
1056
1057
|
i0.ɵɵelementEnd()()();
|
|
1057
|
-
i0.ɵɵconditionalCreate(17, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_17_Template, 27, 5, "div",
|
|
1058
|
-
i0.ɵɵconditionalCreate(18, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_Template, 23, 4, "div",
|
|
1059
|
-
i0.ɵɵconditionalCreate(19, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_Template, 7, 0, "div",
|
|
1060
|
-
i0.ɵɵconditionalCreate(20, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_20_Template, 10, 0, "div",
|
|
1058
|
+
i0.ɵɵconditionalCreate(17, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_17_Template, 27, 5, "div", 135);
|
|
1059
|
+
i0.ɵɵconditionalCreate(18, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_18_Template, 23, 4, "div", 136);
|
|
1060
|
+
i0.ɵɵconditionalCreate(19, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_19_Template, 7, 0, "div", 136);
|
|
1061
|
+
i0.ɵɵconditionalCreate(20, MJTestFormComponentExtended_Conditional_65_Conditional_2_Conditional_20_Template, 10, 0, "div", 81);
|
|
1061
1062
|
i0.ɵɵelementEnd();
|
|
1062
1063
|
} if (rf & 2) {
|
|
1063
1064
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
@@ -1082,8 +1083,8 @@ function MJTestFormComponentExtended_Conditional_65_Conditional_2_Template(rf, c
|
|
|
1082
1083
|
} }
|
|
1083
1084
|
function MJTestFormComponentExtended_Conditional_65_Template(rf, ctx) { if (rf & 1) {
|
|
1084
1085
|
i0.ɵɵelementStart(0, "div", 37);
|
|
1085
|
-
i0.ɵɵconditionalCreate(1, MJTestFormComponentExtended_Conditional_65_Conditional_1_Template, 2, 0, "div",
|
|
1086
|
-
i0.ɵɵconditionalCreate(2, MJTestFormComponentExtended_Conditional_65_Conditional_2_Template, 21, 13, "div",
|
|
1086
|
+
i0.ɵɵconditionalCreate(1, MJTestFormComponentExtended_Conditional_65_Conditional_1_Template, 2, 0, "div", 79);
|
|
1087
|
+
i0.ɵɵconditionalCreate(2, MJTestFormComponentExtended_Conditional_65_Conditional_2_Template, 21, 13, "div", 127);
|
|
1087
1088
|
i0.ɵɵelementEnd();
|
|
1088
1089
|
} if (rf & 2) {
|
|
1089
1090
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -1094,35 +1095,35 @@ function MJTestFormComponentExtended_Conditional_65_Template(rf, ctx) { if (rf &
|
|
|
1094
1095
|
} }
|
|
1095
1096
|
function MJTestFormComponentExtended_Conditional_68_Template(rf, ctx) { if (rf & 1) {
|
|
1096
1097
|
const _r17 = i0.ɵɵgetCurrentView();
|
|
1097
|
-
i0.ɵɵelementStart(0, "div", 40)(1, "div",
|
|
1098
|
+
i0.ɵɵelementStart(0, "div", 40)(1, "div", 174);
|
|
1098
1099
|
i0.ɵɵelement(2, "i", 39);
|
|
1099
1100
|
i0.ɵɵtext(3, " Shortcuts ");
|
|
1100
|
-
i0.ɵɵelementStart(4, "button",
|
|
1101
|
+
i0.ɵɵelementStart(4, "button", 175);
|
|
1101
1102
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Conditional_68_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r17); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.toggleShortcuts()); });
|
|
1102
|
-
i0.ɵɵelement(5, "i",
|
|
1103
|
+
i0.ɵɵelement(5, "i", 176);
|
|
1103
1104
|
i0.ɵɵelementEnd()();
|
|
1104
|
-
i0.ɵɵelementStart(6, "div",
|
|
1105
|
+
i0.ɵɵelementStart(6, "div", 177)(7, "div", 178)(8, "span");
|
|
1105
1106
|
i0.ɵɵtext(9, "Refresh");
|
|
1106
1107
|
i0.ɵɵelementEnd();
|
|
1107
|
-
i0.ɵɵelementStart(10, "span",
|
|
1108
|
+
i0.ɵɵelementStart(10, "span", 179)(11, "kbd");
|
|
1108
1109
|
i0.ɵɵtext(12, "Cmd");
|
|
1109
1110
|
i0.ɵɵelementEnd();
|
|
1110
1111
|
i0.ɵɵelementStart(13, "kbd");
|
|
1111
1112
|
i0.ɵɵtext(14, "R");
|
|
1112
1113
|
i0.ɵɵelementEnd()()();
|
|
1113
|
-
i0.ɵɵelementStart(15, "div",
|
|
1114
|
+
i0.ɵɵelementStart(15, "div", 178)(16, "span");
|
|
1114
1115
|
i0.ɵɵtext(17, "Run Test");
|
|
1115
1116
|
i0.ɵɵelementEnd();
|
|
1116
|
-
i0.ɵɵelementStart(18, "span",
|
|
1117
|
+
i0.ɵɵelementStart(18, "span", 179)(19, "kbd");
|
|
1117
1118
|
i0.ɵɵtext(20, "Cmd");
|
|
1118
1119
|
i0.ɵɵelementEnd();
|
|
1119
1120
|
i0.ɵɵelementStart(21, "kbd");
|
|
1120
1121
|
i0.ɵɵtext(22, "Enter");
|
|
1121
1122
|
i0.ɵɵelementEnd()()();
|
|
1122
|
-
i0.ɵɵelementStart(23, "div",
|
|
1123
|
+
i0.ɵɵelementStart(23, "div", 178)(24, "span");
|
|
1123
1124
|
i0.ɵɵtext(25, "Switch Tabs");
|
|
1124
1125
|
i0.ɵɵelementEnd();
|
|
1125
|
-
i0.ɵɵelementStart(26, "span",
|
|
1126
|
+
i0.ɵɵelementStart(26, "span", 179)(27, "kbd");
|
|
1126
1127
|
i0.ɵɵtext(28, "1");
|
|
1127
1128
|
i0.ɵɵelementEnd();
|
|
1128
1129
|
i0.ɵɵtext(29, "-");
|
|
@@ -1130,6 +1131,19 @@ function MJTestFormComponentExtended_Conditional_68_Template(rf, ctx) { if (rf &
|
|
|
1130
1131
|
i0.ɵɵtext(31, "5");
|
|
1131
1132
|
i0.ɵɵelementEnd()()()()();
|
|
1132
1133
|
} }
|
|
1134
|
+
function MJTestFormComponentExtended_Conditional_69_Template(rf, ctx) { if (rf & 1) {
|
|
1135
|
+
const _r18 = i0.ɵɵgetCurrentView();
|
|
1136
|
+
i0.ɵɵelementStart(0, "mj-slide-panel", 180);
|
|
1137
|
+
i0.ɵɵlistener("Closed", function MJTestFormComponentExtended_Conditional_69_Template_mj_slide_panel_Closed_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnPanelClosed()); });
|
|
1138
|
+
i0.ɵɵelementStart(1, "app-test-run-dialog", 181);
|
|
1139
|
+
i0.ɵɵlistener("PanelClose", function MJTestFormComponentExtended_Conditional_69_Template_app_test_run_dialog_PanelClose_1_listener() { i0.ɵɵrestoreView(_r18); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnPanelClosed()); });
|
|
1140
|
+
i0.ɵɵelementEnd()();
|
|
1141
|
+
} if (rf & 2) {
|
|
1142
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
1143
|
+
i0.ɵɵproperty("Title", (ctx_r0.testingDialogService.PanelOptions == null ? null : ctx_r0.testingDialogService.PanelOptions.testId) ? "Test Execution" : "Run Test")("Resizable", true);
|
|
1144
|
+
i0.ɵɵadvance();
|
|
1145
|
+
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) ?? "test");
|
|
1146
|
+
} }
|
|
1133
1147
|
/** Settings key for keyboard shortcuts visibility */
|
|
1134
1148
|
const SHORTCUTS_SETTINGS_KEY = '__mj.Testing.ShowKeyboardShortcuts';
|
|
1135
1149
|
let MJTestFormComponentExtended = class MJTestFormComponentExtended extends MJTestFormComponent {
|
|
@@ -1188,6 +1202,12 @@ let MJTestFormComponentExtended = class MJTestFormComponentExtended extends MJTe
|
|
|
1188
1202
|
this.evalPreferences = prefs;
|
|
1189
1203
|
this.cdr.markForCheck();
|
|
1190
1204
|
});
|
|
1205
|
+
// Subscribe to panel state changes so the slide panel renders in this form
|
|
1206
|
+
this.testingDialogService.PanelStateChanged$
|
|
1207
|
+
.pipe(takeUntil(this.destroy$))
|
|
1208
|
+
.subscribe(() => {
|
|
1209
|
+
this.cdr.detectChanges();
|
|
1210
|
+
});
|
|
1191
1211
|
if (this.record && this.record.ID) {
|
|
1192
1212
|
this.parseJsonFields();
|
|
1193
1213
|
}
|
|
@@ -1488,6 +1508,10 @@ let MJTestFormComponentExtended = class MJTestFormComponentExtended extends MJTe
|
|
|
1488
1508
|
this.testingDialogService.OpenTestPanel(this.record.ID);
|
|
1489
1509
|
}
|
|
1490
1510
|
}
|
|
1511
|
+
OnPanelClosed() {
|
|
1512
|
+
this.testingDialogService.ClosePanel();
|
|
1513
|
+
this.cdr.markForCheck();
|
|
1514
|
+
}
|
|
1491
1515
|
async refresh() {
|
|
1492
1516
|
this.isRefreshing = true;
|
|
1493
1517
|
this.cdr.markForCheck();
|
|
@@ -1850,7 +1874,7 @@ let MJTestFormComponentExtended = class MJTestFormComponentExtended extends MJTe
|
|
|
1850
1874
|
static { this.ɵfac = /*@__PURE__*/ (() => { let ɵMJTestFormComponentExtended_BaseFactory; return function MJTestFormComponentExtended_Factory(__ngFactoryType__) { return (ɵMJTestFormComponentExtended_BaseFactory || (ɵMJTestFormComponentExtended_BaseFactory = i0.ɵɵgetInheritedFactory(MJTestFormComponentExtended)))(__ngFactoryType__ || MJTestFormComponentExtended); }; })(); }
|
|
1851
1875
|
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJTestFormComponentExtended, selectors: [["mj-test-form"]], hostBindings: function MJTestFormComponentExtended_HostBindings(rf, ctx) { if (rf & 1) {
|
|
1852
1876
|
i0.ɵɵlistener("keydown", function MJTestFormComponentExtended_keydown_HostBindingHandler($event) { return ctx.handleKeyboardShortcut($event); }, i0.ɵɵresolveDocument);
|
|
1853
|
-
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
1877
|
+
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 70, vars: 38, consts: [[1, "test-form"], [1, "test-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-flask"], [1, "header-content"], [1, "header-left"], [1, "test-icon"], [1, "test-info"], [1, "test-meta"], [1, "status-badge", 3, "ngClass"], [1, "fas", 3, "ngClass"], [1, "test-type"], [1, "header-actions"], ["mjButton", "", "variant", "primary", 3, "click"], [1, "fas", "fa-play"], ["mjButton", "", 3, "click", "disabled"], [1, "test-description"], [1, "metrics-bar"], [1, "tabs-container"], ["role", "tablist", 1, "tabs"], ["role", "tab", 1, "tab", 3, "click"], [1, "fas", "fa-th-large"], [1, "fas", "fa-sliders-h"], [1, "fas", "fa-history"], [1, "tab-badge"], [1, "fas", "fa-layer-group"], [1, "fas", "fa-chart-line"], [1, "tab-content"], [1, "overview-tab"], [1, "config-tab"], [1, "runs-tab"], [1, "suites-tab"], [1, "history-tab"], [1, "shortcuts-toggle", 3, "click", "title"], [1, "fas", "fa-keyboard"], [1, "keyboard-shortcuts"], ["Mode", "slide", 3, "Title", "Resizable"], [1, "fas", "fa-tag"], [1, "metric-card"], [1, "metric-label"], [1, "metric-value"], [1, "metric-progress"], [1, "metric-progress-fill"], [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, "json-section"], [1, "fas", "fa-code"], [1, "json-tabs"], [1, "json-tab", 3, "click"], [1, "fas", "fa-sign-in-alt"], [1, "fas", "fa-check-double"], [1, "fas", "fa-cog"], [1, "fas", "fa-tags"], [1, "code-editor-container"], ["language", "json", 3, "value", "readonly", "toolbar", "lineWrapping"], [1, "config-section"], [1, "fas", "fa-cogs"], [1, "config-grid"], [1, "config-item"], ["type", "number", "placeholder", "Lower = Higher Priority", 1, "config-input", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "1", 1, "config-input", 3, "ngModelChange", "ngModel"], ["type", "number", 1, "config-input", 3, "ngModelChange", "ngModel"], ["type", "number", "step", "0.000001", 1, "config-input", 3, "ngModelChange", "ngModel"], [1, "config-item", "full-width"], ["type", "number", "placeholder", "Default: 300000 (5 min)", 1, "config-input", 3, "ngModelChange", "ngModel"], [1, "config-hint"], [1, "config-editor-container"], ["language", "json", 3, "change", "value", "readonly", "lineWrapping"], [1, "config-editor-container", "small"], [1, "loading-state"], [1, "runs-list"], [1, "empty-state"], [1, "skeleton-list"], [1, "skeleton-card"], [1, "skeleton-icon"], [1, "skeleton-content"], [1, "skeleton-line", "wide"], [1, "skeleton-line", "narrow"], [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"], [3, "entityName", "recordId"], [1, "run-eval-stack"], [1, "eval-pill", "status-pill", 3, "ngClass", "title"], [1, "run-tags"], [1, "fas", "fa-chevron-right"], [1, "fas", "fa-clock"], [1, "fas", "fa-dollar-sign"], ["title", "Human Review: No rating submitted yet", 1, "eval-pill", "human-pill", "no-feedback"], [1, "eval-pill", "human-pill", "has-feedback", 3, "rating-low", "rating-medium", "rating-good", "rating-excellent", "title"], [1, "fas", "fa-user-slash"], [1, "eval-pill", "human-pill", "has-feedback", 3, "title"], [1, "fas", "fa-user"], ["title", "Auto Score: No automated score available", 1, "eval-pill", "auto-pill", "no-score"], [1, "eval-pill", "auto-pill", "has-score", 3, "score-low", "score-medium", "score-good", "score-excellent", "title"], [1, "fas", "fa-robot"], [1, "eval-pill", "auto-pill", "has-score", 3, "title"], [1, "run-tag"], [1, "run-tag-more"], [1, "empty-icon"], [1, "fas", "fa-play-circle"], [1, "suites-list"], [1, "suite-item"], [1, "suite-item", 3, "click"], [1, "suite-icon"], [1, "suite-content"], [1, "suite-name"], [1, "suite-meta"], [1, "fas", "fa-sort-numeric-up"], [1, "fas", "fa-folder-open"], [1, "history-content"], ["text", "Loading history..."], [1, "history-filters"], [1, "time-range-filters"], [1, "filter-label"], [1, "filter-btn", 3, "click"], [1, "history-actions"], [1, "fas", "fa-download"], [1, "history-kpi-cards"], [1, "history-section"], [1, "kpi-card"], [1, "kpi-icon"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-icon", "pass-rate"], [1, "fas", "fa-percentage"], [1, "fas", "trend-icon"], [1, "fas", "fa-star"], [1, "fas", "fa-calendar-alt"], [1, "history-table-container"], [1, "history-table"], [1, "date-cell"], [1, "runs-cell"], [1, "passed-cell"], [1, "failed-cell"], [1, "pass-rate-cell"], [1, "score-cell"], [1, "duration-cell"], [1, "cost-cell"], [1, "pass-rate-bar"], [1, "pass-rate-fill"], [1, "pass-rate-text"], [1, "suite-performance-list"], [1, "suite-perf-card"], [1, "suite-perf-card", 3, "click"], [1, "suite-perf-header"], [1, "suite-perf-name"], [1, "suite-perf-tags"], [1, "suite-perf-stats"], [1, "suite-stat"], [1, "stat-value"], [1, "stat-label"], [1, "fas", "fa-chevron-right", "suite-perf-arrow"], [1, "tag-mini"], [1, "tag-more"], [1, "stat-value", "pass-rate"], [1, "shortcuts-header"], ["title", "Hide shortcuts", 1, "shortcuts-close", 3, "click"], [1, "fas", "fa-times"], [1, "shortcut-list"], [1, "shortcut-item"], [1, "shortcut-keys"], ["Mode", "slide", 3, "Closed", "Title", "Resizable"], [3, "PanelClose", "PanelMode", "selectedTestId", "selectedSuiteId", "runMode"]], template: function MJTestFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
|
|
1854
1878
|
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "nav", 2)(3, "ol")(4, "li")(5, "a", 3);
|
|
1855
1879
|
i0.ɵɵlistener("click", function MJTestFormComponentExtended_Template_a_click_5_listener() { return ctx.navigateToTestingDashboard(); });
|
|
1856
1880
|
i0.ɵɵelement(6, "i", 4);
|
|
@@ -1935,6 +1959,7 @@ let MJTestFormComponentExtended = class MJTestFormComponentExtended extends MJTe
|
|
|
1935
1959
|
i0.ɵɵelement(67, "i", 39);
|
|
1936
1960
|
i0.ɵɵelementEnd();
|
|
1937
1961
|
i0.ɵɵconditionalCreate(68, MJTestFormComponentExtended_Conditional_68_Template, 32, 0, "div", 40);
|
|
1962
|
+
i0.ɵɵconditionalCreate(69, MJTestFormComponentExtended_Conditional_69_Template, 2, 6, "mj-slide-panel", 41);
|
|
1938
1963
|
i0.ɵɵelementEnd();
|
|
1939
1964
|
} if (rf & 2) {
|
|
1940
1965
|
i0.ɵɵadvance(13);
|
|
@@ -1994,7 +2019,9 @@ let MJTestFormComponentExtended = class MJTestFormComponentExtended extends MJTe
|
|
|
1994
2019
|
i0.ɵɵproperty("title", ctx.showShortcuts ? "Hide keyboard shortcuts" : "Show keyboard shortcuts");
|
|
1995
2020
|
i0.ɵɵadvance(2);
|
|
1996
2021
|
i0.ɵɵconditional(ctx.showShortcuts ? 68 : -1);
|
|
1997
|
-
} }, dependencies: [i1.NgClass, i2.DefaultValueAccessor, i2.NumberValueAccessor, i2.NgControlStatus, i2.MinValidator, i2.NgModel, i3.MJButtonDirective, i4.CodeEditorComponent, i5.EvaluationModeToggleComponent, i6.LoadingComponent, i7.EntityLinkPillComponent, i1.DatePipe], styles: ["\n\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-primary-dark: var(--mj-brand-primary-hover);\n --test-success: var(--mj-status-success);\n --test-success-light: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n --test-error: var(--mj-status-error);\n --test-error-light: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n --test-warning: var(--mj-status-warning);\n --test-warning-light: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\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-muted);\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\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.test-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, 'Helvetica Neue', Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n\n\n\n\n.test-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\n\n.test-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.test-icon[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n\n\n.test-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.test-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 line-height: 1.2;\n word-wrap: break-word;\n}\n\n.test-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\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 letter-spacing: 0.5px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.status-badge.status-active[_ngcontent-%COMP%] { background: var(--mj-status-success); }\n.status-badge.status-disabled[_ngcontent-%COMP%] { background: var(--mj-text-secondary); }\n.status-badge.status-pending[_ngcontent-%COMP%] { background: var(--mj-status-warning); }\n\n.status-badge-inline[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\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-type[_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.header-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n white-space: nowrap;\n}\n\n\n\n.test-description[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--test-radius-md);\n margin-bottom: 16px;\n border: 1px solid var(--test-border);\n}\n\n.test-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\n\n.metrics-bar[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n gap: 12px;\n}\n\n.metric-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 14px;\n text-align: center;\n transition: var(--test-transition);\n}\n\n.metric-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.metric-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 margin-bottom: 6px;\n}\n\n.metric-value[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n\n\n.metric-progress[_ngcontent-%COMP%] {\n margin-top: 8px;\n height: 4px;\n background: var(--test-border);\n border-radius: 2px;\n overflow: hidden;\n}\n\n.metric-progress-fill[_ngcontent-%COMP%] {\n height: 100%;\n background: var(--mj-status-success);\n border-radius: 2px;\n transition: width 0.5s ease-out;\n}\n\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 -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.tabs[_ngcontent-%COMP%]::-webkit-scrollbar {\n display: none;\n}\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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 15px;\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 transition: var(--test-transition);\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 margin-left: 4px;\n}\n\n\n\n\n\n.tab-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n scroll-behavior: smooth;\n}\n\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\n\n.info-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%] {\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%] {\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 word-wrap: break-word;\n font-weight: 500;\n}\n\n\n\n.json-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.json-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 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.json-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.json-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n margin-bottom: 16px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n flex-wrap: wrap;\n}\n\n.json-tab[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 100px;\n padding: 10px 14px;\n border: none;\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n border-radius: var(--test-radius-sm);\n transition: var(--test-transition);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.json-tab[_ngcontent-%COMP%]:hover {\n color: var(--test-text);\n background: var(--mj-bg-overlay);\n}\n\n.json-tab.active[_ngcontent-%COMP%] {\n background: var(--test-surface);\n color: var(--test-primary);\n font-weight: 600;\n box-shadow: var(--test-shadow-sm);\n}\n\n.json-tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.code-editor-container[_ngcontent-%COMP%] {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n min-height: 200px;\n max-height: 400px;\n}\n\n\n\n\n\n.config-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.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.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.config-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.config-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 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.full-width[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\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 background: var(--test-surface);\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) 10%, transparent);\n}\n\n.config-input[_ngcontent-%COMP%]::placeholder {\n color: var(--test-text-muted);\n}\n\n.config-hint[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--test-text-muted);\n margin-top: 4px;\n}\n\n.config-editor-container[_ngcontent-%COMP%] {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n min-height: 200px;\n}\n\n.config-editor-container.small[_ngcontent-%COMP%] {\n min-height: 100px;\n max-height: 150px;\n}\n\n\n\n\n\n.runs-tab[_ngcontent-%COMP%], \n.suites-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n\n\n.loading-state[_ngcontent-%COMP%] {\n padding: 0;\n}\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-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\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 flex-shrink: 0;\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\n\n.runs-list[_ngcontent-%COMP%], \n.suites-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.run-item[_ngcontent-%COMP%], \n.suite-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.run-item[_ngcontent-%COMP%]:hover, \n.suite-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 box-shadow: var(--test-shadow-sm);\n}\n\n.run-icon[_ngcontent-%COMP%], \n.suite-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\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.suite-icon[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\n}\n\n.run-content[_ngcontent-%COMP%], \n.suite-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.run-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 4px;\n}\n\n.run-id[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-status[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.suite-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-meta[_ngcontent-%COMP%], \n.suite-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: var(--test-text-secondary);\n flex-wrap: wrap;\n}\n\n.run-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%], \n.suite-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.run-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.suite-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 11px;\n}\n\n.run-item[_ngcontent-%COMP%] > i.fa-chevron-right[_ngcontent-%COMP%], \n.suite-item[_ngcontent-%COMP%] > i.fa-chevron-right[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.run-item[_ngcontent-%COMP%]:hover > i.fa-chevron-right[_ngcontent-%COMP%], \n.suite-item[_ngcontent-%COMP%]:hover > i.fa-chevron-right[_ngcontent-%COMP%] {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n\n\n.run-eval-stack[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n\n\n\n.eval-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n transition: var(--test-transition);\n}\n\n.eval-pill[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.eval-pill.status-pill.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.eval-pill.status-pill.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-pill.status-pill.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.eval-pill.status-pill.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.eval-pill.status-pill.status-skipped[_ngcontent-%COMP%], \n.eval-pill.status-pill.status-pending[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-pill.status-pill.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.eval-pill.human-pill.no-feedback[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n padding: 4px 8px;\n}\n\n.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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.eval-pill.auto-pill.no-score[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n padding: 4px 8px;\n}\n\n.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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.run-tags[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n\n.run-tag[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.run-tag-more[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n background: var(--test-border);\n color: var(--test-text-muted);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n}\n\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.no-data[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n color: var(--test-text-muted);\n text-align: center;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n}\n\n.no-data[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.no-data[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\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 color: var(--test-text-secondary);\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}\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-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n font-size: 11px;\n color: var(--test-text);\n}\n\n\n\n\n\n@media (max-width: 1024px) {\n .metrics-bar[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .info-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .config-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .keyboard-shortcuts[_ngcontent-%COMP%], .shortcuts-toggle[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n\n\n\n\n@media (max-width: 768px) {\n .test-form[_ngcontent-%COMP%] {\n height: auto;\n min-height: 100%;\n }\n\n .test-header[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .header-content[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-left[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .test-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n font-size: 20px;\n }\n\n .test-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n\n .test-meta[_ngcontent-%COMP%] {\n gap: 8px;\n }\n\n .status-badge[_ngcontent-%COMP%] {\n padding: 4px 10px;\n font-size: 11px;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .metrics-bar[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n gap: 10px;\n }\n\n .metric-card[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .metric-value[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .tabs[_ngcontent-%COMP%] {\n padding: 0 12px;\n }\n\n .tab[_ngcontent-%COMP%] {\n padding: 12px 14px;\n font-size: 13px;\n gap: 6px;\n }\n\n .tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n\n .tab-shortcut[_ngcontent-%COMP%] {\n display: none;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .info-section[_ngcontent-%COMP%], \n .json-section[_ngcontent-%COMP%], \n .config-section[_ngcontent-%COMP%] {\n padding: 18px;\n }\n\n .info-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .json-tabs[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .json-tab[_ngcontent-%COMP%] {\n min-width: 0;\n justify-content: flex-start;\n }\n\n .run-item[_ngcontent-%COMP%], \n .suite-item[_ngcontent-%COMP%] {\n padding: 14px;\n }\n\n .run-icon[_ngcontent-%COMP%], \n .suite-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 16px;\n }\n\n .run-meta[_ngcontent-%COMP%], \n .suite-meta[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 4px;\n }\n\n .empty-state[_ngcontent-%COMP%] {\n padding: 40px 20px;\n }\n\n .empty-icon[_ngcontent-%COMP%] {\n width: 64px;\n height: 64px;\n }\n\n .empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 28px;\n }\n}\n\n\n\n\n\n@media (max-width: 480px) {\n .test-header[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .header-left[_ngcontent-%COMP%] {\n gap: 12px;\n }\n\n .test-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 18px;\n border-radius: 8px;\n }\n\n .test-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .metrics-bar[_ngcontent-%COMP%] {\n grid-template-columns: 1fr 1fr;\n }\n\n .tabs[_ngcontent-%COMP%] {\n padding: 0 8px;\n }\n\n .tab[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-size: 12px;\n }\n\n .tab-badge[_ngcontent-%COMP%] {\n display: none;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .run-header[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n }\n}\n\n\n\n\n\n@media (hover: none) and (pointer: coarse) {\n .tab[_ngcontent-%COMP%], \n .json-tab[_ngcontent-%COMP%], \n .run-item[_ngcontent-%COMP%], \n .suite-item[_ngcontent-%COMP%] {\n -webkit-tap-highlight-color: transparent;\n }\n\n .run-item[_ngcontent-%COMP%]:active, \n .suite-item[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n transform: scale(0.98);\n }\n\n .tab[_ngcontent-%COMP%]:active, \n .json-tab[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n }\n\n \n\n .tab[_ngcontent-%COMP%] {\n min-height: 48px;\n }\n\n .run-item[_ngcontent-%COMP%], \n .suite-item[_ngcontent-%COMP%] {\n min-height: 64px;\n }\n}\n\n\n\n\n\n@media (prefers-reduced-motion: reduce) {\n *[_ngcontent-%COMP%], \n *[_ngcontent-%COMP%]::before, \n *[_ngcontent-%COMP%]::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n\n .skeleton-icon[_ngcontent-%COMP%], \n .skeleton-line[_ngcontent-%COMP%] {\n animation: none;\n background: var(--mj-border-default);\n }\n}\n\n\n\n\n\n.history-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.history-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n\n\n.history-filters[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n box-shadow: var(--test-shadow-sm);\n}\n\n.time-range-filters[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.filter-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text-secondary);\n margin-right: 4px;\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-light);\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 color: var(--mj-text-inverse);\n border-color: var(--test-primary);\n}\n\n.history-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n\n\n.history-kpi-cards[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 16px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 18px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\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: var(--mj-brand-primary);\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 20px;\n flex-shrink: 0;\n}\n\n.kpi-icon.pass-rate[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 22px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-top: 2px;\n}\n\n.trend-icon[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.trend-icon.trend-up[_ngcontent-%COMP%] {\n color: var(--test-success);\n}\n\n.trend-icon.trend-down[_ngcontent-%COMP%] {\n color: var(--test-error);\n}\n\n\n\n.history-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.history-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: 10px;\n}\n\n.history-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n\n\n.history-table-container[_ngcontent-%COMP%] {\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.history-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 14px;\n}\n\n.history-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n.history-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px 16px;\n text-align: left;\n border-bottom: 1px solid var(--test-border);\n}\n\n.history-table[_ngcontent-%COMP%] th[_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 background: var(--test-bg);\n}\n\n.history-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 3%, transparent);\n}\n\n.date-cell[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--test-text);\n}\n\n.passed-cell[_ngcontent-%COMP%] {\n color: var(--test-success);\n font-weight: 600;\n}\n\n.failed-cell[_ngcontent-%COMP%] {\n color: var(--test-error);\n font-weight: 600;\n}\n\n.pass-rate-cell[_ngcontent-%COMP%] {\n min-width: 120px;\n}\n\n.pass-rate-bar[_ngcontent-%COMP%] {\n position: relative;\n height: 24px;\n background: var(--test-bg);\n border-radius: 12px;\n overflow: hidden;\n}\n\n.pass-rate-fill[_ngcontent-%COMP%] {\n position: absolute;\n left: 0;\n top: 0;\n height: 100%;\n background: var(--mj-status-success);\n border-radius: 12px;\n transition: width 0.5s ease-out;\n}\n\n.pass-rate-text[_ngcontent-%COMP%] {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n font-size: 11px;\n font-weight: 700;\n color: var(--test-text);\n z-index: 1;\n}\n\n\n\n.suite-performance-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.suite-perf-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 18px;\n background: var(--test-bg);\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.suite-perf-card[_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.suite-perf-header[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.suite-perf-name[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 6px;\n}\n\n.suite-perf-tags[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.tag-mini[_ngcontent-%COMP%] {\n display: inline-flex;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.tag-more[_ngcontent-%COMP%] {\n display: inline-flex;\n padding: 2px 8px;\n background: var(--test-border);\n color: var(--test-text-muted);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.suite-perf-stats[_ngcontent-%COMP%] {\n display: flex;\n gap: 24px;\n flex-wrap: wrap;\n}\n\n.suite-stat[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n}\n\n.suite-stat[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.suite-stat[_ngcontent-%COMP%] .stat-value.pass-rate.high[_ngcontent-%COMP%] {\n color: var(--test-success);\n}\n\n.suite-stat[_ngcontent-%COMP%] .stat-value.pass-rate.low[_ngcontent-%COMP%] {\n color: var(--test-error);\n}\n\n.suite-stat[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--test-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.suite-perf-arrow[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.suite-perf-card[_ngcontent-%COMP%]:hover .suite-perf-arrow[_ngcontent-%COMP%] {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n\n\n\n\n@media print {\n .test-form[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n height: auto;\n }\n\n .header-actions[_ngcontent-%COMP%], \n .tabs-container[_ngcontent-%COMP%], \n .keyboard-shortcuts[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n overflow: visible;\n padding: 0;\n }\n\n .info-section[_ngcontent-%COMP%], \n .json-section[_ngcontent-%COMP%], \n .config-section[_ngcontent-%COMP%], \n .empty-state[_ngcontent-%COMP%] {\n break-inside: avoid;\n box-shadow: none;\n border: 1px solid var(--mj-border-default);\n }\n}"], changeDetection: 0 }); }
|
|
2022
|
+
i0.ɵɵadvance();
|
|
2023
|
+
i0.ɵɵconditional(ctx.testingDialogService.IsPanelOpen ? 69 : -1);
|
|
2024
|
+
} }, dependencies: [i1.NgClass, i2.DefaultValueAccessor, i2.NumberValueAccessor, i2.NgControlStatus, i2.MinValidator, i2.NgModel, i3.MJButtonDirective, i4.CodeEditorComponent, i5.TestRunDialogComponent, i5.EvaluationModeToggleComponent, i6.LoadingComponent, i7.MjSlidePanelComponent, i8.EntityLinkPillComponent, i1.DatePipe], styles: ["\n\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-primary-dark: var(--mj-brand-primary-hover);\n --test-success: var(--mj-status-success);\n --test-success-light: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n --test-error: var(--mj-status-error);\n --test-error-light: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n --test-warning: var(--mj-status-warning);\n --test-warning-light: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\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-muted);\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\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.test-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, 'Helvetica Neue', Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n\n\n\n\n.test-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\n\n.test-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.test-icon[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n\n\n.test-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.test-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 line-height: 1.2;\n word-wrap: break-word;\n}\n\n.test-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\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 letter-spacing: 0.5px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.status-badge.status-active[_ngcontent-%COMP%] { background: var(--mj-status-success); }\n.status-badge.status-disabled[_ngcontent-%COMP%] { background: var(--mj-text-secondary); }\n.status-badge.status-pending[_ngcontent-%COMP%] { background: var(--mj-status-warning); }\n\n.status-badge-inline[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\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-type[_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.header-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n white-space: nowrap;\n}\n\n\n\n.test-description[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--test-radius-md);\n margin-bottom: 16px;\n border: 1px solid var(--test-border);\n}\n\n.test-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\n\n.metrics-bar[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n gap: 12px;\n}\n\n.metric-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 14px;\n text-align: center;\n transition: var(--test-transition);\n}\n\n.metric-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.metric-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 margin-bottom: 6px;\n}\n\n.metric-value[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n\n\n.metric-progress[_ngcontent-%COMP%] {\n margin-top: 8px;\n height: 4px;\n background: var(--test-border);\n border-radius: 2px;\n overflow: hidden;\n}\n\n.metric-progress-fill[_ngcontent-%COMP%] {\n height: 100%;\n background: var(--mj-status-success);\n border-radius: 2px;\n transition: width 0.5s ease-out;\n}\n\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 -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.tabs[_ngcontent-%COMP%]::-webkit-scrollbar {\n display: none;\n}\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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 15px;\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 transition: var(--test-transition);\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 margin-left: 4px;\n}\n\n\n\n\n\n.tab-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n scroll-behavior: smooth;\n}\n\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\n\n.info-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%] {\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%] {\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 word-wrap: break-word;\n font-weight: 500;\n}\n\n\n\n.json-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.json-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 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.json-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.json-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n margin-bottom: 16px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n flex-wrap: wrap;\n}\n\n.json-tab[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 100px;\n padding: 10px 14px;\n border: none;\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n border-radius: var(--test-radius-sm);\n transition: var(--test-transition);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.json-tab[_ngcontent-%COMP%]:hover {\n color: var(--test-text);\n background: var(--mj-bg-overlay);\n}\n\n.json-tab.active[_ngcontent-%COMP%] {\n background: var(--test-surface);\n color: var(--test-primary);\n font-weight: 600;\n box-shadow: var(--test-shadow-sm);\n}\n\n.json-tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.code-editor-container[_ngcontent-%COMP%] {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n min-height: 200px;\n max-height: 400px;\n}\n\n\n\n\n\n.config-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.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.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.config-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.config-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 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.full-width[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\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 background: var(--test-surface);\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) 10%, transparent);\n}\n\n.config-input[_ngcontent-%COMP%]::placeholder {\n color: var(--test-text-muted);\n}\n\n.config-hint[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--test-text-muted);\n margin-top: 4px;\n}\n\n.config-editor-container[_ngcontent-%COMP%] {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n min-height: 200px;\n}\n\n.config-editor-container.small[_ngcontent-%COMP%] {\n min-height: 100px;\n max-height: 150px;\n}\n\n\n\n\n\n.runs-tab[_ngcontent-%COMP%], \n.suites-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n\n\n.loading-state[_ngcontent-%COMP%] {\n padding: 0;\n}\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-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\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 flex-shrink: 0;\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\n\n.runs-list[_ngcontent-%COMP%], \n.suites-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.run-item[_ngcontent-%COMP%], \n.suite-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.run-item[_ngcontent-%COMP%]:hover, \n.suite-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 box-shadow: var(--test-shadow-sm);\n}\n\n.run-icon[_ngcontent-%COMP%], \n.suite-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\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.suite-icon[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\n}\n\n.run-content[_ngcontent-%COMP%], \n.suite-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.run-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 4px;\n}\n\n.run-id[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-status[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.suite-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-meta[_ngcontent-%COMP%], \n.suite-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: var(--test-text-secondary);\n flex-wrap: wrap;\n}\n\n.run-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%], \n.suite-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.run-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.suite-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 11px;\n}\n\n.run-item[_ngcontent-%COMP%] > i.fa-chevron-right[_ngcontent-%COMP%], \n.suite-item[_ngcontent-%COMP%] > i.fa-chevron-right[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.run-item[_ngcontent-%COMP%]:hover > i.fa-chevron-right[_ngcontent-%COMP%], \n.suite-item[_ngcontent-%COMP%]:hover > i.fa-chevron-right[_ngcontent-%COMP%] {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n\n\n.run-eval-stack[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n\n\n\n.eval-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n transition: var(--test-transition);\n}\n\n.eval-pill[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.eval-pill.status-pill.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.eval-pill.status-pill.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-pill.status-pill.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.eval-pill.status-pill.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.eval-pill.status-pill.status-skipped[_ngcontent-%COMP%], \n.eval-pill.status-pill.status-pending[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-pill.status-pill.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.eval-pill.human-pill.no-feedback[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n padding: 4px 8px;\n}\n\n.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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.eval-pill.auto-pill.no-score[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n padding: 4px 8px;\n}\n\n.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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.run-tags[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n\n.run-tag[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.run-tag-more[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n background: var(--test-border);\n color: var(--test-text-muted);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n}\n\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.no-data[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n color: var(--test-text-muted);\n text-align: center;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n}\n\n.no-data[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.no-data[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\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 color: var(--test-text-secondary);\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}\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-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n font-size: 11px;\n color: var(--test-text);\n}\n\n\n\n\n\n@media (max-width: 1024px) {\n .metrics-bar[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .info-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .config-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .keyboard-shortcuts[_ngcontent-%COMP%], .shortcuts-toggle[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n\n\n\n\n@media (max-width: 768px) {\n .test-form[_ngcontent-%COMP%] {\n height: auto;\n min-height: 100%;\n }\n\n .test-header[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .header-content[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-left[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .test-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n font-size: 20px;\n }\n\n .test-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n\n .test-meta[_ngcontent-%COMP%] {\n gap: 8px;\n }\n\n .status-badge[_ngcontent-%COMP%] {\n padding: 4px 10px;\n font-size: 11px;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .metrics-bar[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n gap: 10px;\n }\n\n .metric-card[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .metric-value[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .tabs[_ngcontent-%COMP%] {\n padding: 0 12px;\n }\n\n .tab[_ngcontent-%COMP%] {\n padding: 12px 14px;\n font-size: 13px;\n gap: 6px;\n }\n\n .tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n\n .tab-shortcut[_ngcontent-%COMP%] {\n display: none;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .info-section[_ngcontent-%COMP%], \n .json-section[_ngcontent-%COMP%], \n .config-section[_ngcontent-%COMP%] {\n padding: 18px;\n }\n\n .info-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .json-tabs[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .json-tab[_ngcontent-%COMP%] {\n min-width: 0;\n justify-content: flex-start;\n }\n\n .run-item[_ngcontent-%COMP%], \n .suite-item[_ngcontent-%COMP%] {\n padding: 14px;\n }\n\n .run-icon[_ngcontent-%COMP%], \n .suite-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 16px;\n }\n\n .run-meta[_ngcontent-%COMP%], \n .suite-meta[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 4px;\n }\n\n .empty-state[_ngcontent-%COMP%] {\n padding: 40px 20px;\n }\n\n .empty-icon[_ngcontent-%COMP%] {\n width: 64px;\n height: 64px;\n }\n\n .empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 28px;\n }\n}\n\n\n\n\n\n@media (max-width: 480px) {\n .test-header[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .header-left[_ngcontent-%COMP%] {\n gap: 12px;\n }\n\n .test-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 18px;\n border-radius: 8px;\n }\n\n .test-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .metrics-bar[_ngcontent-%COMP%] {\n grid-template-columns: 1fr 1fr;\n }\n\n .tabs[_ngcontent-%COMP%] {\n padding: 0 8px;\n }\n\n .tab[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-size: 12px;\n }\n\n .tab-badge[_ngcontent-%COMP%] {\n display: none;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .run-header[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n }\n}\n\n\n\n\n\n@media (hover: none) and (pointer: coarse) {\n .tab[_ngcontent-%COMP%], \n .json-tab[_ngcontent-%COMP%], \n .run-item[_ngcontent-%COMP%], \n .suite-item[_ngcontent-%COMP%] {\n -webkit-tap-highlight-color: transparent;\n }\n\n .run-item[_ngcontent-%COMP%]:active, \n .suite-item[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n transform: scale(0.98);\n }\n\n .tab[_ngcontent-%COMP%]:active, \n .json-tab[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n }\n\n \n\n .tab[_ngcontent-%COMP%] {\n min-height: 48px;\n }\n\n .run-item[_ngcontent-%COMP%], \n .suite-item[_ngcontent-%COMP%] {\n min-height: 64px;\n }\n}\n\n\n\n\n\n@media (prefers-reduced-motion: reduce) {\n *[_ngcontent-%COMP%], \n *[_ngcontent-%COMP%]::before, \n *[_ngcontent-%COMP%]::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n\n .skeleton-icon[_ngcontent-%COMP%], \n .skeleton-line[_ngcontent-%COMP%] {\n animation: none;\n background: var(--mj-border-default);\n }\n}\n\n\n\n\n\n.history-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.history-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n\n\n.history-filters[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n box-shadow: var(--test-shadow-sm);\n}\n\n.time-range-filters[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.filter-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text-secondary);\n margin-right: 4px;\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-light);\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 color: var(--mj-text-inverse);\n border-color: var(--test-primary);\n}\n\n.history-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n\n\n.history-kpi-cards[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 16px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 18px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\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: var(--mj-brand-primary);\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 20px;\n flex-shrink: 0;\n}\n\n.kpi-icon.pass-rate[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 22px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-top: 2px;\n}\n\n.trend-icon[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.trend-icon.trend-up[_ngcontent-%COMP%] {\n color: var(--test-success);\n}\n\n.trend-icon.trend-down[_ngcontent-%COMP%] {\n color: var(--test-error);\n}\n\n\n\n.history-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.history-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: 10px;\n}\n\n.history-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n\n\n.history-table-container[_ngcontent-%COMP%] {\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.history-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 14px;\n}\n\n.history-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n.history-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px 16px;\n text-align: left;\n border-bottom: 1px solid var(--test-border);\n}\n\n.history-table[_ngcontent-%COMP%] th[_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 background: var(--test-bg);\n}\n\n.history-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 3%, transparent);\n}\n\n.date-cell[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--test-text);\n}\n\n.passed-cell[_ngcontent-%COMP%] {\n color: var(--test-success);\n font-weight: 600;\n}\n\n.failed-cell[_ngcontent-%COMP%] {\n color: var(--test-error);\n font-weight: 600;\n}\n\n.pass-rate-cell[_ngcontent-%COMP%] {\n min-width: 120px;\n}\n\n.pass-rate-bar[_ngcontent-%COMP%] {\n position: relative;\n height: 24px;\n background: var(--test-bg);\n border-radius: 12px;\n overflow: hidden;\n}\n\n.pass-rate-fill[_ngcontent-%COMP%] {\n position: absolute;\n left: 0;\n top: 0;\n height: 100%;\n background: var(--mj-status-success);\n border-radius: 12px;\n transition: width 0.5s ease-out;\n}\n\n.pass-rate-text[_ngcontent-%COMP%] {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n font-size: 11px;\n font-weight: 700;\n color: var(--test-text);\n z-index: 1;\n}\n\n\n\n.suite-performance-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.suite-perf-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 18px;\n background: var(--test-bg);\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.suite-perf-card[_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.suite-perf-header[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.suite-perf-name[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 6px;\n}\n\n.suite-perf-tags[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.tag-mini[_ngcontent-%COMP%] {\n display: inline-flex;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.tag-more[_ngcontent-%COMP%] {\n display: inline-flex;\n padding: 2px 8px;\n background: var(--test-border);\n color: var(--test-text-muted);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.suite-perf-stats[_ngcontent-%COMP%] {\n display: flex;\n gap: 24px;\n flex-wrap: wrap;\n}\n\n.suite-stat[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n}\n\n.suite-stat[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.suite-stat[_ngcontent-%COMP%] .stat-value.pass-rate.high[_ngcontent-%COMP%] {\n color: var(--test-success);\n}\n\n.suite-stat[_ngcontent-%COMP%] .stat-value.pass-rate.low[_ngcontent-%COMP%] {\n color: var(--test-error);\n}\n\n.suite-stat[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--test-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.suite-perf-arrow[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.suite-perf-card[_ngcontent-%COMP%]:hover .suite-perf-arrow[_ngcontent-%COMP%] {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n\n\n\n\n@media print {\n .test-form[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n height: auto;\n }\n\n .header-actions[_ngcontent-%COMP%], \n .tabs-container[_ngcontent-%COMP%], \n .keyboard-shortcuts[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n overflow: visible;\n padding: 0;\n }\n\n .info-section[_ngcontent-%COMP%], \n .json-section[_ngcontent-%COMP%], \n .config-section[_ngcontent-%COMP%], \n .empty-state[_ngcontent-%COMP%] {\n break-inside: avoid;\n box-shadow: none;\n border: 1px solid var(--mj-border-default);\n }\n}"], changeDetection: 0 }); }
|
|
1998
2025
|
};
|
|
1999
2026
|
MJTestFormComponentExtended = __decorate([
|
|
2000
2027
|
RegisterClass(BaseFormComponent, 'MJ: Tests')
|
|
@@ -2002,7 +2029,7 @@ MJTestFormComponentExtended = __decorate([
|
|
|
2002
2029
|
export { MJTestFormComponentExtended };
|
|
2003
2030
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJTestFormComponentExtended, [{
|
|
2004
2031
|
type: Component,
|
|
2005
|
-
args: [{ standalone: false, selector: 'mj-test-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"test-form\">\n <!-- Header Section -->\n <div class=\"test-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-flask\"></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=\"test-icon\" [style.background-color]=\"getStatusColor()\">\n <i class=\"fas fa-flask\"></i>\n </div>\n <div class=\"test-info\">\n <h1>{{ record.Name }}</h1>\n <div class=\"test-meta\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass()\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon()\"></i>\n {{ record.Status }}\n </span>\n @if (record.Type) {\n <span class=\"test-type\">\n <i class=\"fas fa-tag\"></i>\n {{ record.Type }}\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)=\"runTest()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Test\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\n <!-- Test Description -->\n @if (record.Description) {\n <div class=\"test-description\">\n <p>{{ record.Description }}</p>\n </div>\n }\n\n <!-- Metrics Bar -->\n @if (testRunsLoaded && testRuns.length > 0) {\n <div class=\"metrics-bar\">\n <div class=\"metric-card\">\n <div class=\"metric-label\">Total Runs</div>\n <div class=\"metric-value\">{{ testRuns.length }}</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-label\">Pass Rate</div>\n <div class=\"metric-value\">{{ getPassRate().toFixed(1) }}%</div>\n <div class=\"metric-progress\">\n <div class=\"metric-progress-fill\" [style.width.%]=\"getPassRate()\"></div>\n </div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-label\">Avg Cost</div>\n <div class=\"metric-value\">{{ formatCost(getAverageCost()) }}</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-label\">Avg Duration</div>\n <div class=\"metric-value\">{{ formatDuration(getAverageDuration()) }}</div>\n </div>\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>\n <span>Overview</span>\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'config'\"\n (click)=\"changeTab('config')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'config'\">\n <i class=\"fas fa-sliders-h\"></i>\n <span>Configuration</span>\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>\n <span>Runs</span>\n @if (testRunsLoaded) {\n <span class=\"tab-badge\">{{ testRuns.length }}</span>\n }\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'suites'\"\n (click)=\"changeTab('suites')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'suites'\">\n <i class=\"fas fa-layer-group\"></i>\n <span>Test Suites</span>\n @if (suiteTestsLoaded) {\n <span class=\"tab-badge\">{{ suiteTests.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>\n <span>Analytics</span>\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 <!-- Basic Information -->\n <div class=\"info-section\">\n <h3><i class=\"fas fa-info-circle\"></i> Test 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\">Type</div>\n <div class=\"info-value\">{{ record.Type || 'N/A' }}</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\">Priority</div>\n <div class=\"info-value\">{{ record.Priority || 'N/A' }}</div>\n </div>\n <div class=\"info-item\">\n <div class=\"info-label\">Estimated Duration</div>\n <div class=\"info-value\">{{ record.EstimatedDurationSeconds ? formatDuration(record.EstimatedDurationSeconds) : 'N/A' }}</div>\n </div>\n <div class=\"info-item\">\n <div class=\"info-label\">Estimated Cost</div>\n <div class=\"info-value\">{{ record.EstimatedCostUSD ? formatCost(record.EstimatedCostUSD) : 'N/A' }}</div>\n </div>\n <div class=\"info-item\">\n <div class=\"info-label\">Repeat Count</div>\n <div class=\"info-value\">{{ record.RepeatCount || 1 }}</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 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>\n </div>\n <!-- JSON Data Views -->\n <div class=\"json-section\">\n <h3><i class=\"fas fa-code\"></i> Test Definition</h3>\n <div class=\"json-tabs\">\n <button class=\"json-tab\"\n [class.active]=\"activeJsonView === 'input'\"\n (click)=\"setJsonView('input')\">\n <i class=\"fas fa-sign-in-alt\"></i>\n Input Definition\n </button>\n <button class=\"json-tab\"\n [class.active]=\"activeJsonView === 'expected'\"\n (click)=\"setJsonView('expected')\">\n <i class=\"fas fa-check-double\"></i>\n Expected Outcomes\n </button>\n <button class=\"json-tab\"\n [class.active]=\"activeJsonView === 'config'\"\n (click)=\"setJsonView('config')\">\n <i class=\"fas fa-cog\"></i>\n Configuration\n </button>\n <button class=\"json-tab\"\n [class.active]=\"activeJsonView === 'tags'\"\n (click)=\"setJsonView('tags')\">\n <i class=\"fas fa-tags\"></i>\n Tags\n </button>\n </div>\n <div class=\"code-editor-container\">\n <mj-code-editor\n [value]=\"getJsonData()\"\n language=\"json\"\n [readonly]=\"true\"\n [toolbar]=\"jsonToolbar\"\n [lineWrapping]=\"true\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n }\n\n <!-- Configuration Tab -->\n @if (activeTab === 'config') {\n <div class=\"config-tab\">\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>Priority</label>\n <input type=\"number\" [(ngModel)]=\"record.Priority\" class=\"config-input\" placeholder=\"Lower = Higher Priority\" />\n </div>\n <div class=\"config-item\">\n <label>Repeat Count</label>\n <input type=\"number\" [(ngModel)]=\"record.RepeatCount\" class=\"config-input\" min=\"1\" />\n </div>\n <div class=\"config-item\">\n <label>Estimated Duration (seconds)</label>\n <input type=\"number\" [(ngModel)]=\"record.EstimatedDurationSeconds\" class=\"config-input\" />\n </div>\n <div class=\"config-item\">\n <label>Estimated Cost (USD)</label>\n <input type=\"number\" step=\"0.000001\" [(ngModel)]=\"record.EstimatedCostUSD\" class=\"config-input\" />\n </div>\n <div class=\"config-item full-width\">\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\">Leave empty for default 5 minute timeout</span>\n </div>\n </div>\n </div>\n <div class=\"config-section\">\n <h3><i class=\"fas fa-sign-in-alt\"></i> Input Definition (JSON)</h3>\n <div class=\"config-editor-container\">\n <mj-code-editor\n [value]=\"record.InputDefinition || ''\"\n language=\"json\"\n [readonly]=\"false\"\n [lineWrapping]=\"true\"\n (change)=\"record.InputDefinition = $event\">\n </mj-code-editor>\n </div>\n </div>\n <div class=\"config-section\">\n <h3><i class=\"fas fa-check-double\"></i> Expected Outcomes (JSON)</h3>\n <div class=\"config-editor-container\">\n <mj-code-editor\n [value]=\"record.ExpectedOutcomes || ''\"\n language=\"json\"\n [readonly]=\"false\"\n [lineWrapping]=\"true\"\n (change)=\"record.ExpectedOutcomes = $event\">\n </mj-code-editor>\n </div>\n </div>\n <div class=\"config-section\">\n <h3><i class=\"fas fa-cog\"></i> Configuration (JSON)</h3>\n <div class=\"config-editor-container\">\n <mj-code-editor\n [value]=\"record.Configuration || ''\"\n language=\"json\"\n [readonly]=\"false\"\n [lineWrapping]=\"true\"\n (change)=\"record.Configuration = $event\">\n </mj-code-editor>\n </div>\n </div>\n <div class=\"config-section\">\n <h3><i class=\"fas fa-tags\"></i> Tags (JSON Array)</h3>\n <div class=\"config-editor-container small\">\n <mj-code-editor\n [value]=\"record.Tags || '[]'\"\n language=\"json\"\n [readonly]=\"false\"\n [lineWrapping]=\"true\"\n (change)=\"record.Tags = $event\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n }\n\n <!-- Test 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,4,5]; 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 && testRuns.length > 0) {\n <div class=\"runs-list\">\n @for (run of testRuns; track run) {\n <div class=\"run-item\" (click)=\"openTestRun(run.ID)\">\n <div class=\"run-icon\" [style.background-color]=\"getRunStatusColor(run.Status)\">\n <i class=\"fas\"\n [class.fa-check]=\"run.Status === 'Passed'\"\n [class.fa-times]=\"run.Status === 'Failed'\"\n [class.fa-exclamation]=\"run.Status === 'Error'\"\n [class.fa-stopwatch]=\"run.Status === 'Timeout'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"></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.DurationSeconds) {\n <span><i class=\"fas fa-clock\"></i> {{ formatDuration(run.DurationSeconds) }}</span>\n }\n @if (run.CostUSD) {\n <span><i class=\"fas fa-dollar-sign\"></i> {{ formatCost(run.CostUSD) }}</span>\n }\n @if (run.TargetLogEntityID && run.TargetLogID) {\n <mj-entity-link-pill\n [entityName]=\"run.TargetLogEntity\"\n [recordId]=\"run.TargetLogID\">\n </mj-entity-link-pill>\n }\n </div>\n <!-- Evaluation indicators -->\n <div class=\"run-eval-stack\">\n <!-- Status indicator -->\n @if (evalPreferences.showExecution) {\n <span class=\"eval-pill status-pill\"\n [ngClass]=\"'status-' + run.Status.toLowerCase()\"\n [title]=\"getStatusTooltip(run.Status)\">\n <i class=\"fas\"\n [class.fa-check]=\"run.Status === 'Passed'\"\n [class.fa-times]=\"run.Status === 'Failed'\"\n [class.fa-exclamation]=\"run.Status === 'Error'\"\n [class.fa-hourglass-end]=\"run.Status === 'Timeout'\"\n [class.fa-forward]=\"run.Status === 'Skipped'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"></i>\n <span>{{ run.Status }}</span>\n </span>\n }\n <!-- Human feedback indicator -->\n @if (evalPreferences.showHuman) {\n @if (!getFeedbackForRun(run.ID)?.Rating) {\n <span class=\"eval-pill human-pill no-feedback\"\n title=\"Human Review: No rating submitted yet\">\n <i class=\"fas fa-user-slash\"></i>\n </span>\n }\n @if (getFeedbackForRun(run.ID)?.Rating; as rating) {\n <span class=\"eval-pill human-pill has-feedback\"\n [class.rating-low]=\"rating <= 4\"\n [class.rating-medium]=\"rating >= 5 && rating <= 6\"\n [class.rating-good]=\"rating >= 7 && rating <= 8\"\n [class.rating-excellent]=\"rating >= 9\"\n [title]=\"getHumanTooltip(rating, getFeedbackForRun(run.ID)?.CorrectionSummary || getFeedbackForRun(run.ID)?.Comments || null)\">\n <i class=\"fas fa-user\"></i>\n <span>{{ rating }}</span>\n </span>\n }\n }\n <!-- Auto score indicator -->\n @if (evalPreferences.showAuto) {\n @if (run.Score == null) {\n <span class=\"eval-pill auto-pill no-score\"\n title=\"Auto Score: No automated score available\">\n <i class=\"fas fa-robot\"></i>\n </span>\n }\n @if (run.Score != null) {\n <span class=\"eval-pill auto-pill has-score\"\n [class.score-low]=\"run.Score < 0.5\"\n [class.score-medium]=\"run.Score >= 0.5 && run.Score < 0.7\"\n [class.score-good]=\"run.Score >= 0.7 && run.Score < 0.85\"\n [class.score-excellent]=\"run.Score >= 0.85\"\n [title]=\"'Auto Score: ' + (run.Score * 100).toFixed(0) + '% automated evaluation'\">\n <i class=\"fas fa-robot\"></i>\n <span>{{ (run.Score * 100).toFixed(0) }}%</span>\n </span>\n }\n }\n </div>\n @if (getRunTags(run).length > 0) {\n <div class=\"run-tags\">\n @for (tag of getRunTags(run).slice(0, 3); track tag) {\n <span class=\"run-tag\">{{ tag }}</span>\n }\n @if (getRunTags(run).length > 3) {\n <span class=\"run-tag-more\">+{{ getRunTags(run).length - 3 }}</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 (testRunsLoaded && !loadingRuns && testRuns.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 Test Runs Yet</h4>\n <p>Run this test to see execution history and results here.</p>\n <button mjButton (click)=\"runTest()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Test Now\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Test Suites Tab -->\n @if (activeTab === 'suites') {\n <div class=\"suites-tab\">\n <!-- Loading State -->\n @if (loadingSuites) {\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 <!-- Suites List -->\n @if (!loadingSuites && suiteTests.length > 0) {\n <div class=\"suites-list\">\n @for (suiteTest of suiteTests; track suiteTest) {\n <div class=\"suite-item\" (click)=\"openTestSuite(suiteTest.SuiteID)\">\n <div class=\"suite-icon\">\n <i class=\"fas fa-layer-group\"></i>\n </div>\n <div class=\"suite-content\">\n <div class=\"suite-name\">{{ suiteTest.Suite }}</div>\n <div class=\"suite-meta\">\n <span><i class=\"fas fa-sort-numeric-up\"></i> Sequence: {{ suiteTest.Sequence }}</span>\n @if (suiteTest.Status) {\n <span><i class=\"fas fa-info-circle\"></i> {{ suiteTest.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 (suiteTestsLoaded && !loadingSuites && suiteTests.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-folder-open\"></i>\n </div>\n <h4>Not Part of Any Suite</h4>\n <p>This test is not included in any test suites. Add it to a suite to run it with other tests.</p>\n </div>\n }\n </div>\n }\n\n <!-- Analytics Tab -->\n @if (activeTab === 'analytics') {\n <div class=\"history-tab\">\n <!-- Loading State -->\n @if (loadingHistory) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading history...\"></mj-loading>\n </div>\n }\n <!-- History Content -->\n @if (!loadingHistory && historyLoaded) {\n <div class=\"history-content\">\n <!-- Filters -->\n <div class=\"history-filters\">\n <div class=\"time-range-filters\">\n <span class=\"filter-label\">Time Range:</span>\n <button class=\"filter-btn\"\n [class.active]=\"historyTimeRange === '7d'\"\n (click)=\"setHistoryTimeRange('7d')\">7 Days</button>\n <button class=\"filter-btn\"\n [class.active]=\"historyTimeRange === '30d'\"\n (click)=\"setHistoryTimeRange('30d')\">30 Days</button>\n <button class=\"filter-btn\"\n [class.active]=\"historyTimeRange === '90d'\"\n (click)=\"setHistoryTimeRange('90d')\">90 Days</button>\n <button class=\"filter-btn\"\n [class.active]=\"historyTimeRange === 'all'\"\n (click)=\"setHistoryTimeRange('all')\">All Time</button>\n </div>\n <div class=\"history-actions\">\n <button mjButton (click)=\"exportHistoryToCSV()\" [disabled]=\"historyData.length === 0\">\n <i class=\"fas fa-download\"></i> Export CSV\n </button>\n </div>\n </div>\n <!-- KPI Cards -->\n @if (historyData.length > 0) {\n <div class=\"history-kpi-cards\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\">\n <i class=\"fas fa-play-circle\"></i>\n </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 @if (evalPreferences.showExecution) {\n <div class=\"kpi-card\">\n <div class=\"kpi-icon pass-rate\">\n <i class=\"fas fa-percentage\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">\n {{ getOverallPassRate().toFixed(1) }}%\n <i class=\"fas trend-icon\"\n [class.fa-arrow-up]=\"getPassRateTrend() === 'up'\"\n [class.fa-arrow-down]=\"getPassRateTrend() === 'down'\"\n [class.fa-minus]=\"getPassRateTrend() === 'stable'\"\n [class.trend-up]=\"getPassRateTrend() === 'up'\"\n [class.trend-down]=\"getPassRateTrend() === 'down'\"></i>\n </div>\n <div class=\"kpi-label\">Pass Rate</div>\n </div>\n </div>\n }\n @if (evalPreferences.showAuto) {\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\">\n <i class=\"fas fa-star\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ (getOverallAvgScore() * 100).toFixed(1) }}%</div>\n <div class=\"kpi-label\">Avg Score</div>\n </div>\n </div>\n }\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\">\n <i class=\"fas fa-clock\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatDuration(getOverallAvgDuration()) }}</div>\n <div class=\"kpi-label\">Avg Duration</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\">\n <i class=\"fas fa-dollar-sign\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatCost(getOverallAvgCost()) }}</div>\n <div class=\"kpi-label\">Avg Cost</div>\n </div>\n </div>\n </div>\n }\n <!-- Daily History Table -->\n @if (historyData.length > 0) {\n <div class=\"history-section\">\n <h3><i class=\"fas fa-calendar-alt\"></i> Daily Performance</h3>\n <div class=\"history-table-container\">\n <table class=\"history-table\">\n <thead>\n <tr>\n <th>Date</th>\n <th>Runs</th>\n @if (evalPreferences.showExecution) {\n <th>Passed</th>\n }\n @if (evalPreferences.showExecution) {\n <th>Failed</th>\n }\n @if (evalPreferences.showExecution) {\n <th>Pass Rate</th>\n }\n @if (evalPreferences.showAuto) {\n <th>Avg Score</th>\n }\n <th>Avg Duration</th>\n <th>Avg Cost</th>\n </tr>\n </thead>\n <tbody>\n @for (day of historyData; track day) {\n <tr>\n <td class=\"date-cell\">{{ day.date | date:'mediumDate' }}</td>\n <td class=\"runs-cell\">{{ day.runCount }}</td>\n @if (evalPreferences.showExecution) {\n <td class=\"passed-cell\">{{ day.passCount }}</td>\n }\n @if (evalPreferences.showExecution) {\n <td class=\"failed-cell\">{{ day.failCount }}</td>\n }\n @if (evalPreferences.showExecution) {\n <td class=\"pass-rate-cell\">\n <div class=\"pass-rate-bar\">\n <div class=\"pass-rate-fill\" [style.width.%]=\"day.passRate\"></div>\n <span class=\"pass-rate-text\">{{ day.passRate.toFixed(1) }}%</span>\n </div>\n </td>\n }\n @if (evalPreferences.showAuto) {\n <td class=\"score-cell\">{{ (day.avgScore * 100).toFixed(1) }}%</td>\n }\n <td class=\"duration-cell\">{{ formatDuration(day.avgDuration) }}</td>\n <td class=\"cost-cell\">{{ formatCost(day.avgCost) }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n }\n <!-- Suite Performance -->\n @if (suitePerformance.length > 0) {\n <div class=\"history-section\">\n <h3><i class=\"fas fa-layer-group\"></i> Performance by Suite</h3>\n <div class=\"suite-performance-list\">\n @for (suite of suitePerformance; track suite) {\n <div class=\"suite-perf-card\" (click)=\"openSuiteFromHistory(suite.suiteId)\">\n <div class=\"suite-perf-header\">\n <div class=\"suite-perf-name\">{{ suite.suiteName }}</div>\n @if (suite.tags.length > 0) {\n <div class=\"suite-perf-tags\">\n @for (tag of suite.tags.slice(0, 3); track tag) {\n <span class=\"tag-mini\">{{ tag }}</span>\n }\n @if (suite.tags.length > 3) {\n <span class=\"tag-more\">+{{ suite.tags.length - 3 }}</span>\n }\n </div>\n }\n </div>\n <div class=\"suite-perf-stats\">\n <div class=\"suite-stat\">\n <span class=\"stat-value\">{{ suite.totalRuns }}</span>\n <span class=\"stat-label\">Runs</span>\n </div>\n @if (evalPreferences.showExecution) {\n <div class=\"suite-stat\">\n <span class=\"stat-value pass-rate\" [class.high]=\"suite.passRate >= 80\" [class.low]=\"suite.passRate < 50\">\n {{ suite.passRate.toFixed(1) }}%\n </span>\n <span class=\"stat-label\">Pass Rate</span>\n </div>\n }\n @if (evalPreferences.showAuto) {\n <div class=\"suite-stat\">\n <span class=\"stat-value\">{{ (suite.avgScore * 100).toFixed(1) }}%</span>\n <span class=\"stat-label\">Avg Score</span>\n </div>\n }\n <div class=\"suite-stat\">\n <span class=\"stat-value\">{{ formatDuration(suite.avgDuration) }}</span>\n <span class=\"stat-label\">Avg Duration</span>\n </div>\n <div class=\"suite-stat\">\n <span class=\"stat-value\">{{ formatCost(suite.avgCost) }}</span>\n <span class=\"stat-label\">Avg Cost</span>\n </div>\n @if (suite.lastRun) {\n <div class=\"suite-stat\">\n <span class=\"stat-value\">{{ getRelativeTime(suite.lastRun) }}</span>\n <span class=\"stat-label\">Last Run</span>\n </div>\n }\n </div>\n <i class=\"fas fa-chevron-right suite-perf-arrow\"></i>\n </div>\n }\n </div>\n </div>\n }\n <!-- Empty State -->\n @if (historyData.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 History Available</h4>\n <p>Run this test to start building history and analytics data.</p>\n <button mjButton (click)=\"runTest()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Test Now\n </button>\n </div>\n }\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 Test</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</div>\n", styles: ["/* ===========================\n Test Form - World-Class UX\n Premium Test Definition Styles\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-primary-dark: var(--mj-brand-primary-hover);\n --test-success: var(--mj-status-success);\n --test-success-light: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n --test-error: var(--mj-status-error);\n --test-error-light: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n --test-warning: var(--mj-status-warning);\n --test-warning-light: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\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-muted);\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/* 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/* Base Container */\n.test-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, 'Helvetica Neue', Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n/* ===========================\n Header Section\n =========================== */\n.test-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/* Test Icon */\n.test-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.test-icon:hover {\n transform: scale(1.05);\n}\n\n/* Test Info */\n.test-info {\n flex: 1;\n min-width: 0;\n}\n\n.test-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 line-height: 1.2;\n word-wrap: break-word;\n}\n\n.test-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n/* Status Badge */\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 letter-spacing: 0.5px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.status-badge.status-active { background: var(--mj-status-success); }\n.status-badge.status-disabled { background: var(--mj-text-secondary); }\n.status-badge.status-pending { background: var(--mj-status-warning); }\n\n.status-badge-inline {\n display: inline-flex;\n align-items: center;\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-type {\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.header-actions button {\n white-space: nowrap;\n}\n\n/* Test Description */\n.test-description {\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--test-radius-md);\n margin-bottom: 16px;\n border: 1px solid var(--test-border);\n}\n\n.test-description p {\n margin: 0;\n color: var(--test-text-secondary);\n line-height: 1.6;\n font-size: 14px;\n}\n\n/* ===========================\n Metrics Bar\n =========================== */\n.metrics-bar {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n gap: 12px;\n}\n\n.metric-card {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 14px;\n text-align: center;\n transition: var(--test-transition);\n}\n\n.metric-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.metric-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 margin-bottom: 6px;\n}\n\n.metric-value {\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n/* Progress bar in metric card */\n.metric-progress {\n margin-top: 8px;\n height: 4px;\n background: var(--test-border);\n border-radius: 2px;\n overflow: hidden;\n}\n\n.metric-progress-fill {\n height: 100%;\n background: var(--mj-status-success);\n border-radius: 2px;\n transition: width 0.5s ease-out;\n}\n\n/* ===========================\n Tabs Navigation\n =========================== */\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 -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.tabs::-webkit-scrollbar {\n display: none;\n}\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 i {\n font-size: 15px;\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 transition: var(--test-transition);\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 margin-left: 4px;\n}\n\n/* ===========================\n Tab Content Area\n =========================== */\n.tab-content {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n scroll-behavior: smooth;\n}\n\n/* ===========================\n Overview Tab\n =========================== */\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 */\n.info-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 {\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 {\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 word-wrap: break-word;\n font-weight: 500;\n}\n\n/* JSON Section */\n.json-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.json-section h3 {\n margin: 0 0 16px 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.json-section h3 i {\n color: var(--test-primary);\n}\n\n.json-tabs {\n display: flex;\n gap: 4px;\n margin-bottom: 16px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n flex-wrap: wrap;\n}\n\n.json-tab {\n flex: 1;\n min-width: 100px;\n padding: 10px 14px;\n border: none;\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n border-radius: var(--test-radius-sm);\n transition: var(--test-transition);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.json-tab:hover {\n color: var(--test-text);\n background: var(--mj-bg-overlay);\n}\n\n.json-tab.active {\n background: var(--test-surface);\n color: var(--test-primary);\n font-weight: 600;\n box-shadow: var(--test-shadow-sm);\n}\n\n.json-tab i {\n font-size: 12px;\n}\n\n.code-editor-container {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n min-height: 200px;\n max-height: 400px;\n}\n\n/* ===========================\n Configuration Tab\n =========================== */\n.config-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: fadeIn 0.3s ease-out;\n}\n\n.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.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.config-section h3 i {\n color: var(--test-primary);\n}\n\n.config-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: 20px;\n}\n\n.config-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.config-item.full-width {\n grid-column: 1 / -1;\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 background: var(--test-surface);\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) 10%, transparent);\n}\n\n.config-input::placeholder {\n color: var(--test-text-muted);\n}\n\n.config-hint {\n font-size: 11px;\n color: var(--test-text-muted);\n margin-top: 4px;\n}\n\n.config-editor-container {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n min-height: 200px;\n}\n\n.config-editor-container.small {\n min-height: 100px;\n max-height: 150px;\n}\n\n/* ===========================\n Runs Tab\n =========================== */\n.runs-tab,\n.suites-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n/* Loading States & Skeletons */\n.loading-state {\n padding: 0;\n}\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-icon {\n width: 44px;\n height: 44px;\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 flex-shrink: 0;\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/* Runs List */\n.runs-list,\n.suites-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.run-item,\n.suite-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.run-item:hover,\n.suite-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 box-shadow: var(--test-shadow-sm);\n}\n\n.run-icon,\n.suite-icon {\n width: 44px;\n height: 44px;\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.suite-icon {\n background: var(--mj-status-warning);\n}\n\n.run-content,\n.suite-content {\n flex: 1;\n min-width: 0;\n}\n\n.run-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 4px;\n}\n\n.run-id {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-status {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.suite-name {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-meta,\n.suite-meta {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: var(--test-text-secondary);\n flex-wrap: wrap;\n}\n\n.run-meta span,\n.suite-meta span {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.run-meta span i,\n.suite-meta span i {\n color: var(--test-text-muted);\n font-size: 11px;\n}\n\n.run-item > i.fa-chevron-right,\n.suite-item > i.fa-chevron-right {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.run-item:hover > i.fa-chevron-right,\n.suite-item:hover > i.fa-chevron-right {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n/* Run Evaluation Stack */\n.run-eval-stack {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n\n/* Evaluation Pills */\n.eval-pill {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n transition: var(--test-transition);\n}\n\n.eval-pill i {\n font-size: 10px;\n}\n\n/* Status pill colors */\n.eval-pill.status-pill.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.eval-pill.status-pill.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-pill.status-pill.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.eval-pill.status-pill.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.eval-pill.status-pill.status-skipped,\n.eval-pill.status-pill.status-pending {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-pill.status-pill.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/* Human feedback pills */\n.eval-pill.human-pill.no-feedback {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n padding: 4px 8px;\n}\n\n.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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 pills */\n.eval-pill.auto-pill.no-score {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n padding: 4px 8px;\n}\n\n.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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/* Run Tags */\n.run-tags {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n\n.run-tag {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.run-tag-more {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n background: var(--test-border);\n color: var(--test-text-muted);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n}\n\n/* ===========================\n Empty States\n =========================== */\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/* Legacy no-data for backwards compatibility */\n.no-data {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n color: var(--test-text-muted);\n text-align: center;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n}\n\n.no-data i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.no-data p {\n margin: 0;\n font-size: 14px;\n}\n\n/* ===========================\n Keyboard Shortcuts Popup\n =========================== */\n/* Keyboard shortcuts toggle button */\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 color: var(--test-text-secondary);\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}\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-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n font-size: 11px;\n color: var(--test-text);\n}\n\n/* ===========================\n Responsive Design - Tablet\n =========================== */\n@media (max-width: 1024px) {\n .metrics-bar {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .info-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .config-grid {\n grid-template-columns: 1fr;\n }\n\n .keyboard-shortcuts, .shortcuts-toggle {\n display: none;\n }\n}\n\n/* ===========================\n Responsive Design - Mobile\n =========================== */\n@media (max-width: 768px) {\n .test-form {\n height: auto;\n min-height: 100%;\n }\n\n .test-header {\n padding: 16px;\n }\n\n .header-content {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-left {\n width: 100%;\n }\n\n .test-icon {\n width: 48px;\n height: 48px;\n font-size: 20px;\n }\n\n .test-info h1 {\n font-size: 18px;\n }\n\n .test-meta {\n gap: 8px;\n }\n\n .status-badge {\n padding: 4px 10px;\n font-size: 11px;\n }\n\n .header-actions {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions button {\n flex: 1;\n }\n\n .metrics-bar {\n grid-template-columns: repeat(2, 1fr);\n gap: 10px;\n }\n\n .metric-card {\n padding: 12px;\n }\n\n .metric-value {\n font-size: 16px;\n }\n\n .tabs {\n padding: 0 12px;\n }\n\n .tab {\n padding: 12px 14px;\n font-size: 13px;\n gap: 6px;\n }\n\n .tab i {\n font-size: 14px;\n }\n\n .tab-shortcut {\n display: none;\n }\n\n .tab-content {\n padding: 16px;\n }\n\n .info-section,\n .json-section,\n .config-section {\n padding: 18px;\n }\n\n .info-grid {\n grid-template-columns: 1fr;\n }\n\n .json-tabs {\n flex-direction: column;\n }\n\n .json-tab {\n min-width: 0;\n justify-content: flex-start;\n }\n\n .run-item,\n .suite-item {\n padding: 14px;\n }\n\n .run-icon,\n .suite-icon {\n width: 40px;\n height: 40px;\n font-size: 16px;\n }\n\n .run-meta,\n .suite-meta {\n flex-direction: column;\n gap: 4px;\n }\n\n .empty-state {\n padding: 40px 20px;\n }\n\n .empty-icon {\n width: 64px;\n height: 64px;\n }\n\n .empty-icon i {\n font-size: 28px;\n }\n}\n\n/* ===========================\n Responsive Design - Small Mobile\n =========================== */\n@media (max-width: 480px) {\n .test-header {\n padding: 12px;\n }\n\n .header-left {\n gap: 12px;\n }\n\n .test-icon {\n width: 40px;\n height: 40px;\n font-size: 18px;\n border-radius: 8px;\n }\n\n .test-info h1 {\n font-size: 16px;\n }\n\n .metrics-bar {\n grid-template-columns: 1fr 1fr;\n }\n\n .tabs {\n padding: 0 8px;\n }\n\n .tab {\n padding: 10px 12px;\n font-size: 12px;\n }\n\n .tab-badge {\n display: none;\n }\n\n .tab-content {\n padding: 12px;\n }\n\n .run-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n }\n}\n\n/* ===========================\n Touch Device Optimizations\n =========================== */\n@media (hover: none) and (pointer: coarse) {\n .tab,\n .json-tab,\n .run-item,\n .suite-item {\n -webkit-tap-highlight-color: transparent;\n }\n\n .run-item:active,\n .suite-item:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n transform: scale(0.98);\n }\n\n .tab:active,\n .json-tab:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n }\n\n /* Larger touch targets */\n .tab {\n min-height: 48px;\n }\n\n .run-item,\n .suite-item {\n min-height: 64px;\n }\n}\n\n/* ===========================\n Reduced Motion\n =========================== */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n\n .skeleton-icon,\n .skeleton-line {\n animation: none;\n background: var(--mj-border-default);\n }\n}\n\n/* ===========================\n History Tab\n =========================== */\n.history-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n.history-content {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n/* History Filters */\n.history-filters {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n box-shadow: var(--test-shadow-sm);\n}\n\n.time-range-filters {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.filter-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text-secondary);\n margin-right: 4px;\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-light);\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 color: var(--mj-text-inverse);\n border-color: var(--test-primary);\n}\n\n.history-actions {\n display: flex;\n gap: 8px;\n}\n\n/* KPI Cards */\n.history-kpi-cards {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 16px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 18px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\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: var(--mj-brand-primary);\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 20px;\n flex-shrink: 0;\n}\n\n.kpi-icon.pass-rate {\n background: var(--mj-status-success);\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 22px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--test-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-top: 2px;\n}\n\n.trend-icon {\n font-size: 14px;\n}\n\n.trend-icon.trend-up {\n color: var(--test-success);\n}\n\n.trend-icon.trend-down {\n color: var(--test-error);\n}\n\n/* History Section */\n.history-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.history-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: 10px;\n}\n\n.history-section h3 i {\n color: var(--test-primary);\n}\n\n/* History Table */\n.history-table-container {\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.history-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 14px;\n}\n\n.history-table th,\n.history-table td {\n padding: 12px 16px;\n text-align: left;\n border-bottom: 1px solid var(--test-border);\n}\n\n.history-table th {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n background: var(--test-bg);\n}\n\n.history-table tbody tr:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 3%, transparent);\n}\n\n.date-cell {\n font-weight: 600;\n color: var(--test-text);\n}\n\n.passed-cell {\n color: var(--test-success);\n font-weight: 600;\n}\n\n.failed-cell {\n color: var(--test-error);\n font-weight: 600;\n}\n\n.pass-rate-cell {\n min-width: 120px;\n}\n\n.pass-rate-bar {\n position: relative;\n height: 24px;\n background: var(--test-bg);\n border-radius: 12px;\n overflow: hidden;\n}\n\n.pass-rate-fill {\n position: absolute;\n left: 0;\n top: 0;\n height: 100%;\n background: var(--mj-status-success);\n border-radius: 12px;\n transition: width 0.5s ease-out;\n}\n\n.pass-rate-text {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n font-size: 11px;\n font-weight: 700;\n color: var(--test-text);\n z-index: 1;\n}\n\n/* Suite Performance List */\n.suite-performance-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.suite-perf-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 18px;\n background: var(--test-bg);\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.suite-perf-card: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.suite-perf-header {\n flex: 1;\n min-width: 0;\n}\n\n.suite-perf-name {\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 6px;\n}\n\n.suite-perf-tags {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.tag-mini {\n display: inline-flex;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.tag-more {\n display: inline-flex;\n padding: 2px 8px;\n background: var(--test-border);\n color: var(--test-text-muted);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.suite-perf-stats {\n display: flex;\n gap: 24px;\n flex-wrap: wrap;\n}\n\n.suite-stat {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n}\n\n.suite-stat .stat-value {\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.suite-stat .stat-value.pass-rate.high {\n color: var(--test-success);\n}\n\n.suite-stat .stat-value.pass-rate.low {\n color: var(--test-error);\n}\n\n.suite-stat .stat-label {\n font-size: 10px;\n color: var(--test-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.suite-perf-arrow {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.suite-perf-card:hover .suite-perf-arrow {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n/* ===========================\n Print Styles\n =========================== */\n@media print {\n .test-form {\n background: var(--mj-bg-surface);\n height: auto;\n }\n\n .header-actions,\n .tabs-container,\n .keyboard-shortcuts {\n display: none !important;\n }\n\n .tab-content {\n overflow: visible;\n padding: 0;\n }\n\n .info-section,\n .json-section,\n .config-section,\n .empty-state {\n break-inside: avoid;\n box-shadow: none;\n border: 1px solid var(--mj-border-default);\n }\n}\n"] }]
|
|
2032
|
+
args: [{ standalone: false, selector: 'mj-test-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"test-form\">\n <!-- Header Section -->\n <div class=\"test-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-flask\"></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=\"test-icon\" [style.background-color]=\"getStatusColor()\">\n <i class=\"fas fa-flask\"></i>\n </div>\n <div class=\"test-info\">\n <h1>{{ record.Name }}</h1>\n <div class=\"test-meta\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass()\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon()\"></i>\n {{ record.Status }}\n </span>\n @if (record.Type) {\n <span class=\"test-type\">\n <i class=\"fas fa-tag\"></i>\n {{ record.Type }}\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)=\"runTest()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Test\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\n <!-- Test Description -->\n @if (record.Description) {\n <div class=\"test-description\">\n <p>{{ record.Description }}</p>\n </div>\n }\n\n <!-- Metrics Bar -->\n @if (testRunsLoaded && testRuns.length > 0) {\n <div class=\"metrics-bar\">\n <div class=\"metric-card\">\n <div class=\"metric-label\">Total Runs</div>\n <div class=\"metric-value\">{{ testRuns.length }}</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-label\">Pass Rate</div>\n <div class=\"metric-value\">{{ getPassRate().toFixed(1) }}%</div>\n <div class=\"metric-progress\">\n <div class=\"metric-progress-fill\" [style.width.%]=\"getPassRate()\"></div>\n </div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-label\">Avg Cost</div>\n <div class=\"metric-value\">{{ formatCost(getAverageCost()) }}</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-label\">Avg Duration</div>\n <div class=\"metric-value\">{{ formatDuration(getAverageDuration()) }}</div>\n </div>\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>\n <span>Overview</span>\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'config'\"\n (click)=\"changeTab('config')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'config'\">\n <i class=\"fas fa-sliders-h\"></i>\n <span>Configuration</span>\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>\n <span>Runs</span>\n @if (testRunsLoaded) {\n <span class=\"tab-badge\">{{ testRuns.length }}</span>\n }\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'suites'\"\n (click)=\"changeTab('suites')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'suites'\">\n <i class=\"fas fa-layer-group\"></i>\n <span>Test Suites</span>\n @if (suiteTestsLoaded) {\n <span class=\"tab-badge\">{{ suiteTests.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>\n <span>Analytics</span>\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 <!-- Basic Information -->\n <div class=\"info-section\">\n <h3><i class=\"fas fa-info-circle\"></i> Test 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\">Type</div>\n <div class=\"info-value\">{{ record.Type || 'N/A' }}</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\">Priority</div>\n <div class=\"info-value\">{{ record.Priority || 'N/A' }}</div>\n </div>\n <div class=\"info-item\">\n <div class=\"info-label\">Estimated Duration</div>\n <div class=\"info-value\">{{ record.EstimatedDurationSeconds ? formatDuration(record.EstimatedDurationSeconds) : 'N/A' }}</div>\n </div>\n <div class=\"info-item\">\n <div class=\"info-label\">Estimated Cost</div>\n <div class=\"info-value\">{{ record.EstimatedCostUSD ? formatCost(record.EstimatedCostUSD) : 'N/A' }}</div>\n </div>\n <div class=\"info-item\">\n <div class=\"info-label\">Repeat Count</div>\n <div class=\"info-value\">{{ record.RepeatCount || 1 }}</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 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>\n </div>\n <!-- JSON Data Views -->\n <div class=\"json-section\">\n <h3><i class=\"fas fa-code\"></i> Test Definition</h3>\n <div class=\"json-tabs\">\n <button class=\"json-tab\"\n [class.active]=\"activeJsonView === 'input'\"\n (click)=\"setJsonView('input')\">\n <i class=\"fas fa-sign-in-alt\"></i>\n Input Definition\n </button>\n <button class=\"json-tab\"\n [class.active]=\"activeJsonView === 'expected'\"\n (click)=\"setJsonView('expected')\">\n <i class=\"fas fa-check-double\"></i>\n Expected Outcomes\n </button>\n <button class=\"json-tab\"\n [class.active]=\"activeJsonView === 'config'\"\n (click)=\"setJsonView('config')\">\n <i class=\"fas fa-cog\"></i>\n Configuration\n </button>\n <button class=\"json-tab\"\n [class.active]=\"activeJsonView === 'tags'\"\n (click)=\"setJsonView('tags')\">\n <i class=\"fas fa-tags\"></i>\n Tags\n </button>\n </div>\n <div class=\"code-editor-container\">\n <mj-code-editor\n [value]=\"getJsonData()\"\n language=\"json\"\n [readonly]=\"true\"\n [toolbar]=\"jsonToolbar\"\n [lineWrapping]=\"true\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n }\n\n <!-- Configuration Tab -->\n @if (activeTab === 'config') {\n <div class=\"config-tab\">\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>Priority</label>\n <input type=\"number\" [(ngModel)]=\"record.Priority\" class=\"config-input\" placeholder=\"Lower = Higher Priority\" />\n </div>\n <div class=\"config-item\">\n <label>Repeat Count</label>\n <input type=\"number\" [(ngModel)]=\"record.RepeatCount\" class=\"config-input\" min=\"1\" />\n </div>\n <div class=\"config-item\">\n <label>Estimated Duration (seconds)</label>\n <input type=\"number\" [(ngModel)]=\"record.EstimatedDurationSeconds\" class=\"config-input\" />\n </div>\n <div class=\"config-item\">\n <label>Estimated Cost (USD)</label>\n <input type=\"number\" step=\"0.000001\" [(ngModel)]=\"record.EstimatedCostUSD\" class=\"config-input\" />\n </div>\n <div class=\"config-item full-width\">\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\">Leave empty for default 5 minute timeout</span>\n </div>\n </div>\n </div>\n <div class=\"config-section\">\n <h3><i class=\"fas fa-sign-in-alt\"></i> Input Definition (JSON)</h3>\n <div class=\"config-editor-container\">\n <mj-code-editor\n [value]=\"record.InputDefinition || ''\"\n language=\"json\"\n [readonly]=\"false\"\n [lineWrapping]=\"true\"\n (change)=\"record.InputDefinition = $event\">\n </mj-code-editor>\n </div>\n </div>\n <div class=\"config-section\">\n <h3><i class=\"fas fa-check-double\"></i> Expected Outcomes (JSON)</h3>\n <div class=\"config-editor-container\">\n <mj-code-editor\n [value]=\"record.ExpectedOutcomes || ''\"\n language=\"json\"\n [readonly]=\"false\"\n [lineWrapping]=\"true\"\n (change)=\"record.ExpectedOutcomes = $event\">\n </mj-code-editor>\n </div>\n </div>\n <div class=\"config-section\">\n <h3><i class=\"fas fa-cog\"></i> Configuration (JSON)</h3>\n <div class=\"config-editor-container\">\n <mj-code-editor\n [value]=\"record.Configuration || ''\"\n language=\"json\"\n [readonly]=\"false\"\n [lineWrapping]=\"true\"\n (change)=\"record.Configuration = $event\">\n </mj-code-editor>\n </div>\n </div>\n <div class=\"config-section\">\n <h3><i class=\"fas fa-tags\"></i> Tags (JSON Array)</h3>\n <div class=\"config-editor-container small\">\n <mj-code-editor\n [value]=\"record.Tags || '[]'\"\n language=\"json\"\n [readonly]=\"false\"\n [lineWrapping]=\"true\"\n (change)=\"record.Tags = $event\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n }\n\n <!-- Test 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,4,5]; 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 && testRuns.length > 0) {\n <div class=\"runs-list\">\n @for (run of testRuns; track run) {\n <div class=\"run-item\" (click)=\"openTestRun(run.ID)\">\n <div class=\"run-icon\" [style.background-color]=\"getRunStatusColor(run.Status)\">\n <i class=\"fas\"\n [class.fa-check]=\"run.Status === 'Passed'\"\n [class.fa-times]=\"run.Status === 'Failed'\"\n [class.fa-exclamation]=\"run.Status === 'Error'\"\n [class.fa-stopwatch]=\"run.Status === 'Timeout'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"></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.DurationSeconds) {\n <span><i class=\"fas fa-clock\"></i> {{ formatDuration(run.DurationSeconds) }}</span>\n }\n @if (run.CostUSD) {\n <span><i class=\"fas fa-dollar-sign\"></i> {{ formatCost(run.CostUSD) }}</span>\n }\n @if (run.TargetLogEntityID && run.TargetLogID) {\n <mj-entity-link-pill\n [entityName]=\"run.TargetLogEntity\"\n [recordId]=\"run.TargetLogID\">\n </mj-entity-link-pill>\n }\n </div>\n <!-- Evaluation indicators -->\n <div class=\"run-eval-stack\">\n <!-- Status indicator -->\n @if (evalPreferences.showExecution) {\n <span class=\"eval-pill status-pill\"\n [ngClass]=\"'status-' + run.Status.toLowerCase()\"\n [title]=\"getStatusTooltip(run.Status)\">\n <i class=\"fas\"\n [class.fa-check]=\"run.Status === 'Passed'\"\n [class.fa-times]=\"run.Status === 'Failed'\"\n [class.fa-exclamation]=\"run.Status === 'Error'\"\n [class.fa-hourglass-end]=\"run.Status === 'Timeout'\"\n [class.fa-forward]=\"run.Status === 'Skipped'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"></i>\n <span>{{ run.Status }}</span>\n </span>\n }\n <!-- Human feedback indicator -->\n @if (evalPreferences.showHuman) {\n @if (!getFeedbackForRun(run.ID)?.Rating) {\n <span class=\"eval-pill human-pill no-feedback\"\n title=\"Human Review: No rating submitted yet\">\n <i class=\"fas fa-user-slash\"></i>\n </span>\n }\n @if (getFeedbackForRun(run.ID)?.Rating; as rating) {\n <span class=\"eval-pill human-pill has-feedback\"\n [class.rating-low]=\"rating <= 4\"\n [class.rating-medium]=\"rating >= 5 && rating <= 6\"\n [class.rating-good]=\"rating >= 7 && rating <= 8\"\n [class.rating-excellent]=\"rating >= 9\"\n [title]=\"getHumanTooltip(rating, getFeedbackForRun(run.ID)?.CorrectionSummary || getFeedbackForRun(run.ID)?.Comments || null)\">\n <i class=\"fas fa-user\"></i>\n <span>{{ rating }}</span>\n </span>\n }\n }\n <!-- Auto score indicator -->\n @if (evalPreferences.showAuto) {\n @if (run.Score == null) {\n <span class=\"eval-pill auto-pill no-score\"\n title=\"Auto Score: No automated score available\">\n <i class=\"fas fa-robot\"></i>\n </span>\n }\n @if (run.Score != null) {\n <span class=\"eval-pill auto-pill has-score\"\n [class.score-low]=\"run.Score < 0.5\"\n [class.score-medium]=\"run.Score >= 0.5 && run.Score < 0.7\"\n [class.score-good]=\"run.Score >= 0.7 && run.Score < 0.85\"\n [class.score-excellent]=\"run.Score >= 0.85\"\n [title]=\"'Auto Score: ' + (run.Score * 100).toFixed(0) + '% automated evaluation'\">\n <i class=\"fas fa-robot\"></i>\n <span>{{ (run.Score * 100).toFixed(0) }}%</span>\n </span>\n }\n }\n </div>\n @if (getRunTags(run).length > 0) {\n <div class=\"run-tags\">\n @for (tag of getRunTags(run).slice(0, 3); track tag) {\n <span class=\"run-tag\">{{ tag }}</span>\n }\n @if (getRunTags(run).length > 3) {\n <span class=\"run-tag-more\">+{{ getRunTags(run).length - 3 }}</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 (testRunsLoaded && !loadingRuns && testRuns.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 Test Runs Yet</h4>\n <p>Run this test to see execution history and results here.</p>\n <button mjButton (click)=\"runTest()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Test Now\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Test Suites Tab -->\n @if (activeTab === 'suites') {\n <div class=\"suites-tab\">\n <!-- Loading State -->\n @if (loadingSuites) {\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 <!-- Suites List -->\n @if (!loadingSuites && suiteTests.length > 0) {\n <div class=\"suites-list\">\n @for (suiteTest of suiteTests; track suiteTest) {\n <div class=\"suite-item\" (click)=\"openTestSuite(suiteTest.SuiteID)\">\n <div class=\"suite-icon\">\n <i class=\"fas fa-layer-group\"></i>\n </div>\n <div class=\"suite-content\">\n <div class=\"suite-name\">{{ suiteTest.Suite }}</div>\n <div class=\"suite-meta\">\n <span><i class=\"fas fa-sort-numeric-up\"></i> Sequence: {{ suiteTest.Sequence }}</span>\n @if (suiteTest.Status) {\n <span><i class=\"fas fa-info-circle\"></i> {{ suiteTest.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 (suiteTestsLoaded && !loadingSuites && suiteTests.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-folder-open\"></i>\n </div>\n <h4>Not Part of Any Suite</h4>\n <p>This test is not included in any test suites. Add it to a suite to run it with other tests.</p>\n </div>\n }\n </div>\n }\n\n <!-- Analytics Tab -->\n @if (activeTab === 'analytics') {\n <div class=\"history-tab\">\n <!-- Loading State -->\n @if (loadingHistory) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading history...\"></mj-loading>\n </div>\n }\n <!-- History Content -->\n @if (!loadingHistory && historyLoaded) {\n <div class=\"history-content\">\n <!-- Filters -->\n <div class=\"history-filters\">\n <div class=\"time-range-filters\">\n <span class=\"filter-label\">Time Range:</span>\n <button class=\"filter-btn\"\n [class.active]=\"historyTimeRange === '7d'\"\n (click)=\"setHistoryTimeRange('7d')\">7 Days</button>\n <button class=\"filter-btn\"\n [class.active]=\"historyTimeRange === '30d'\"\n (click)=\"setHistoryTimeRange('30d')\">30 Days</button>\n <button class=\"filter-btn\"\n [class.active]=\"historyTimeRange === '90d'\"\n (click)=\"setHistoryTimeRange('90d')\">90 Days</button>\n <button class=\"filter-btn\"\n [class.active]=\"historyTimeRange === 'all'\"\n (click)=\"setHistoryTimeRange('all')\">All Time</button>\n </div>\n <div class=\"history-actions\">\n <button mjButton (click)=\"exportHistoryToCSV()\" [disabled]=\"historyData.length === 0\">\n <i class=\"fas fa-download\"></i> Export CSV\n </button>\n </div>\n </div>\n <!-- KPI Cards -->\n @if (historyData.length > 0) {\n <div class=\"history-kpi-cards\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\">\n <i class=\"fas fa-play-circle\"></i>\n </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 @if (evalPreferences.showExecution) {\n <div class=\"kpi-card\">\n <div class=\"kpi-icon pass-rate\">\n <i class=\"fas fa-percentage\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">\n {{ getOverallPassRate().toFixed(1) }}%\n <i class=\"fas trend-icon\"\n [class.fa-arrow-up]=\"getPassRateTrend() === 'up'\"\n [class.fa-arrow-down]=\"getPassRateTrend() === 'down'\"\n [class.fa-minus]=\"getPassRateTrend() === 'stable'\"\n [class.trend-up]=\"getPassRateTrend() === 'up'\"\n [class.trend-down]=\"getPassRateTrend() === 'down'\"></i>\n </div>\n <div class=\"kpi-label\">Pass Rate</div>\n </div>\n </div>\n }\n @if (evalPreferences.showAuto) {\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\">\n <i class=\"fas fa-star\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ (getOverallAvgScore() * 100).toFixed(1) }}%</div>\n <div class=\"kpi-label\">Avg Score</div>\n </div>\n </div>\n }\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\">\n <i class=\"fas fa-clock\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatDuration(getOverallAvgDuration()) }}</div>\n <div class=\"kpi-label\">Avg Duration</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\">\n <i class=\"fas fa-dollar-sign\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatCost(getOverallAvgCost()) }}</div>\n <div class=\"kpi-label\">Avg Cost</div>\n </div>\n </div>\n </div>\n }\n <!-- Daily History Table -->\n @if (historyData.length > 0) {\n <div class=\"history-section\">\n <h3><i class=\"fas fa-calendar-alt\"></i> Daily Performance</h3>\n <div class=\"history-table-container\">\n <table class=\"history-table\">\n <thead>\n <tr>\n <th>Date</th>\n <th>Runs</th>\n @if (evalPreferences.showExecution) {\n <th>Passed</th>\n }\n @if (evalPreferences.showExecution) {\n <th>Failed</th>\n }\n @if (evalPreferences.showExecution) {\n <th>Pass Rate</th>\n }\n @if (evalPreferences.showAuto) {\n <th>Avg Score</th>\n }\n <th>Avg Duration</th>\n <th>Avg Cost</th>\n </tr>\n </thead>\n <tbody>\n @for (day of historyData; track day) {\n <tr>\n <td class=\"date-cell\">{{ day.date | date:'mediumDate' }}</td>\n <td class=\"runs-cell\">{{ day.runCount }}</td>\n @if (evalPreferences.showExecution) {\n <td class=\"passed-cell\">{{ day.passCount }}</td>\n }\n @if (evalPreferences.showExecution) {\n <td class=\"failed-cell\">{{ day.failCount }}</td>\n }\n @if (evalPreferences.showExecution) {\n <td class=\"pass-rate-cell\">\n <div class=\"pass-rate-bar\">\n <div class=\"pass-rate-fill\" [style.width.%]=\"day.passRate\"></div>\n <span class=\"pass-rate-text\">{{ day.passRate.toFixed(1) }}%</span>\n </div>\n </td>\n }\n @if (evalPreferences.showAuto) {\n <td class=\"score-cell\">{{ (day.avgScore * 100).toFixed(1) }}%</td>\n }\n <td class=\"duration-cell\">{{ formatDuration(day.avgDuration) }}</td>\n <td class=\"cost-cell\">{{ formatCost(day.avgCost) }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n }\n <!-- Suite Performance -->\n @if (suitePerformance.length > 0) {\n <div class=\"history-section\">\n <h3><i class=\"fas fa-layer-group\"></i> Performance by Suite</h3>\n <div class=\"suite-performance-list\">\n @for (suite of suitePerformance; track suite) {\n <div class=\"suite-perf-card\" (click)=\"openSuiteFromHistory(suite.suiteId)\">\n <div class=\"suite-perf-header\">\n <div class=\"suite-perf-name\">{{ suite.suiteName }}</div>\n @if (suite.tags.length > 0) {\n <div class=\"suite-perf-tags\">\n @for (tag of suite.tags.slice(0, 3); track tag) {\n <span class=\"tag-mini\">{{ tag }}</span>\n }\n @if (suite.tags.length > 3) {\n <span class=\"tag-more\">+{{ suite.tags.length - 3 }}</span>\n }\n </div>\n }\n </div>\n <div class=\"suite-perf-stats\">\n <div class=\"suite-stat\">\n <span class=\"stat-value\">{{ suite.totalRuns }}</span>\n <span class=\"stat-label\">Runs</span>\n </div>\n @if (evalPreferences.showExecution) {\n <div class=\"suite-stat\">\n <span class=\"stat-value pass-rate\" [class.high]=\"suite.passRate >= 80\" [class.low]=\"suite.passRate < 50\">\n {{ suite.passRate.toFixed(1) }}%\n </span>\n <span class=\"stat-label\">Pass Rate</span>\n </div>\n }\n @if (evalPreferences.showAuto) {\n <div class=\"suite-stat\">\n <span class=\"stat-value\">{{ (suite.avgScore * 100).toFixed(1) }}%</span>\n <span class=\"stat-label\">Avg Score</span>\n </div>\n }\n <div class=\"suite-stat\">\n <span class=\"stat-value\">{{ formatDuration(suite.avgDuration) }}</span>\n <span class=\"stat-label\">Avg Duration</span>\n </div>\n <div class=\"suite-stat\">\n <span class=\"stat-value\">{{ formatCost(suite.avgCost) }}</span>\n <span class=\"stat-label\">Avg Cost</span>\n </div>\n @if (suite.lastRun) {\n <div class=\"suite-stat\">\n <span class=\"stat-value\">{{ getRelativeTime(suite.lastRun) }}</span>\n <span class=\"stat-label\">Last Run</span>\n </div>\n }\n </div>\n <i class=\"fas fa-chevron-right suite-perf-arrow\"></i>\n </div>\n }\n </div>\n </div>\n }\n <!-- Empty State -->\n @if (historyData.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 History Available</h4>\n <p>Run this test to start building history and analytics data.</p>\n <button mjButton (click)=\"runTest()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Test Now\n </button>\n </div>\n }\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 Test</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 Test Execution -->\n @if (testingDialogService.IsPanelOpen) {\n <mj-slide-panel\n Mode=\"slide\"\n [Title]=\"testingDialogService.PanelOptions?.testId ? 'Test Execution' : 'Run Test'\"\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 ?? 'test'\"\n (PanelClose)=\"OnPanelClosed()\">\n </app-test-run-dialog>\n </mj-slide-panel>\n }\n</div>\n", styles: ["/* ===========================\n Test Form - World-Class UX\n Premium Test Definition Styles\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-primary-dark: var(--mj-brand-primary-hover);\n --test-success: var(--mj-status-success);\n --test-success-light: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n --test-error: var(--mj-status-error);\n --test-error-light: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n --test-warning: var(--mj-status-warning);\n --test-warning-light: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\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-muted);\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/* 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/* Base Container */\n.test-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, 'Helvetica Neue', Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n/* ===========================\n Header Section\n =========================== */\n.test-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/* Test Icon */\n.test-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.test-icon:hover {\n transform: scale(1.05);\n}\n\n/* Test Info */\n.test-info {\n flex: 1;\n min-width: 0;\n}\n\n.test-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 line-height: 1.2;\n word-wrap: break-word;\n}\n\n.test-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n/* Status Badge */\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 letter-spacing: 0.5px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.status-badge.status-active { background: var(--mj-status-success); }\n.status-badge.status-disabled { background: var(--mj-text-secondary); }\n.status-badge.status-pending { background: var(--mj-status-warning); }\n\n.status-badge-inline {\n display: inline-flex;\n align-items: center;\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-type {\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.header-actions button {\n white-space: nowrap;\n}\n\n/* Test Description */\n.test-description {\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--test-radius-md);\n margin-bottom: 16px;\n border: 1px solid var(--test-border);\n}\n\n.test-description p {\n margin: 0;\n color: var(--test-text-secondary);\n line-height: 1.6;\n font-size: 14px;\n}\n\n/* ===========================\n Metrics Bar\n =========================== */\n.metrics-bar {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n gap: 12px;\n}\n\n.metric-card {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 14px;\n text-align: center;\n transition: var(--test-transition);\n}\n\n.metric-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.metric-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 margin-bottom: 6px;\n}\n\n.metric-value {\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n/* Progress bar in metric card */\n.metric-progress {\n margin-top: 8px;\n height: 4px;\n background: var(--test-border);\n border-radius: 2px;\n overflow: hidden;\n}\n\n.metric-progress-fill {\n height: 100%;\n background: var(--mj-status-success);\n border-radius: 2px;\n transition: width 0.5s ease-out;\n}\n\n/* ===========================\n Tabs Navigation\n =========================== */\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 -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.tabs::-webkit-scrollbar {\n display: none;\n}\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 i {\n font-size: 15px;\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 transition: var(--test-transition);\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 margin-left: 4px;\n}\n\n/* ===========================\n Tab Content Area\n =========================== */\n.tab-content {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n scroll-behavior: smooth;\n}\n\n/* ===========================\n Overview Tab\n =========================== */\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 */\n.info-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 {\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 {\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 word-wrap: break-word;\n font-weight: 500;\n}\n\n/* JSON Section */\n.json-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.json-section h3 {\n margin: 0 0 16px 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.json-section h3 i {\n color: var(--test-primary);\n}\n\n.json-tabs {\n display: flex;\n gap: 4px;\n margin-bottom: 16px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n flex-wrap: wrap;\n}\n\n.json-tab {\n flex: 1;\n min-width: 100px;\n padding: 10px 14px;\n border: none;\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n border-radius: var(--test-radius-sm);\n transition: var(--test-transition);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.json-tab:hover {\n color: var(--test-text);\n background: var(--mj-bg-overlay);\n}\n\n.json-tab.active {\n background: var(--test-surface);\n color: var(--test-primary);\n font-weight: 600;\n box-shadow: var(--test-shadow-sm);\n}\n\n.json-tab i {\n font-size: 12px;\n}\n\n.code-editor-container {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n min-height: 200px;\n max-height: 400px;\n}\n\n/* ===========================\n Configuration Tab\n =========================== */\n.config-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: fadeIn 0.3s ease-out;\n}\n\n.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.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.config-section h3 i {\n color: var(--test-primary);\n}\n\n.config-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: 20px;\n}\n\n.config-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.config-item.full-width {\n grid-column: 1 / -1;\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 background: var(--test-surface);\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) 10%, transparent);\n}\n\n.config-input::placeholder {\n color: var(--test-text-muted);\n}\n\n.config-hint {\n font-size: 11px;\n color: var(--test-text-muted);\n margin-top: 4px;\n}\n\n.config-editor-container {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n min-height: 200px;\n}\n\n.config-editor-container.small {\n min-height: 100px;\n max-height: 150px;\n}\n\n/* ===========================\n Runs Tab\n =========================== */\n.runs-tab,\n.suites-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n/* Loading States & Skeletons */\n.loading-state {\n padding: 0;\n}\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-icon {\n width: 44px;\n height: 44px;\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 flex-shrink: 0;\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/* Runs List */\n.runs-list,\n.suites-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.run-item,\n.suite-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.run-item:hover,\n.suite-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 box-shadow: var(--test-shadow-sm);\n}\n\n.run-icon,\n.suite-icon {\n width: 44px;\n height: 44px;\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.suite-icon {\n background: var(--mj-status-warning);\n}\n\n.run-content,\n.suite-content {\n flex: 1;\n min-width: 0;\n}\n\n.run-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 4px;\n}\n\n.run-id {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-status {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.suite-name {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-meta,\n.suite-meta {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: var(--test-text-secondary);\n flex-wrap: wrap;\n}\n\n.run-meta span,\n.suite-meta span {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.run-meta span i,\n.suite-meta span i {\n color: var(--test-text-muted);\n font-size: 11px;\n}\n\n.run-item > i.fa-chevron-right,\n.suite-item > i.fa-chevron-right {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.run-item:hover > i.fa-chevron-right,\n.suite-item:hover > i.fa-chevron-right {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n/* Run Evaluation Stack */\n.run-eval-stack {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n\n/* Evaluation Pills */\n.eval-pill {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border-radius: 16px;\n font-size: 11px;\n font-weight: 600;\n transition: var(--test-transition);\n}\n\n.eval-pill i {\n font-size: 10px;\n}\n\n/* Status pill colors */\n.eval-pill.status-pill.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.eval-pill.status-pill.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-pill.status-pill.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.eval-pill.status-pill.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.eval-pill.status-pill.status-skipped,\n.eval-pill.status-pill.status-pending {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-pill.status-pill.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/* Human feedback pills */\n.eval-pill.human-pill.no-feedback {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n padding: 4px 8px;\n}\n\n.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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.eval-pill.human-pill.has-feedback.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 pills */\n.eval-pill.auto-pill.no-score {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n padding: 4px 8px;\n}\n\n.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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.eval-pill.auto-pill.has-score.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/* Run Tags */\n.run-tags {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 8px;\n flex-wrap: wrap;\n}\n\n.run-tag {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.run-tag-more {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n background: var(--test-border);\n color: var(--test-text-muted);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n}\n\n/* ===========================\n Empty States\n =========================== */\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/* Legacy no-data for backwards compatibility */\n.no-data {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n color: var(--test-text-muted);\n text-align: center;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n}\n\n.no-data i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.no-data p {\n margin: 0;\n font-size: 14px;\n}\n\n/* ===========================\n Keyboard Shortcuts Popup\n =========================== */\n/* Keyboard shortcuts toggle button */\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 color: var(--test-text-secondary);\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}\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-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n font-size: 11px;\n color: var(--test-text);\n}\n\n/* ===========================\n Responsive Design - Tablet\n =========================== */\n@media (max-width: 1024px) {\n .metrics-bar {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .info-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .config-grid {\n grid-template-columns: 1fr;\n }\n\n .keyboard-shortcuts, .shortcuts-toggle {\n display: none;\n }\n}\n\n/* ===========================\n Responsive Design - Mobile\n =========================== */\n@media (max-width: 768px) {\n .test-form {\n height: auto;\n min-height: 100%;\n }\n\n .test-header {\n padding: 16px;\n }\n\n .header-content {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-left {\n width: 100%;\n }\n\n .test-icon {\n width: 48px;\n height: 48px;\n font-size: 20px;\n }\n\n .test-info h1 {\n font-size: 18px;\n }\n\n .test-meta {\n gap: 8px;\n }\n\n .status-badge {\n padding: 4px 10px;\n font-size: 11px;\n }\n\n .header-actions {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions button {\n flex: 1;\n }\n\n .metrics-bar {\n grid-template-columns: repeat(2, 1fr);\n gap: 10px;\n }\n\n .metric-card {\n padding: 12px;\n }\n\n .metric-value {\n font-size: 16px;\n }\n\n .tabs {\n padding: 0 12px;\n }\n\n .tab {\n padding: 12px 14px;\n font-size: 13px;\n gap: 6px;\n }\n\n .tab i {\n font-size: 14px;\n }\n\n .tab-shortcut {\n display: none;\n }\n\n .tab-content {\n padding: 16px;\n }\n\n .info-section,\n .json-section,\n .config-section {\n padding: 18px;\n }\n\n .info-grid {\n grid-template-columns: 1fr;\n }\n\n .json-tabs {\n flex-direction: column;\n }\n\n .json-tab {\n min-width: 0;\n justify-content: flex-start;\n }\n\n .run-item,\n .suite-item {\n padding: 14px;\n }\n\n .run-icon,\n .suite-icon {\n width: 40px;\n height: 40px;\n font-size: 16px;\n }\n\n .run-meta,\n .suite-meta {\n flex-direction: column;\n gap: 4px;\n }\n\n .empty-state {\n padding: 40px 20px;\n }\n\n .empty-icon {\n width: 64px;\n height: 64px;\n }\n\n .empty-icon i {\n font-size: 28px;\n }\n}\n\n/* ===========================\n Responsive Design - Small Mobile\n =========================== */\n@media (max-width: 480px) {\n .test-header {\n padding: 12px;\n }\n\n .header-left {\n gap: 12px;\n }\n\n .test-icon {\n width: 40px;\n height: 40px;\n font-size: 18px;\n border-radius: 8px;\n }\n\n .test-info h1 {\n font-size: 16px;\n }\n\n .metrics-bar {\n grid-template-columns: 1fr 1fr;\n }\n\n .tabs {\n padding: 0 8px;\n }\n\n .tab {\n padding: 10px 12px;\n font-size: 12px;\n }\n\n .tab-badge {\n display: none;\n }\n\n .tab-content {\n padding: 12px;\n }\n\n .run-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n }\n}\n\n/* ===========================\n Touch Device Optimizations\n =========================== */\n@media (hover: none) and (pointer: coarse) {\n .tab,\n .json-tab,\n .run-item,\n .suite-item {\n -webkit-tap-highlight-color: transparent;\n }\n\n .run-item:active,\n .suite-item:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n transform: scale(0.98);\n }\n\n .tab:active,\n .json-tab:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n }\n\n /* Larger touch targets */\n .tab {\n min-height: 48px;\n }\n\n .run-item,\n .suite-item {\n min-height: 64px;\n }\n}\n\n/* ===========================\n Reduced Motion\n =========================== */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n\n .skeleton-icon,\n .skeleton-line {\n animation: none;\n background: var(--mj-border-default);\n }\n}\n\n/* ===========================\n History Tab\n =========================== */\n.history-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n.history-content {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n/* History Filters */\n.history-filters {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n box-shadow: var(--test-shadow-sm);\n}\n\n.time-range-filters {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.filter-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text-secondary);\n margin-right: 4px;\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-light);\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 color: var(--mj-text-inverse);\n border-color: var(--test-primary);\n}\n\n.history-actions {\n display: flex;\n gap: 8px;\n}\n\n/* KPI Cards */\n.history-kpi-cards {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 16px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 18px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\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: var(--mj-brand-primary);\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 20px;\n flex-shrink: 0;\n}\n\n.kpi-icon.pass-rate {\n background: var(--mj-status-success);\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 22px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--test-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-top: 2px;\n}\n\n.trend-icon {\n font-size: 14px;\n}\n\n.trend-icon.trend-up {\n color: var(--test-success);\n}\n\n.trend-icon.trend-down {\n color: var(--test-error);\n}\n\n/* History Section */\n.history-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.history-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: 10px;\n}\n\n.history-section h3 i {\n color: var(--test-primary);\n}\n\n/* History Table */\n.history-table-container {\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.history-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 14px;\n}\n\n.history-table th,\n.history-table td {\n padding: 12px 16px;\n text-align: left;\n border-bottom: 1px solid var(--test-border);\n}\n\n.history-table th {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n background: var(--test-bg);\n}\n\n.history-table tbody tr:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 3%, transparent);\n}\n\n.date-cell {\n font-weight: 600;\n color: var(--test-text);\n}\n\n.passed-cell {\n color: var(--test-success);\n font-weight: 600;\n}\n\n.failed-cell {\n color: var(--test-error);\n font-weight: 600;\n}\n\n.pass-rate-cell {\n min-width: 120px;\n}\n\n.pass-rate-bar {\n position: relative;\n height: 24px;\n background: var(--test-bg);\n border-radius: 12px;\n overflow: hidden;\n}\n\n.pass-rate-fill {\n position: absolute;\n left: 0;\n top: 0;\n height: 100%;\n background: var(--mj-status-success);\n border-radius: 12px;\n transition: width 0.5s ease-out;\n}\n\n.pass-rate-text {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n font-size: 11px;\n font-weight: 700;\n color: var(--test-text);\n z-index: 1;\n}\n\n/* Suite Performance List */\n.suite-performance-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.suite-perf-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 18px;\n background: var(--test-bg);\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.suite-perf-card: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.suite-perf-header {\n flex: 1;\n min-width: 0;\n}\n\n.suite-perf-name {\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 6px;\n}\n\n.suite-perf-tags {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.tag-mini {\n display: inline-flex;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.tag-more {\n display: inline-flex;\n padding: 2px 8px;\n background: var(--test-border);\n color: var(--test-text-muted);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.suite-perf-stats {\n display: flex;\n gap: 24px;\n flex-wrap: wrap;\n}\n\n.suite-stat {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n}\n\n.suite-stat .stat-value {\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.suite-stat .stat-value.pass-rate.high {\n color: var(--test-success);\n}\n\n.suite-stat .stat-value.pass-rate.low {\n color: var(--test-error);\n}\n\n.suite-stat .stat-label {\n font-size: 10px;\n color: var(--test-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.suite-perf-arrow {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.suite-perf-card:hover .suite-perf-arrow {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n/* ===========================\n Print Styles\n =========================== */\n@media print {\n .test-form {\n background: var(--mj-bg-surface);\n height: auto;\n }\n\n .header-actions,\n .tabs-container,\n .keyboard-shortcuts {\n display: none !important;\n }\n\n .tab-content {\n overflow: visible;\n padding: 0;\n }\n\n .info-section,\n .json-section,\n .config-section,\n .empty-state {\n break-inside: avoid;\n box-shadow: none;\n border: 1px solid var(--mj-border-default);\n }\n}\n"] }]
|
|
2006
2033
|
}], null, { handleKeyboardShortcut: [{
|
|
2007
2034
|
type: HostListener,
|
|
2008
2035
|
args: ['document:keydown', ['$event']]
|