@memberjunction/ng-core-entity-forms 2.129.0 → 2.130.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/custom/Tests/entity-link-pill.component.d.ts +44 -0
- package/dist/lib/custom/Tests/entity-link-pill.component.d.ts.map +1 -0
- package/dist/lib/custom/Tests/entity-link-pill.component.js +124 -0
- package/dist/lib/custom/Tests/entity-link-pill.component.js.map +1 -0
- package/dist/lib/custom/Tests/test-form.component.d.ts +96 -9
- package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.js +1529 -277
- package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.d.ts +50 -9
- package/dist/lib/custom/Tests/test-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.js +1079 -426
- package/dist/lib/custom/Tests/test-run-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts +228 -5
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.js +3309 -201
- package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts +88 -3
- package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-suite-run-form.component.js +1976 -262
- package/dist/lib/custom/Tests/test-suite-run-form.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts +9 -2
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +275 -244
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
- package/dist/lib/custom/custom-forms.module.d.ts +27 -26
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +9 -3
- package/dist/lib/custom/custom-forms.module.js.map +1 -1
- package/dist/lib/generated/Entities/AIAgent/aiagent.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/AIAgent/aiagent.form.component.js +154 -122
- package/dist/lib/generated/Entities/AIAgent/aiagent.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/AIAgentModality/aiagentmodality.form.component.d.ts +11 -0
- package/dist/lib/generated/Entities/AIAgentModality/aiagentmodality.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/AIAgentModality/aiagentmodality.form.component.js +75 -0
- package/dist/lib/generated/Entities/AIAgentModality/aiagentmodality.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/AIArchitecture/aiarchitecture.form.component.d.ts +11 -0
- package/dist/lib/generated/Entities/AIArchitecture/aiarchitecture.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/AIArchitecture/aiarchitecture.form.component.js +121 -0
- package/dist/lib/generated/Entities/AIArchitecture/aiarchitecture.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/AIConfiguration/aiconfiguration.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/AIConfiguration/aiconfiguration.form.component.js +77 -41
- package/dist/lib/generated/Entities/AIConfiguration/aiconfiguration.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/AIModality/aimodality.form.component.d.ts +11 -0
- package/dist/lib/generated/Entities/AIModality/aimodality.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/AIModality/aimodality.form.component.js +167 -0
- package/dist/lib/generated/Entities/AIModality/aimodality.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/AIModel/aimodel.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/AIModel/aimodel.form.component.js +160 -102
- package/dist/lib/generated/Entities/AIModel/aimodel.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/AIModelArchitecture/aimodelarchitecture.form.component.d.ts +11 -0
- package/dist/lib/generated/Entities/AIModelArchitecture/aimodelarchitecture.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/AIModelArchitecture/aimodelarchitecture.form.component.js +73 -0
- package/dist/lib/generated/Entities/AIModelArchitecture/aimodelarchitecture.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/AIModelModality/aimodelmodality.form.component.d.ts +11 -0
- package/dist/lib/generated/Entities/AIModelModality/aimodelmodality.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/AIModelModality/aimodelmodality.form.component.js +89 -0
- package/dist/lib/generated/Entities/AIModelModality/aimodelmodality.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/AIModelType/aimodeltype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/AIModelType/aimodeltype.form.component.js +27 -13
- package/dist/lib/generated/Entities/AIModelType/aimodeltype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/ConversationDetail/conversationdetail.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/ConversationDetail/conversationdetail.form.component.js +39 -21
- package/dist/lib/generated/Entities/ConversationDetail/conversationdetail.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/ConversationDetailAttachment/conversationdetailattachment.form.component.d.ts +11 -0
- package/dist/lib/generated/Entities/ConversationDetailAttachment/conversationdetailattachment.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/ConversationDetailAttachment/conversationdetailattachment.form.component.js +95 -0
- package/dist/lib/generated/Entities/ConversationDetailAttachment/conversationdetailattachment.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/Entity/entity.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/Entity/entity.form.component.js +61 -43
- package/dist/lib/generated/Entities/Entity/entity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/File/file.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/File/file.form.component.js +22 -4
- package/dist/lib/generated/Entities/File/file.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/FileStorageProvider/filestorageprovider.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/FileStorageProvider/filestorageprovider.form.component.js +40 -4
- package/dist/lib/generated/Entities/FileStorageProvider/filestorageprovider.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/Test/test.form.component.js +17 -15
- package/dist/lib/generated/Entities/Test/test.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/TestRun/testrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/TestRun/testrun.form.component.js +55 -43
- package/dist/lib/generated/Entities/TestRun/testrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/TestRunFeedback/testrunfeedback.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/TestRunFeedback/testrunfeedback.form.component.js +9 -15
- package/dist/lib/generated/Entities/TestRunFeedback/testrunfeedback.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/TestSuite/testsuite.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/TestSuite/testsuite.form.component.js +39 -19
- package/dist/lib/generated/Entities/TestSuite/testsuite.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/TestSuiteRun/testsuiterun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/TestSuiteRun/testsuiterun.form.component.js +40 -16
- package/dist/lib/generated/Entities/TestSuiteRun/testsuiterun.form.component.js.map +1 -1
- package/dist/lib/generated/generated-forms.module.d.ts +145 -134
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
- package/dist/lib/generated/generated-forms.module.js +168 -87
- package/dist/lib/generated/generated-forms.module.js.map +1 -1
- package/package.json +28 -27
|
@@ -4,58 +4,243 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
|
8
|
-
import { Subject } from 'rxjs';
|
|
7
|
+
import { Component, ChangeDetectionStrategy, HostListener } from '@angular/core';
|
|
8
|
+
import { Subject, interval } from 'rxjs';
|
|
9
|
+
import { takeUntil } from 'rxjs/operators';
|
|
9
10
|
import { CompositeKey, Metadata, RunView } from '@memberjunction/core';
|
|
10
11
|
import { BaseFormComponent } from '@memberjunction/ng-base-forms';
|
|
11
12
|
import { RegisterClass } from '@memberjunction/global';
|
|
12
13
|
import { SharedService } from '@memberjunction/ng-shared';
|
|
13
14
|
import { TestRunFormComponent } from '../../generated/Entities/TestRun/testrun.form.component';
|
|
15
|
+
import { TagsHelper } from '@memberjunction/ng-testing';
|
|
16
|
+
import { createCopyOnlyToolbar } from '@memberjunction/ng-code-editor';
|
|
14
17
|
import * as i0 from "@angular/core";
|
|
15
18
|
import * as i1 from "@memberjunction/ng-shared";
|
|
16
19
|
import * as i2 from "@angular/router";
|
|
17
|
-
import * as i3 from "@
|
|
18
|
-
import * as i4 from "@
|
|
19
|
-
|
|
20
|
+
import * as i3 from "@memberjunction/ng-testing";
|
|
21
|
+
import * as i4 from "@memberjunction/ng-base-application";
|
|
22
|
+
import * as i5 from "@angular/common";
|
|
23
|
+
import * as i6 from "@angular/forms";
|
|
24
|
+
import * as i7 from "@progress/kendo-angular-buttons";
|
|
25
|
+
import * as i8 from "@memberjunction/ng-code-editor";
|
|
26
|
+
import * as i9 from "./entity-link-pill.component";
|
|
27
|
+
const _c0 = () => [1, 2, 3];
|
|
28
|
+
const _c1 = () => [1, 2];
|
|
29
|
+
const _c2 = () => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
30
|
+
function TestRunFormComponentExtended_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
20
31
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
21
|
-
i0.ɵɵelementStart(0, "
|
|
22
|
-
i0.ɵɵlistener("click", function
|
|
23
|
-
i0.ɵɵelement(1, "i",
|
|
32
|
+
i0.ɵɵelementStart(0, "div", 65);
|
|
33
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_1_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.retryLoad()); });
|
|
34
|
+
i0.ɵɵelement(1, "i", 66);
|
|
35
|
+
i0.ɵɵelementStart(2, "span");
|
|
36
|
+
i0.ɵɵtext(3);
|
|
37
|
+
i0.ɵɵelementEnd();
|
|
38
|
+
i0.ɵɵelementStart(4, "button", 67);
|
|
39
|
+
i0.ɵɵelement(5, "i", 21);
|
|
40
|
+
i0.ɵɵtext(6, " Retry ");
|
|
41
|
+
i0.ɵɵelementEnd()();
|
|
42
|
+
} if (rf & 2) {
|
|
43
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
44
|
+
i0.ɵɵadvance(3);
|
|
45
|
+
i0.ɵɵtextInterpolate(ctx_r1.error);
|
|
46
|
+
} }
|
|
47
|
+
function TestRunFormComponentExtended_li_10_Template(rf, ctx) { if (rf & 1) {
|
|
48
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
49
|
+
i0.ɵɵelementStart(0, "li");
|
|
50
|
+
i0.ɵɵelement(1, "i", 9);
|
|
51
|
+
i0.ɵɵelementStart(2, "a", 4);
|
|
52
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_li_10_Template_a_click_2_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openTest()); });
|
|
53
|
+
i0.ɵɵelement(3, "i", 68);
|
|
54
|
+
i0.ɵɵelementStart(4, "span", 6);
|
|
55
|
+
i0.ɵɵtext(5);
|
|
56
|
+
i0.ɵɵelementEnd()()();
|
|
57
|
+
} if (rf & 2) {
|
|
58
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
59
|
+
i0.ɵɵadvance(5);
|
|
60
|
+
i0.ɵɵtextInterpolate(ctx_r1.test.Name);
|
|
61
|
+
} }
|
|
62
|
+
function TestRunFormComponentExtended_span_27_Template(rf, ctx) { if (rf & 1) {
|
|
63
|
+
i0.ɵɵelementStart(0, "span", 69);
|
|
64
|
+
i0.ɵɵelement(1, "i", 68);
|
|
24
65
|
i0.ɵɵtext(2);
|
|
25
66
|
i0.ɵɵelementEnd();
|
|
26
67
|
} if (rf & 2) {
|
|
27
68
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
28
69
|
i0.ɵɵadvance(2);
|
|
29
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r1.test.
|
|
70
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.test.Type, " ");
|
|
71
|
+
} }
|
|
72
|
+
function TestRunFormComponentExtended_span_28_Template(rf, ctx) { if (rf & 1) {
|
|
73
|
+
i0.ɵɵelementStart(0, "span", 69);
|
|
74
|
+
i0.ɵɵelement(1, "i", 70);
|
|
75
|
+
i0.ɵɵtext(2, " Auto-refreshing ");
|
|
76
|
+
i0.ɵɵelementEnd();
|
|
77
|
+
} }
|
|
78
|
+
function TestRunFormComponentExtended_div_66_Template(rf, ctx) { if (rf & 1) {
|
|
79
|
+
i0.ɵɵelementStart(0, "div", 71);
|
|
80
|
+
i0.ɵɵelement(1, "div", 72);
|
|
81
|
+
i0.ɵɵelementEnd();
|
|
82
|
+
} if (rf & 2) {
|
|
83
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
84
|
+
i0.ɵɵadvance();
|
|
85
|
+
i0.ɵɵstyleProp("width", ctx_r1.getScorePercentage(), "%")("background-color", ctx_r1.getStatusColor());
|
|
30
86
|
} }
|
|
31
|
-
function
|
|
32
|
-
i0.ɵɵ
|
|
87
|
+
function TestRunFormComponentExtended_div_75_Template(rf, ctx) { if (rf & 1) {
|
|
88
|
+
i0.ɵɵelementStart(0, "div", 71);
|
|
89
|
+
i0.ɵɵelement(1, "div", 72);
|
|
90
|
+
i0.ɵɵelementEnd();
|
|
91
|
+
} if (rf & 2) {
|
|
92
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
93
|
+
i0.ɵɵadvance();
|
|
94
|
+
i0.ɵɵstyleProp("width", ctx_r1.getPassRatePercentage(), "%")("background-color", ctx_r1.getStatusColor());
|
|
33
95
|
} }
|
|
34
|
-
function
|
|
35
|
-
i0.ɵɵelementStart(0, "span",
|
|
96
|
+
function TestRunFormComponentExtended_div_84_span_1_Template(rf, ctx) { if (rf & 1) {
|
|
97
|
+
i0.ɵɵelementStart(0, "span", 77);
|
|
98
|
+
i0.ɵɵelement(1, "i", 78);
|
|
99
|
+
i0.ɵɵtext(2);
|
|
100
|
+
i0.ɵɵelementEnd();
|
|
101
|
+
} if (rf & 2) {
|
|
102
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
103
|
+
i0.ɵɵadvance(2);
|
|
104
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.record.RunByUser, " ");
|
|
105
|
+
} }
|
|
106
|
+
function TestRunFormComponentExtended_div_84_span_2_Template(rf, ctx) { if (rf & 1) {
|
|
107
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
108
|
+
i0.ɵɵelementStart(0, "span", 79);
|
|
109
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_84_span_2_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.openTestSuiteRun()); });
|
|
110
|
+
i0.ɵɵelement(1, "i", 80);
|
|
111
|
+
i0.ɵɵtext(2);
|
|
112
|
+
i0.ɵɵelementEnd();
|
|
113
|
+
} if (rf & 2) {
|
|
114
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
115
|
+
i0.ɵɵadvance(2);
|
|
116
|
+
i0.ɵɵtextInterpolate1(" Part of Suite Run (Seq: ", ctx_r1.record.Sequence, ") ");
|
|
117
|
+
} }
|
|
118
|
+
function TestRunFormComponentExtended_div_84_mj_entity_link_pill_3_Template(rf, ctx) { if (rf & 1) {
|
|
119
|
+
i0.ɵɵelement(0, "mj-entity-link-pill", 81);
|
|
120
|
+
} if (rf & 2) {
|
|
121
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
122
|
+
i0.ɵɵproperty("entityName", ctx_r1.record.TargetLogEntity)("recordId", ctx_r1.record.TargetLogID);
|
|
123
|
+
} }
|
|
124
|
+
function TestRunFormComponentExtended_div_84_Template(rf, ctx) { if (rf & 1) {
|
|
125
|
+
i0.ɵɵelementStart(0, "div", 73);
|
|
126
|
+
i0.ɵɵtemplate(1, TestRunFormComponentExtended_div_84_span_1_Template, 3, 1, "span", 74)(2, TestRunFormComponentExtended_div_84_span_2_Template, 3, 1, "span", 75)(3, TestRunFormComponentExtended_div_84_mj_entity_link_pill_3_Template, 1, 2, "mj-entity-link-pill", 76);
|
|
127
|
+
i0.ɵɵelementEnd();
|
|
128
|
+
} if (rf & 2) {
|
|
129
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
130
|
+
i0.ɵɵadvance();
|
|
131
|
+
i0.ɵɵproperty("ngIf", ctx_r1.record.RunByUser);
|
|
132
|
+
i0.ɵɵadvance();
|
|
133
|
+
i0.ɵɵproperty("ngIf", ctx_r1.testSuiteRun);
|
|
134
|
+
i0.ɵɵadvance();
|
|
135
|
+
i0.ɵɵproperty("ngIf", ctx_r1.record.TargetLogEntityID && ctx_r1.record.TargetLogID);
|
|
136
|
+
} }
|
|
137
|
+
function TestRunFormComponentExtended_div_85_div_4_span_1_Template(rf, ctx) { if (rf & 1) {
|
|
138
|
+
i0.ɵɵelementStart(0, "span", 92);
|
|
36
139
|
i0.ɵɵtext(1);
|
|
37
140
|
i0.ɵɵelementEnd();
|
|
141
|
+
} if (rf & 2) {
|
|
142
|
+
const tag_r6 = ctx.$implicit;
|
|
143
|
+
i0.ɵɵadvance();
|
|
144
|
+
i0.ɵɵtextInterpolate(tag_r6);
|
|
145
|
+
} }
|
|
146
|
+
function TestRunFormComponentExtended_div_85_div_4_Template(rf, ctx) { if (rf & 1) {
|
|
147
|
+
i0.ɵɵelementStart(0, "div", 90);
|
|
148
|
+
i0.ɵɵtemplate(1, TestRunFormComponentExtended_div_85_div_4_span_1_Template, 2, 1, "span", 91);
|
|
149
|
+
i0.ɵɵelementEnd();
|
|
150
|
+
} if (rf & 2) {
|
|
151
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
152
|
+
i0.ɵɵadvance();
|
|
153
|
+
i0.ɵɵproperty("ngForOf", ctx_r1.tags);
|
|
154
|
+
} }
|
|
155
|
+
function TestRunFormComponentExtended_div_85_span_5_Template(rf, ctx) { if (rf & 1) {
|
|
156
|
+
i0.ɵɵelementStart(0, "span", 93);
|
|
157
|
+
i0.ɵɵtext(1, "No tags");
|
|
158
|
+
i0.ɵɵelementEnd();
|
|
159
|
+
} }
|
|
160
|
+
function TestRunFormComponentExtended_div_85_Template(rf, ctx) { if (rf & 1) {
|
|
161
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
162
|
+
i0.ɵɵelementStart(0, "div", 82)(1, "div", 83)(2, "span", 84);
|
|
163
|
+
i0.ɵɵelement(3, "i", 85);
|
|
164
|
+
i0.ɵɵelementEnd();
|
|
165
|
+
i0.ɵɵtemplate(4, TestRunFormComponentExtended_div_85_div_4_Template, 2, 1, "div", 86)(5, TestRunFormComponentExtended_div_85_span_5_Template, 2, 0, "span", 87);
|
|
166
|
+
i0.ɵɵelementStart(6, "button", 88);
|
|
167
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_85_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.startEditingTags()); });
|
|
168
|
+
i0.ɵɵelement(7, "i", 89);
|
|
169
|
+
i0.ɵɵtext(8, " Add ");
|
|
170
|
+
i0.ɵɵelementEnd()()();
|
|
38
171
|
} if (rf & 2) {
|
|
39
172
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
173
|
+
i0.ɵɵadvance(4);
|
|
174
|
+
i0.ɵɵproperty("ngIf", ctx_r1.tags.length > 0);
|
|
40
175
|
i0.ɵɵadvance();
|
|
41
|
-
i0.ɵɵ
|
|
176
|
+
i0.ɵɵproperty("ngIf", ctx_r1.tags.length === 0);
|
|
42
177
|
} }
|
|
43
|
-
function
|
|
44
|
-
const
|
|
45
|
-
i0.ɵɵelementStart(0, "
|
|
46
|
-
i0.ɵɵtext(
|
|
178
|
+
function TestRunFormComponentExtended_div_86_span_7_Template(rf, ctx) { if (rf & 1) {
|
|
179
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
180
|
+
i0.ɵɵelementStart(0, "span", 108);
|
|
181
|
+
i0.ɵɵtext(1);
|
|
182
|
+
i0.ɵɵelementStart(2, "button", 109);
|
|
183
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_86_span_7_Template_button_click_2_listener() { const tag_r9 = i0.ɵɵrestoreView(_r8).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.removeTag(tag_r9)); });
|
|
184
|
+
i0.ɵɵelement(3, "i", 110);
|
|
185
|
+
i0.ɵɵelementEnd()();
|
|
186
|
+
} if (rf & 2) {
|
|
187
|
+
const tag_r9 = ctx.$implicit;
|
|
188
|
+
i0.ɵɵadvance();
|
|
189
|
+
i0.ɵɵtextInterpolate1(" ", tag_r9, " ");
|
|
190
|
+
} }
|
|
191
|
+
function TestRunFormComponentExtended_div_86_span_8_Template(rf, ctx) { if (rf & 1) {
|
|
192
|
+
i0.ɵɵelementStart(0, "span", 111);
|
|
193
|
+
i0.ɵɵtext(1, "No tags yet");
|
|
47
194
|
i0.ɵɵelementEnd();
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
i0.ɵɵ
|
|
195
|
+
} }
|
|
196
|
+
function TestRunFormComponentExtended_div_86_i_15_Template(rf, ctx) { if (rf & 1) {
|
|
197
|
+
i0.ɵɵelement(0, "i", 112);
|
|
198
|
+
} }
|
|
199
|
+
function TestRunFormComponentExtended_div_86_Template(rf, ctx) { if (rf & 1) {
|
|
200
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
201
|
+
i0.ɵɵelementStart(0, "div", 94)(1, "div", 95)(2, "span", 96);
|
|
202
|
+
i0.ɵɵelement(3, "i", 85);
|
|
203
|
+
i0.ɵɵtext(4, " Edit Tags");
|
|
51
204
|
i0.ɵɵelementEnd()();
|
|
205
|
+
i0.ɵɵelementStart(5, "div", 97)(6, "div", 98);
|
|
206
|
+
i0.ɵɵtemplate(7, TestRunFormComponentExtended_div_86_span_7_Template, 4, 1, "span", 99)(8, TestRunFormComponentExtended_div_86_span_8_Template, 2, 0, "span", 100);
|
|
207
|
+
i0.ɵɵelementEnd();
|
|
208
|
+
i0.ɵɵelementStart(9, "div", 101)(10, "input", 102);
|
|
209
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TestRunFormComponentExtended_div_86_Template_input_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newTag, $event) || (ctx_r1.newTag = $event); return i0.ɵɵresetView($event); });
|
|
210
|
+
i0.ɵɵlistener("keyup.enter", function TestRunFormComponentExtended_div_86_Template_input_keyup_enter_10_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.addTag()); });
|
|
211
|
+
i0.ɵɵelementEnd();
|
|
212
|
+
i0.ɵɵelementStart(11, "button", 103);
|
|
213
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_86_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.addTag()); });
|
|
214
|
+
i0.ɵɵelement(12, "i", 89);
|
|
215
|
+
i0.ɵɵelementEnd()()();
|
|
216
|
+
i0.ɵɵelementStart(13, "div", 104)(14, "button", 105);
|
|
217
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_86_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.saveTags()); });
|
|
218
|
+
i0.ɵɵtemplate(15, TestRunFormComponentExtended_div_86_i_15_Template, 1, 0, "i", 106);
|
|
219
|
+
i0.ɵɵtext(16);
|
|
220
|
+
i0.ɵɵelementEnd();
|
|
221
|
+
i0.ɵɵelementStart(17, "button", 107);
|
|
222
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_86_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelEditingTags()); });
|
|
223
|
+
i0.ɵɵtext(18, "Cancel");
|
|
224
|
+
i0.ɵɵelementEnd()()();
|
|
52
225
|
} if (rf & 2) {
|
|
53
226
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
54
|
-
i0.ɵɵadvance(
|
|
55
|
-
i0.ɵɵ
|
|
227
|
+
i0.ɵɵadvance(7);
|
|
228
|
+
i0.ɵɵproperty("ngForOf", ctx_r1.tags);
|
|
229
|
+
i0.ɵɵadvance();
|
|
230
|
+
i0.ɵɵproperty("ngIf", ctx_r1.tags.length === 0);
|
|
231
|
+
i0.ɵɵadvance(2);
|
|
232
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newTag);
|
|
233
|
+
i0.ɵɵadvance();
|
|
234
|
+
i0.ɵɵproperty("disabled", !ctx_r1.newTag.trim());
|
|
235
|
+
i0.ɵɵadvance(3);
|
|
236
|
+
i0.ɵɵproperty("disabled", ctx_r1.savingTags);
|
|
237
|
+
i0.ɵɵadvance();
|
|
238
|
+
i0.ɵɵproperty("ngIf", ctx_r1.savingTags);
|
|
239
|
+
i0.ɵɵadvance();
|
|
240
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.savingTags ? "Saving..." : "Save", " ");
|
|
56
241
|
} }
|
|
57
|
-
function
|
|
58
|
-
i0.ɵɵelementStart(0, "span",
|
|
242
|
+
function TestRunFormComponentExtended_span_101_Template(rf, ctx) { if (rf & 1) {
|
|
243
|
+
i0.ɵɵelementStart(0, "span", 113);
|
|
59
244
|
i0.ɵɵtext(1);
|
|
60
245
|
i0.ɵɵelementEnd();
|
|
61
246
|
} if (rf & 2) {
|
|
@@ -63,8 +248,8 @@ function TestRunFormComponentExtended_span_78_Template(rf, ctx) { if (rf & 1) {
|
|
|
63
248
|
i0.ɵɵadvance();
|
|
64
249
|
i0.ɵɵtextInterpolate(ctx_r1.aiAgentRuns.length + ctx_r1.aiPromptRuns.length);
|
|
65
250
|
} }
|
|
66
|
-
function
|
|
67
|
-
i0.ɵɵelementStart(0, "span",
|
|
251
|
+
function TestRunFormComponentExtended_span_106_Template(rf, ctx) { if (rf & 1) {
|
|
252
|
+
i0.ɵɵelementStart(0, "span", 113);
|
|
68
253
|
i0.ɵɵtext(1);
|
|
69
254
|
i0.ɵɵelementEnd();
|
|
70
255
|
} if (rf & 2) {
|
|
@@ -72,450 +257,585 @@ function TestRunFormComponentExtended_span_83_Template(rf, ctx) { if (rf & 1) {
|
|
|
72
257
|
i0.ɵɵadvance();
|
|
73
258
|
i0.ɵɵtextInterpolate(ctx_r1.feedbacks.length);
|
|
74
259
|
} }
|
|
75
|
-
function
|
|
76
|
-
i0.ɵɵ
|
|
260
|
+
function TestRunFormComponentExtended_button_111_Template(rf, ctx) { if (rf & 1) {
|
|
261
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
262
|
+
i0.ɵɵelementStart(0, "button", 114);
|
|
263
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_button_111_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.changeTab("log")); });
|
|
264
|
+
i0.ɵɵelement(1, "i", 115);
|
|
265
|
+
i0.ɵɵelementStart(2, "span");
|
|
266
|
+
i0.ɵɵtext(3, "Log");
|
|
267
|
+
i0.ɵɵelementEnd()();
|
|
268
|
+
} if (rf & 2) {
|
|
269
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
270
|
+
i0.ɵɵclassProp("active", ctx_r1.activeTab === "log");
|
|
271
|
+
i0.ɵɵattribute("aria-selected", ctx_r1.activeTab === "log");
|
|
272
|
+
} }
|
|
273
|
+
function TestRunFormComponentExtended_div_113_div_5_Template(rf, ctx) { if (rf & 1) {
|
|
274
|
+
i0.ɵɵelement(0, "div", 137);
|
|
275
|
+
} }
|
|
276
|
+
function TestRunFormComponentExtended_div_113_div_16_div_8_div_6_Template(rf, ctx) { if (rf & 1) {
|
|
277
|
+
i0.ɵɵelementStart(0, "div", 150);
|
|
77
278
|
i0.ɵɵtext(1);
|
|
78
279
|
i0.ɵɵelementEnd();
|
|
79
280
|
} if (rf & 2) {
|
|
80
|
-
const
|
|
281
|
+
const check_r12 = i0.ɵɵnextContext().$implicit;
|
|
81
282
|
i0.ɵɵadvance();
|
|
82
|
-
i0.ɵɵ
|
|
283
|
+
i0.ɵɵtextInterpolate(check_r12.message);
|
|
284
|
+
} }
|
|
285
|
+
function TestRunFormComponentExtended_div_113_div_16_div_8_div_7_Template(rf, ctx) { if (rf & 1) {
|
|
286
|
+
i0.ɵɵelementStart(0, "div", 151)(1, "span", 152);
|
|
287
|
+
i0.ɵɵtext(2, "Weight:");
|
|
288
|
+
i0.ɵɵelementEnd();
|
|
289
|
+
i0.ɵɵtext(3);
|
|
290
|
+
i0.ɵɵelementEnd();
|
|
291
|
+
} if (rf & 2) {
|
|
292
|
+
const check_r12 = i0.ɵɵnextContext().$implicit;
|
|
293
|
+
i0.ɵɵadvance(3);
|
|
294
|
+
i0.ɵɵtextInterpolate1(" ", check_r12.weight, " ");
|
|
83
295
|
} }
|
|
84
|
-
function
|
|
85
|
-
i0.ɵɵelementStart(0, "div",
|
|
86
|
-
i0.ɵɵelement(2, "i",
|
|
296
|
+
function TestRunFormComponentExtended_div_113_div_16_div_8_Template(rf, ctx) { if (rf & 1) {
|
|
297
|
+
i0.ɵɵelementStart(0, "div", 143)(1, "div", 144);
|
|
298
|
+
i0.ɵɵelement(2, "i", 145);
|
|
87
299
|
i0.ɵɵelementEnd();
|
|
88
|
-
i0.ɵɵelementStart(3, "div",
|
|
300
|
+
i0.ɵɵelementStart(3, "div", 146)(4, "div", 147);
|
|
89
301
|
i0.ɵɵtext(5);
|
|
90
302
|
i0.ɵɵelementEnd();
|
|
91
|
-
i0.ɵɵ
|
|
92
|
-
i0.ɵɵ
|
|
303
|
+
i0.ɵɵtemplate(6, TestRunFormComponentExtended_div_113_div_16_div_8_div_6_Template, 2, 1, "div", 148);
|
|
304
|
+
i0.ɵɵelementEnd();
|
|
305
|
+
i0.ɵɵtemplate(7, TestRunFormComponentExtended_div_113_div_16_div_8_div_7_Template, 4, 1, "div", 149);
|
|
93
306
|
i0.ɵɵelementEnd();
|
|
94
|
-
i0.ɵɵtemplate(8, TestRunFormComponentExtended_div_85_div_11_div_4_div_8_Template, 2, 1, "div", 61);
|
|
95
|
-
i0.ɵɵelementEnd()();
|
|
96
307
|
} if (rf & 2) {
|
|
97
|
-
const
|
|
98
|
-
|
|
308
|
+
const check_r12 = ctx.$implicit;
|
|
309
|
+
const i_r13 = ctx.index;
|
|
310
|
+
i0.ɵɵstyleProp("animation-delay", i_r13 * 50, "ms");
|
|
311
|
+
i0.ɵɵclassProp("passed", check_r12.passed)("failed", !check_r12.passed);
|
|
99
312
|
i0.ɵɵadvance(2);
|
|
100
|
-
i0.ɵɵclassProp("fa-check-circle",
|
|
313
|
+
i0.ɵɵclassProp("fa-check-circle", check_r12.passed)("fa-times-circle", !check_r12.passed);
|
|
101
314
|
i0.ɵɵadvance(3);
|
|
102
|
-
i0.ɵɵtextInterpolate(
|
|
103
|
-
i0.ɵɵadvance(2);
|
|
104
|
-
i0.ɵɵtextInterpolate(check_r5.message);
|
|
315
|
+
i0.ɵɵtextInterpolate(check_r12.name);
|
|
105
316
|
i0.ɵɵadvance();
|
|
106
|
-
i0.ɵɵproperty("ngIf",
|
|
317
|
+
i0.ɵɵproperty("ngIf", check_r12.message);
|
|
318
|
+
i0.ɵɵadvance();
|
|
319
|
+
i0.ɵɵproperty("ngIf", check_r12.weight);
|
|
107
320
|
} }
|
|
108
|
-
function
|
|
109
|
-
i0.ɵɵelementStart(0, "div",
|
|
110
|
-
i0.ɵɵ
|
|
321
|
+
function TestRunFormComponentExtended_div_113_div_16_Template(rf, ctx) { if (rf & 1) {
|
|
322
|
+
i0.ɵɵelementStart(0, "div", 138)(1, "div", 128)(2, "h3");
|
|
323
|
+
i0.ɵɵelement(3, "i", 139);
|
|
324
|
+
i0.ɵɵtext(4, " Check Results");
|
|
111
325
|
i0.ɵɵelementEnd();
|
|
112
|
-
i0.ɵɵelementStart(
|
|
113
|
-
i0.ɵɵ
|
|
326
|
+
i0.ɵɵelementStart(5, "span", 140);
|
|
327
|
+
i0.ɵɵtext(6);
|
|
328
|
+
i0.ɵɵelementEnd()();
|
|
329
|
+
i0.ɵɵelementStart(7, "div", 141);
|
|
330
|
+
i0.ɵɵtemplate(8, TestRunFormComponentExtended_div_113_div_16_div_8_Template, 8, 13, "div", 142);
|
|
114
331
|
i0.ɵɵelementEnd()();
|
|
115
332
|
} if (rf & 2) {
|
|
116
333
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
117
|
-
i0.ɵɵadvance(
|
|
334
|
+
i0.ɵɵadvance(6);
|
|
335
|
+
i0.ɵɵtextInterpolate2("", ctx_r1.record.PassedChecks, " passed, ", ctx_r1.record.FailedChecks, " failed");
|
|
336
|
+
i0.ɵɵadvance(2);
|
|
118
337
|
i0.ɵɵproperty("ngForOf", ctx_r1.getCheckResults());
|
|
119
338
|
} }
|
|
120
|
-
function
|
|
121
|
-
const
|
|
122
|
-
i0.ɵɵelementStart(0, "div",
|
|
123
|
-
i0.ɵɵelement(
|
|
339
|
+
function TestRunFormComponentExtended_div_113_Template(rf, ctx) { if (rf & 1) {
|
|
340
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
341
|
+
i0.ɵɵelementStart(0, "div", 116)(1, "div", 117)(2, "div", 118)(3, "div", 119);
|
|
342
|
+
i0.ɵɵelement(4, "i", 13);
|
|
124
343
|
i0.ɵɵelementEnd();
|
|
125
|
-
i0.ɵɵ
|
|
126
|
-
i0.ɵɵtext(6);
|
|
344
|
+
i0.ɵɵtemplate(5, TestRunFormComponentExtended_div_113_div_5_Template, 1, 0, "div", 120);
|
|
127
345
|
i0.ɵɵelementEnd();
|
|
128
|
-
i0.ɵɵelementStart(
|
|
346
|
+
i0.ɵɵelementStart(6, "div", 121)(7, "h2");
|
|
129
347
|
i0.ɵɵtext(8);
|
|
130
348
|
i0.ɵɵelementEnd();
|
|
131
|
-
i0.ɵɵelementStart(9, "div",
|
|
132
|
-
i0.ɵɵtext(
|
|
133
|
-
i0.ɵɵelementEnd()()();
|
|
134
|
-
i0.ɵɵtemplate(11, TestRunFormComponentExtended_div_85_div_11_Template, 5, 1, "div", 47);
|
|
135
|
-
i0.ɵɵelementStart(12, "div", 48)(13, "h3");
|
|
136
|
-
i0.ɵɵtext(14, "Data Comparison");
|
|
349
|
+
i0.ɵɵelementStart(9, "div", 122)(10, "span", 123);
|
|
350
|
+
i0.ɵɵtext(11);
|
|
137
351
|
i0.ɵɵelementEnd();
|
|
138
|
-
i0.ɵɵelementStart(
|
|
139
|
-
i0.ɵɵ
|
|
140
|
-
i0.ɵɵtext(17, " Input ");
|
|
352
|
+
i0.ɵɵelementStart(12, "span", 124);
|
|
353
|
+
i0.ɵɵtext(13, "|");
|
|
141
354
|
i0.ɵɵelementEnd();
|
|
142
|
-
i0.ɵɵelementStart(
|
|
143
|
-
i0.ɵɵ
|
|
144
|
-
i0.ɵɵ
|
|
355
|
+
i0.ɵɵelementStart(14, "span", 125);
|
|
356
|
+
i0.ɵɵtext(15);
|
|
357
|
+
i0.ɵɵelementEnd()()()();
|
|
358
|
+
i0.ɵɵtemplate(16, TestRunFormComponentExtended_div_113_div_16_Template, 9, 3, "div", 126);
|
|
359
|
+
i0.ɵɵelementStart(17, "div", 127)(18, "div", 128)(19, "h3");
|
|
360
|
+
i0.ɵɵelement(20, "i", 129);
|
|
361
|
+
i0.ɵɵtext(21, " Data Comparison");
|
|
362
|
+
i0.ɵɵelementEnd()();
|
|
363
|
+
i0.ɵɵelementStart(22, "div", 130)(23, "button", 131);
|
|
364
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_113_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setComparisonView("input")); });
|
|
365
|
+
i0.ɵɵelement(24, "i", 132);
|
|
366
|
+
i0.ɵɵtext(25, " Input ");
|
|
367
|
+
i0.ɵɵelementEnd();
|
|
368
|
+
i0.ɵɵelementStart(26, "button", 131);
|
|
369
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_113_Template_button_click_26_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setComparisonView("expected")); });
|
|
370
|
+
i0.ɵɵelement(27, "i", 133);
|
|
371
|
+
i0.ɵɵtext(28, " Expected ");
|
|
145
372
|
i0.ɵɵelementEnd();
|
|
146
|
-
i0.ɵɵelementStart(
|
|
147
|
-
i0.ɵɵlistener("click", function
|
|
148
|
-
i0.ɵɵ
|
|
373
|
+
i0.ɵɵelementStart(29, "button", 131);
|
|
374
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_113_Template_button_click_29_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setComparisonView("actual")); });
|
|
375
|
+
i0.ɵɵelement(30, "i", 134);
|
|
376
|
+
i0.ɵɵtext(31, " Actual ");
|
|
149
377
|
i0.ɵɵelementEnd()();
|
|
150
|
-
i0.ɵɵelementStart(
|
|
151
|
-
i0.ɵɵ
|
|
152
|
-
i0.ɵɵ
|
|
153
|
-
i0.ɵɵelementEnd()()()();
|
|
378
|
+
i0.ɵɵelementStart(32, "div", 135);
|
|
379
|
+
i0.ɵɵelement(33, "mj-code-editor", 136);
|
|
380
|
+
i0.ɵɵelementEnd()()();
|
|
154
381
|
} if (rf & 2) {
|
|
155
382
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
383
|
+
i0.ɵɵproperty("@fadeIn", undefined);
|
|
156
384
|
i0.ɵɵadvance();
|
|
157
|
-
i0.ɵɵ
|
|
158
|
-
i0.ɵɵadvance(
|
|
385
|
+
i0.ɵɵclassMap(ctx_r1.getStatusClass());
|
|
386
|
+
i0.ɵɵadvance(3);
|
|
159
387
|
i0.ɵɵproperty("ngClass", ctx_r1.getStatusIcon());
|
|
388
|
+
i0.ɵɵadvance();
|
|
389
|
+
i0.ɵɵproperty("ngIf", ctx_r1.record.Status === "Running");
|
|
160
390
|
i0.ɵɵadvance(3);
|
|
161
391
|
i0.ɵɵtextInterpolate1("TEST ", ctx_r1.record.Status.toUpperCase(), "");
|
|
162
|
-
i0.ɵɵadvance(
|
|
163
|
-
i0.ɵɵtextInterpolate1("Score: ", ctx_r1.formatScore(ctx_r1.record.Score), "
|
|
164
|
-
i0.ɵɵadvance(
|
|
392
|
+
i0.ɵɵadvance(3);
|
|
393
|
+
i0.ɵɵtextInterpolate1("Score: ", ctx_r1.formatScore(ctx_r1.record.Score), "");
|
|
394
|
+
i0.ɵɵadvance(4);
|
|
165
395
|
i0.ɵɵtextInterpolate2("", ctx_r1.record.PassedChecks, " of ", ctx_r1.record.TotalChecks, " checks passed");
|
|
166
396
|
i0.ɵɵadvance();
|
|
167
397
|
i0.ɵɵproperty("ngIf", ctx_r1.getCheckResults().length > 0);
|
|
168
|
-
i0.ɵɵadvance(
|
|
398
|
+
i0.ɵɵadvance(7);
|
|
169
399
|
i0.ɵɵclassProp("active", ctx_r1.comparisonView === "input");
|
|
170
|
-
i0.ɵɵadvance(
|
|
400
|
+
i0.ɵɵadvance(3);
|
|
171
401
|
i0.ɵɵclassProp("active", ctx_r1.comparisonView === "expected");
|
|
172
|
-
i0.ɵɵadvance(
|
|
402
|
+
i0.ɵɵadvance(3);
|
|
173
403
|
i0.ɵɵclassProp("active", ctx_r1.comparisonView === "actual");
|
|
174
404
|
i0.ɵɵadvance(4);
|
|
175
|
-
i0.ɵɵ
|
|
405
|
+
i0.ɵɵproperty("value", ctx_r1.getComparisonData())("readonly", true)("toolbar", ctx_r1.jsonToolbar)("lineWrapping", true);
|
|
176
406
|
} }
|
|
177
|
-
function
|
|
178
|
-
const
|
|
179
|
-
i0.ɵɵelementStart(0, "
|
|
180
|
-
i0.ɵɵlistener("click", function
|
|
181
|
-
i0.ɵɵ
|
|
407
|
+
function TestRunFormComponentExtended_div_114_div_10_Template(rf, ctx) { if (rf & 1) {
|
|
408
|
+
const _r14 = i0.ɵɵgetCurrentView();
|
|
409
|
+
i0.ɵɵelementStart(0, "div", 169);
|
|
410
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_114_div_10_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.openTest()); });
|
|
411
|
+
i0.ɵɵelementStart(1, "div", 156);
|
|
412
|
+
i0.ɵɵelement(2, "i", 68);
|
|
413
|
+
i0.ɵɵelementEnd();
|
|
414
|
+
i0.ɵɵelementStart(3, "div", 158)(4, "div", 159);
|
|
415
|
+
i0.ɵɵtext(5, "Test");
|
|
416
|
+
i0.ɵɵelementEnd();
|
|
417
|
+
i0.ɵɵelementStart(6, "div", 170);
|
|
418
|
+
i0.ɵɵtext(7);
|
|
419
|
+
i0.ɵɵelementEnd()();
|
|
420
|
+
i0.ɵɵelement(8, "i", 171);
|
|
182
421
|
i0.ɵɵelementEnd();
|
|
183
422
|
} if (rf & 2) {
|
|
184
423
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
185
|
-
i0.ɵɵadvance();
|
|
424
|
+
i0.ɵɵadvance(7);
|
|
186
425
|
i0.ɵɵtextInterpolate(ctx_r1.test.Name);
|
|
187
426
|
} }
|
|
188
|
-
function
|
|
189
|
-
i0.ɵɵelementStart(0, "div",
|
|
190
|
-
i0.ɵɵ
|
|
191
|
-
i0.ɵɵ
|
|
192
|
-
i0.ɵɵ
|
|
193
|
-
i0.ɵɵ
|
|
427
|
+
function TestRunFormComponentExtended_div_114_div_45_Template(rf, ctx) { if (rf & 1) {
|
|
428
|
+
i0.ɵɵelementStart(0, "div", 172)(1, "div", 173)(2, "h3");
|
|
429
|
+
i0.ɵɵelement(3, "i", 66);
|
|
430
|
+
i0.ɵɵtext(4, " Error Message");
|
|
431
|
+
i0.ɵɵelementEnd()();
|
|
432
|
+
i0.ɵɵelementStart(5, "div", 174);
|
|
433
|
+
i0.ɵɵelement(6, "mj-code-editor", 175);
|
|
194
434
|
i0.ɵɵelementEnd()();
|
|
195
435
|
} if (rf & 2) {
|
|
196
436
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
197
|
-
i0.ɵɵadvance(
|
|
198
|
-
i0.ɵɵ
|
|
437
|
+
i0.ɵɵadvance(6);
|
|
438
|
+
i0.ɵɵproperty("value", ctx_r1.record.ErrorMessage)("readonly", true)("toolbar", ctx_r1.jsonToolbar)("lineWrapping", true);
|
|
199
439
|
} }
|
|
200
|
-
function
|
|
201
|
-
i0.ɵɵelementStart(0, "div",
|
|
202
|
-
i0.ɵɵ
|
|
203
|
-
i0.ɵɵ
|
|
204
|
-
i0.ɵɵ
|
|
205
|
-
i0.ɵɵ
|
|
206
|
-
i0.ɵɵ
|
|
440
|
+
function TestRunFormComponentExtended_div_114_div_46_Template(rf, ctx) { if (rf & 1) {
|
|
441
|
+
i0.ɵɵelementStart(0, "div", 176)(1, "div", 128)(2, "h3");
|
|
442
|
+
i0.ɵɵelement(3, "i", 177);
|
|
443
|
+
i0.ɵɵtext(4, " Result Details");
|
|
444
|
+
i0.ɵɵelementEnd()();
|
|
445
|
+
i0.ɵɵelementStart(5, "div", 178);
|
|
446
|
+
i0.ɵɵelement(6, "mj-code-editor", 136);
|
|
207
447
|
i0.ɵɵelementEnd()();
|
|
208
448
|
} if (rf & 2) {
|
|
209
449
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
210
|
-
i0.ɵɵadvance(
|
|
211
|
-
i0.ɵɵ
|
|
450
|
+
i0.ɵɵadvance(6);
|
|
451
|
+
i0.ɵɵproperty("value", ctx_r1.getFormattedResultDetails())("readonly", true)("toolbar", ctx_r1.jsonToolbar)("lineWrapping", true);
|
|
212
452
|
} }
|
|
213
|
-
function
|
|
214
|
-
i0.ɵɵelementStart(0, "div",
|
|
215
|
-
i0.ɵɵ
|
|
453
|
+
function TestRunFormComponentExtended_div_114_Template(rf, ctx) { if (rf & 1) {
|
|
454
|
+
i0.ɵɵelementStart(0, "div", 153)(1, "div", 154)(2, "div", 155)(3, "div", 156);
|
|
455
|
+
i0.ɵɵelement(4, "i", 157);
|
|
216
456
|
i0.ɵɵelementEnd();
|
|
217
|
-
i0.ɵɵelementStart(5, "div",
|
|
218
|
-
i0.ɵɵtext(
|
|
219
|
-
i0.ɵɵelementEnd()();
|
|
220
|
-
i0.ɵɵelementStart(7, "div", 65)(8, "div", 66);
|
|
221
|
-
i0.ɵɵtext(9, "Test");
|
|
457
|
+
i0.ɵɵelementStart(5, "div", 158)(6, "div", 159);
|
|
458
|
+
i0.ɵɵtext(7, "Test Run ID");
|
|
222
459
|
i0.ɵɵelementEnd();
|
|
223
|
-
i0.ɵɵelementStart(
|
|
224
|
-
i0.ɵɵ
|
|
225
|
-
i0.ɵɵelementEnd()();
|
|
226
|
-
i0.ɵɵ
|
|
227
|
-
i0.ɵɵ
|
|
460
|
+
i0.ɵɵelementStart(8, "div", 160);
|
|
461
|
+
i0.ɵɵtext(9);
|
|
462
|
+
i0.ɵɵelementEnd()()();
|
|
463
|
+
i0.ɵɵtemplate(10, TestRunFormComponentExtended_div_114_div_10_Template, 9, 1, "div", 161);
|
|
464
|
+
i0.ɵɵelementStart(11, "div", 155)(12, "div", 156);
|
|
465
|
+
i0.ɵɵelement(13, "i", 162);
|
|
228
466
|
i0.ɵɵelementEnd();
|
|
229
|
-
i0.ɵɵelementStart(15, "div",
|
|
230
|
-
i0.ɵɵtext(16);
|
|
231
|
-
i0.ɵɵelementEnd()();
|
|
232
|
-
i0.ɵɵelementStart(17, "div", 65)(18, "div", 66);
|
|
233
|
-
i0.ɵɵtext(19, "Target Type");
|
|
467
|
+
i0.ɵɵelementStart(14, "div", 158)(15, "div", 159);
|
|
468
|
+
i0.ɵɵtext(16, "Target Type");
|
|
234
469
|
i0.ɵɵelementEnd();
|
|
235
|
-
i0.ɵɵelementStart(
|
|
236
|
-
i0.ɵɵtext(
|
|
237
|
-
i0.ɵɵelementEnd()();
|
|
238
|
-
i0.ɵɵelementStart(
|
|
470
|
+
i0.ɵɵelementStart(17, "div", 163);
|
|
471
|
+
i0.ɵɵtext(18);
|
|
472
|
+
i0.ɵɵelementEnd()()();
|
|
473
|
+
i0.ɵɵelementStart(19, "div", 155)(20, "div", 156);
|
|
474
|
+
i0.ɵɵelement(21, "i", 164);
|
|
475
|
+
i0.ɵɵelementEnd();
|
|
476
|
+
i0.ɵɵelementStart(22, "div", 158)(23, "div", 159);
|
|
239
477
|
i0.ɵɵtext(24, "Started At");
|
|
240
478
|
i0.ɵɵelementEnd();
|
|
241
|
-
i0.ɵɵelementStart(25, "div",
|
|
479
|
+
i0.ɵɵelementStart(25, "div", 163);
|
|
242
480
|
i0.ɵɵtext(26);
|
|
243
481
|
i0.ɵɵpipe(27, "date");
|
|
244
|
-
i0.ɵɵelementEnd()();
|
|
245
|
-
i0.ɵɵelementStart(28, "div",
|
|
246
|
-
i0.ɵɵ
|
|
247
|
-
i0.ɵɵelementEnd();
|
|
248
|
-
i0.ɵɵelementStart(31, "div", 67);
|
|
249
|
-
i0.ɵɵtext(32);
|
|
250
|
-
i0.ɵɵpipe(33, "date");
|
|
251
|
-
i0.ɵɵelementEnd()();
|
|
252
|
-
i0.ɵɵelementStart(34, "div", 65)(35, "div", 66);
|
|
253
|
-
i0.ɵɵtext(36, "Duration");
|
|
254
|
-
i0.ɵɵelementEnd();
|
|
255
|
-
i0.ɵɵelementStart(37, "div", 67);
|
|
256
|
-
i0.ɵɵtext(38);
|
|
257
|
-
i0.ɵɵelementEnd()();
|
|
258
|
-
i0.ɵɵelementStart(39, "div", 65)(40, "div", 66);
|
|
259
|
-
i0.ɵɵtext(41, "Score");
|
|
260
|
-
i0.ɵɵelementEnd();
|
|
261
|
-
i0.ɵɵelementStart(42, "div", 67);
|
|
262
|
-
i0.ɵɵtext(43);
|
|
263
|
-
i0.ɵɵelementEnd()();
|
|
264
|
-
i0.ɵɵelementStart(44, "div", 65)(45, "div", 66);
|
|
265
|
-
i0.ɵɵtext(46, "Cost");
|
|
482
|
+
i0.ɵɵelementEnd()()();
|
|
483
|
+
i0.ɵɵelementStart(28, "div", 155)(29, "div", 156);
|
|
484
|
+
i0.ɵɵelement(30, "i", 165);
|
|
266
485
|
i0.ɵɵelementEnd();
|
|
267
|
-
i0.ɵɵelementStart(
|
|
268
|
-
i0.ɵɵtext(
|
|
269
|
-
i0.ɵɵelementEnd()();
|
|
270
|
-
i0.ɵɵelementStart(49, "div", 65)(50, "div", 66);
|
|
271
|
-
i0.ɵɵtext(51, "Passed Checks");
|
|
486
|
+
i0.ɵɵelementStart(31, "div", 158)(32, "div", 159);
|
|
487
|
+
i0.ɵɵtext(33, "Completed At");
|
|
272
488
|
i0.ɵɵelementEnd();
|
|
273
|
-
i0.ɵɵelementStart(
|
|
274
|
-
i0.ɵɵtext(
|
|
275
|
-
i0.ɵɵ
|
|
276
|
-
i0.ɵɵ
|
|
277
|
-
i0.ɵɵ
|
|
489
|
+
i0.ɵɵelementStart(34, "div", 163);
|
|
490
|
+
i0.ɵɵtext(35);
|
|
491
|
+
i0.ɵɵpipe(36, "date");
|
|
492
|
+
i0.ɵɵelementEnd()()();
|
|
493
|
+
i0.ɵɵelementStart(37, "div", 155)(38, "div", 156);
|
|
494
|
+
i0.ɵɵelement(39, "i", 166);
|
|
278
495
|
i0.ɵɵelementEnd();
|
|
279
|
-
i0.ɵɵelementStart(
|
|
280
|
-
i0.ɵɵtext(
|
|
281
|
-
i0.ɵɵelementEnd()();
|
|
282
|
-
i0.ɵɵelementStart(59, "div", 65)(60, "div", 66);
|
|
283
|
-
i0.ɵɵtext(61, "Total Checks");
|
|
496
|
+
i0.ɵɵelementStart(40, "div", 158)(41, "div", 159);
|
|
497
|
+
i0.ɵɵtext(42, "Duration");
|
|
284
498
|
i0.ɵɵelementEnd();
|
|
285
|
-
i0.ɵɵelementStart(
|
|
286
|
-
i0.ɵɵtext(
|
|
287
|
-
i0.ɵɵelementEnd()()();
|
|
288
|
-
i0.ɵɵtemplate(
|
|
499
|
+
i0.ɵɵelementStart(43, "div", 163);
|
|
500
|
+
i0.ɵɵtext(44);
|
|
501
|
+
i0.ɵɵelementEnd()()()();
|
|
502
|
+
i0.ɵɵtemplate(45, TestRunFormComponentExtended_div_114_div_45_Template, 7, 4, "div", 167)(46, TestRunFormComponentExtended_div_114_div_46_Template, 7, 4, "div", 168);
|
|
289
503
|
i0.ɵɵelementEnd();
|
|
290
504
|
} if (rf & 2) {
|
|
291
505
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
292
|
-
i0.ɵɵ
|
|
506
|
+
i0.ɵɵproperty("@fadeIn", undefined);
|
|
507
|
+
i0.ɵɵadvance(9);
|
|
293
508
|
i0.ɵɵtextInterpolate(ctx_r1.record.ID);
|
|
294
|
-
i0.ɵɵadvance(
|
|
509
|
+
i0.ɵɵadvance();
|
|
295
510
|
i0.ɵɵproperty("ngIf", ctx_r1.test);
|
|
296
|
-
i0.ɵɵadvance(
|
|
297
|
-
i0.ɵɵtextInterpolate(ctx_r1.record.Status);
|
|
298
|
-
i0.ɵɵadvance(5);
|
|
511
|
+
i0.ɵɵadvance(8);
|
|
299
512
|
i0.ɵɵtextInterpolate(ctx_r1.record.TargetType || "N/A");
|
|
300
|
-
i0.ɵɵadvance(
|
|
301
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(27,
|
|
302
|
-
i0.ɵɵadvance(
|
|
303
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(
|
|
304
|
-
i0.ɵɵadvance(
|
|
513
|
+
i0.ɵɵadvance(8);
|
|
514
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(27, 9, ctx_r1.record.StartedAt, "medium"));
|
|
515
|
+
i0.ɵɵadvance(9);
|
|
516
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(36, 12, ctx_r1.record.CompletedAt, "medium"));
|
|
517
|
+
i0.ɵɵadvance(9);
|
|
305
518
|
i0.ɵɵtextInterpolate(ctx_r1.calculateDuration());
|
|
306
|
-
i0.ɵɵadvance(5);
|
|
307
|
-
i0.ɵɵtextInterpolate(ctx_r1.formatScore(ctx_r1.record.Score));
|
|
308
|
-
i0.ɵɵadvance(5);
|
|
309
|
-
i0.ɵɵtextInterpolate(ctx_r1.formatCost(ctx_r1.record.CostUSD));
|
|
310
|
-
i0.ɵɵadvance(5);
|
|
311
|
-
i0.ɵɵtextInterpolate(ctx_r1.record.PassedChecks);
|
|
312
|
-
i0.ɵɵadvance(5);
|
|
313
|
-
i0.ɵɵtextInterpolate(ctx_r1.record.FailedChecks);
|
|
314
|
-
i0.ɵɵadvance(5);
|
|
315
|
-
i0.ɵɵtextInterpolate(ctx_r1.record.TotalChecks);
|
|
316
519
|
i0.ɵɵadvance();
|
|
317
520
|
i0.ɵɵproperty("ngIf", ctx_r1.record.ErrorMessage);
|
|
318
521
|
i0.ɵɵadvance();
|
|
319
|
-
i0.ɵɵproperty("ngIf", ctx_r1.
|
|
522
|
+
i0.ɵɵproperty("ngIf", ctx_r1.parsedData.resultDetails);
|
|
320
523
|
} }
|
|
321
|
-
function
|
|
322
|
-
i0.ɵɵelementStart(0, "
|
|
323
|
-
i0.ɵɵ
|
|
524
|
+
function TestRunFormComponentExtended_div_115_div_1_div_2_Template(rf, ctx) { if (rf & 1) {
|
|
525
|
+
i0.ɵɵelementStart(0, "div", 186);
|
|
526
|
+
i0.ɵɵelement(1, "div", 187);
|
|
527
|
+
i0.ɵɵelementStart(2, "div", 188);
|
|
528
|
+
i0.ɵɵelement(3, "div", 189)(4, "div", 190);
|
|
529
|
+
i0.ɵɵelementEnd()();
|
|
530
|
+
} }
|
|
531
|
+
function TestRunFormComponentExtended_div_115_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
532
|
+
i0.ɵɵelementStart(0, "div", 183)(1, "div", 184);
|
|
533
|
+
i0.ɵɵtemplate(2, TestRunFormComponentExtended_div_115_div_1_div_2_Template, 5, 0, "div", 185);
|
|
534
|
+
i0.ɵɵelementEnd()();
|
|
535
|
+
} if (rf & 2) {
|
|
536
|
+
i0.ɵɵadvance(2);
|
|
537
|
+
i0.ɵɵproperty("ngForOf", i0.ɵɵpureFunction0(1, _c0));
|
|
538
|
+
} }
|
|
539
|
+
function TestRunFormComponentExtended_div_115_div_2_div_8_span_9_Template(rf, ctx) { if (rf & 1) {
|
|
540
|
+
i0.ɵɵelementStart(0, "span", 203);
|
|
541
|
+
i0.ɵɵelement(1, "i", 37);
|
|
542
|
+
i0.ɵɵtext(2);
|
|
543
|
+
i0.ɵɵpipe(3, "number");
|
|
324
544
|
i0.ɵɵelementEnd();
|
|
325
545
|
} if (rf & 2) {
|
|
326
|
-
const
|
|
327
|
-
i0.ɵɵadvance();
|
|
328
|
-
i0.ɵɵtextInterpolate1("
|
|
546
|
+
const run_r16 = i0.ɵɵnextContext().$implicit;
|
|
547
|
+
i0.ɵɵadvance(2);
|
|
548
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind2(3, 1, run_r16.TotalCost, "1.4-4"), " ");
|
|
329
549
|
} }
|
|
330
|
-
function
|
|
331
|
-
const
|
|
332
|
-
i0.ɵɵelementStart(0, "div",
|
|
333
|
-
i0.ɵɵlistener("click", function
|
|
334
|
-
i0.ɵɵelementStart(1, "div",
|
|
335
|
-
i0.ɵɵelement(2, "i",
|
|
550
|
+
function TestRunFormComponentExtended_div_115_div_2_div_8_Template(rf, ctx) { if (rf & 1) {
|
|
551
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
552
|
+
i0.ɵɵelementStart(0, "div", 195);
|
|
553
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_115_div_2_div_8_Template_div_click_0_listener() { const run_r16 = i0.ɵɵrestoreView(_r15).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openAIAgentRun(run_r16.ID)); });
|
|
554
|
+
i0.ɵɵelementStart(1, "div", 196);
|
|
555
|
+
i0.ɵɵelement(2, "i", 48);
|
|
336
556
|
i0.ɵɵelementEnd();
|
|
337
|
-
i0.ɵɵelementStart(3, "div",
|
|
557
|
+
i0.ɵɵelementStart(3, "div", 197)(4, "div", 198);
|
|
338
558
|
i0.ɵɵtext(5);
|
|
339
559
|
i0.ɵɵelementEnd();
|
|
340
|
-
i0.ɵɵelementStart(6, "div",
|
|
560
|
+
i0.ɵɵelementStart(6, "div", 199)(7, "span", 200);
|
|
341
561
|
i0.ɵɵtext(8);
|
|
342
562
|
i0.ɵɵelementEnd();
|
|
343
|
-
i0.ɵɵtemplate(9,
|
|
563
|
+
i0.ɵɵtemplate(9, TestRunFormComponentExtended_div_115_div_2_div_8_span_9_Template, 4, 4, "span", 201);
|
|
344
564
|
i0.ɵɵelementEnd()();
|
|
345
|
-
i0.ɵɵelement(10, "i",
|
|
565
|
+
i0.ɵɵelement(10, "i", 202);
|
|
346
566
|
i0.ɵɵelementEnd();
|
|
347
567
|
} if (rf & 2) {
|
|
348
|
-
const
|
|
568
|
+
const run_r16 = ctx.$implicit;
|
|
349
569
|
i0.ɵɵadvance(5);
|
|
350
|
-
i0.ɵɵtextInterpolate(
|
|
351
|
-
i0.ɵɵadvance(
|
|
352
|
-
i0.ɵɵ
|
|
570
|
+
i0.ɵɵtextInterpolate(run_r16.Agent);
|
|
571
|
+
i0.ɵɵadvance(2);
|
|
572
|
+
i0.ɵɵclassMap(run_r16.Status.toLowerCase());
|
|
353
573
|
i0.ɵɵadvance();
|
|
354
|
-
i0.ɵɵ
|
|
574
|
+
i0.ɵɵtextInterpolate(run_r16.Status);
|
|
575
|
+
i0.ɵɵadvance();
|
|
576
|
+
i0.ɵɵproperty("ngIf", run_r16.TotalCost);
|
|
355
577
|
} }
|
|
356
|
-
function
|
|
357
|
-
i0.ɵɵelementStart(0, "div",
|
|
358
|
-
i0.ɵɵ
|
|
578
|
+
function TestRunFormComponentExtended_div_115_div_2_Template(rf, ctx) { if (rf & 1) {
|
|
579
|
+
i0.ɵɵelementStart(0, "div", 191)(1, "div", 128)(2, "h3");
|
|
580
|
+
i0.ɵɵelement(3, "i", 48);
|
|
581
|
+
i0.ɵɵtext(4, " AI Agent Runs");
|
|
359
582
|
i0.ɵɵelementEnd();
|
|
360
|
-
i0.ɵɵelementStart(
|
|
361
|
-
i0.ɵɵ
|
|
583
|
+
i0.ɵɵelementStart(5, "span", 192);
|
|
584
|
+
i0.ɵɵtext(6);
|
|
585
|
+
i0.ɵɵelementEnd()();
|
|
586
|
+
i0.ɵɵelementStart(7, "div", 193);
|
|
587
|
+
i0.ɵɵtemplate(8, TestRunFormComponentExtended_div_115_div_2_div_8_Template, 11, 5, "div", 194);
|
|
362
588
|
i0.ɵɵelementEnd()();
|
|
363
589
|
} if (rf & 2) {
|
|
364
590
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
365
|
-
i0.ɵɵadvance(
|
|
366
|
-
i0.ɵɵ
|
|
591
|
+
i0.ɵɵadvance(6);
|
|
592
|
+
i0.ɵɵtextInterpolate(ctx_r1.aiAgentRuns.length);
|
|
367
593
|
i0.ɵɵadvance(2);
|
|
368
594
|
i0.ɵɵproperty("ngForOf", ctx_r1.aiAgentRuns);
|
|
369
595
|
} }
|
|
370
|
-
function
|
|
371
|
-
i0.ɵɵelementStart(0, "span");
|
|
372
|
-
i0.ɵɵ
|
|
596
|
+
function TestRunFormComponentExtended_div_115_div_3_div_8_span_7_Template(rf, ctx) { if (rf & 1) {
|
|
597
|
+
i0.ɵɵelementStart(0, "span", 203);
|
|
598
|
+
i0.ɵɵelement(1, "i", 37);
|
|
599
|
+
i0.ɵɵtext(2);
|
|
600
|
+
i0.ɵɵpipe(3, "number");
|
|
373
601
|
i0.ɵɵelementEnd();
|
|
374
602
|
} if (rf & 2) {
|
|
375
|
-
const
|
|
376
|
-
i0.ɵɵadvance();
|
|
377
|
-
i0.ɵɵtextInterpolate1("
|
|
603
|
+
const run_r18 = i0.ɵɵnextContext().$implicit;
|
|
604
|
+
i0.ɵɵadvance(2);
|
|
605
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind2(3, 1, run_r18.TotalCost, "1.4-4"), " ");
|
|
378
606
|
} }
|
|
379
|
-
function
|
|
380
|
-
const
|
|
381
|
-
i0.ɵɵelementStart(0, "div",
|
|
382
|
-
i0.ɵɵlistener("click", function
|
|
383
|
-
i0.ɵɵelementStart(1, "div",
|
|
384
|
-
i0.ɵɵelement(2, "i",
|
|
607
|
+
function TestRunFormComponentExtended_div_115_div_3_div_8_Template(rf, ctx) { if (rf & 1) {
|
|
608
|
+
const _r17 = i0.ɵɵgetCurrentView();
|
|
609
|
+
i0.ɵɵelementStart(0, "div", 195);
|
|
610
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_115_div_3_div_8_Template_div_click_0_listener() { const run_r18 = i0.ɵɵrestoreView(_r17).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openAIPromptRun(run_r18.ID)); });
|
|
611
|
+
i0.ɵɵelementStart(1, "div", 205);
|
|
612
|
+
i0.ɵɵelement(2, "i", 204);
|
|
385
613
|
i0.ɵɵelementEnd();
|
|
386
|
-
i0.ɵɵelementStart(3, "div",
|
|
614
|
+
i0.ɵɵelementStart(3, "div", 197)(4, "div", 198);
|
|
387
615
|
i0.ɵɵtext(5);
|
|
388
616
|
i0.ɵɵelementEnd();
|
|
389
|
-
i0.ɵɵelementStart(6, "div",
|
|
390
|
-
i0.ɵɵtemplate(7,
|
|
617
|
+
i0.ɵɵelementStart(6, "div", 199);
|
|
618
|
+
i0.ɵɵtemplate(7, TestRunFormComponentExtended_div_115_div_3_div_8_span_7_Template, 4, 4, "span", 201);
|
|
391
619
|
i0.ɵɵelementEnd()();
|
|
392
|
-
i0.ɵɵelement(8, "i",
|
|
620
|
+
i0.ɵɵelement(8, "i", 202);
|
|
393
621
|
i0.ɵɵelementEnd();
|
|
394
622
|
} if (rf & 2) {
|
|
395
|
-
const
|
|
623
|
+
const run_r18 = ctx.$implicit;
|
|
396
624
|
i0.ɵɵadvance(5);
|
|
397
|
-
i0.ɵɵtextInterpolate(
|
|
625
|
+
i0.ɵɵtextInterpolate(run_r18.Prompt || run_r18.Model);
|
|
398
626
|
i0.ɵɵadvance(2);
|
|
399
|
-
i0.ɵɵproperty("ngIf",
|
|
627
|
+
i0.ɵɵproperty("ngIf", run_r18.TotalCost);
|
|
400
628
|
} }
|
|
401
|
-
function
|
|
402
|
-
i0.ɵɵelementStart(0, "div",
|
|
403
|
-
i0.ɵɵ
|
|
629
|
+
function TestRunFormComponentExtended_div_115_div_3_Template(rf, ctx) { if (rf & 1) {
|
|
630
|
+
i0.ɵɵelementStart(0, "div", 191)(1, "div", 128)(2, "h3");
|
|
631
|
+
i0.ɵɵelement(3, "i", 204);
|
|
632
|
+
i0.ɵɵtext(4, " AI Prompt Runs");
|
|
404
633
|
i0.ɵɵelementEnd();
|
|
405
|
-
i0.ɵɵelementStart(
|
|
406
|
-
i0.ɵɵ
|
|
634
|
+
i0.ɵɵelementStart(5, "span", 192);
|
|
635
|
+
i0.ɵɵtext(6);
|
|
636
|
+
i0.ɵɵelementEnd()();
|
|
637
|
+
i0.ɵɵelementStart(7, "div", 193);
|
|
638
|
+
i0.ɵɵtemplate(8, TestRunFormComponentExtended_div_115_div_3_div_8_Template, 9, 2, "div", 194);
|
|
407
639
|
i0.ɵɵelementEnd()();
|
|
408
640
|
} if (rf & 2) {
|
|
409
641
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
410
|
-
i0.ɵɵadvance(
|
|
411
|
-
i0.ɵɵ
|
|
642
|
+
i0.ɵɵadvance(6);
|
|
643
|
+
i0.ɵɵtextInterpolate(ctx_r1.aiPromptRuns.length);
|
|
412
644
|
i0.ɵɵadvance(2);
|
|
413
645
|
i0.ɵɵproperty("ngForOf", ctx_r1.aiPromptRuns);
|
|
414
646
|
} }
|
|
415
|
-
function
|
|
416
|
-
i0.ɵɵelementStart(0, "div",
|
|
417
|
-
i0.ɵɵelement(
|
|
418
|
-
i0.ɵɵ
|
|
419
|
-
i0.ɵɵ
|
|
647
|
+
function TestRunFormComponentExtended_div_115_div_4_Template(rf, ctx) { if (rf & 1) {
|
|
648
|
+
i0.ɵɵelementStart(0, "div", 206)(1, "div", 207);
|
|
649
|
+
i0.ɵɵelement(2, "i", 48);
|
|
650
|
+
i0.ɵɵelementEnd();
|
|
651
|
+
i0.ɵɵelementStart(3, "h3");
|
|
652
|
+
i0.ɵɵtext(4, "No AI Runs");
|
|
653
|
+
i0.ɵɵelementEnd();
|
|
654
|
+
i0.ɵɵelementStart(5, "p");
|
|
655
|
+
i0.ɵɵtext(6, "This test execution didn't involve any AI agent or prompt runs.");
|
|
420
656
|
i0.ɵɵelementEnd()();
|
|
421
657
|
} }
|
|
422
|
-
function
|
|
423
|
-
i0.ɵɵelementStart(0, "div",
|
|
424
|
-
i0.ɵɵtemplate(1,
|
|
658
|
+
function TestRunFormComponentExtended_div_115_Template(rf, ctx) { if (rf & 1) {
|
|
659
|
+
i0.ɵɵelementStart(0, "div", 179);
|
|
660
|
+
i0.ɵɵtemplate(1, TestRunFormComponentExtended_div_115_div_1_Template, 3, 2, "div", 180)(2, TestRunFormComponentExtended_div_115_div_2_Template, 9, 2, "div", 181)(3, TestRunFormComponentExtended_div_115_div_3_Template, 9, 2, "div", 181)(4, TestRunFormComponentExtended_div_115_div_4_Template, 7, 0, "div", 182);
|
|
425
661
|
i0.ɵɵelementEnd();
|
|
426
662
|
} if (rf & 2) {
|
|
427
663
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
664
|
+
i0.ɵɵproperty("@fadeIn", undefined);
|
|
665
|
+
i0.ɵɵadvance();
|
|
666
|
+
i0.ɵɵproperty("ngIf", ctx_r1.loadingAIRuns);
|
|
428
667
|
i0.ɵɵadvance();
|
|
429
|
-
i0.ɵɵproperty("ngIf", ctx_r1.aiAgentRuns.length > 0);
|
|
668
|
+
i0.ɵɵproperty("ngIf", !ctx_r1.loadingAIRuns && ctx_r1.aiAgentRuns.length > 0);
|
|
430
669
|
i0.ɵɵadvance();
|
|
431
|
-
i0.ɵɵproperty("ngIf", ctx_r1.aiPromptRuns.length > 0);
|
|
670
|
+
i0.ɵɵproperty("ngIf", !ctx_r1.loadingAIRuns && ctx_r1.aiPromptRuns.length > 0);
|
|
432
671
|
i0.ɵɵadvance();
|
|
433
672
|
i0.ɵɵproperty("ngIf", ctx_r1.aiRunsLoaded && ctx_r1.aiAgentRuns.length === 0 && ctx_r1.aiPromptRuns.length === 0);
|
|
434
673
|
} }
|
|
435
|
-
function
|
|
436
|
-
i0.ɵɵelementStart(0, "div",
|
|
437
|
-
i0.ɵɵ
|
|
438
|
-
i0.ɵɵ
|
|
674
|
+
function TestRunFormComponentExtended_div_116_div_1_div_2_Template(rf, ctx) { if (rf & 1) {
|
|
675
|
+
i0.ɵɵelementStart(0, "div", 186);
|
|
676
|
+
i0.ɵɵelement(1, "div", 210);
|
|
677
|
+
i0.ɵɵelementStart(2, "div", 188);
|
|
678
|
+
i0.ɵɵelement(3, "div", 189)(4, "div", 190)(5, "div", 211);
|
|
679
|
+
i0.ɵɵelementEnd()();
|
|
680
|
+
} }
|
|
681
|
+
function TestRunFormComponentExtended_div_116_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
682
|
+
i0.ɵɵelementStart(0, "div", 183)(1, "div", 184);
|
|
683
|
+
i0.ɵɵtemplate(2, TestRunFormComponentExtended_div_116_div_1_div_2_Template, 6, 0, "div", 185);
|
|
684
|
+
i0.ɵɵelementEnd()();
|
|
439
685
|
} if (rf & 2) {
|
|
440
|
-
|
|
441
|
-
i0.ɵɵ
|
|
442
|
-
i0.ɵɵtextInterpolate1(" Automated Result: ", feedback_r11.IsCorrect ? "Correct" : "Incorrect", " ");
|
|
686
|
+
i0.ɵɵadvance(2);
|
|
687
|
+
i0.ɵɵproperty("ngForOf", i0.ɵɵpureFunction0(1, _c1));
|
|
443
688
|
} }
|
|
444
|
-
function
|
|
445
|
-
i0.ɵɵ
|
|
446
|
-
i0.ɵɵtext(1);
|
|
447
|
-
i0.ɵɵelementEnd();
|
|
689
|
+
function TestRunFormComponentExtended_div_116_div_2_div_1_i_12_Template(rf, ctx) { if (rf & 1) {
|
|
690
|
+
i0.ɵɵelement(0, "i", 34);
|
|
448
691
|
} if (rf & 2) {
|
|
449
|
-
const
|
|
692
|
+
const s_r19 = ctx.$implicit;
|
|
693
|
+
const feedback_r20 = i0.ɵɵnextContext().$implicit;
|
|
694
|
+
i0.ɵɵclassProp("filled", s_r19 <= (feedback_r20.Rating || 0));
|
|
695
|
+
} }
|
|
696
|
+
function TestRunFormComponentExtended_div_116_div_2_div_1_div_15_Template(rf, ctx) { if (rf & 1) {
|
|
697
|
+
i0.ɵɵelementStart(0, "div", 227)(1, "span", 228);
|
|
698
|
+
i0.ɵɵelement(2, "i", 145);
|
|
699
|
+
i0.ɵɵtext(3);
|
|
700
|
+
i0.ɵɵelementEnd()();
|
|
701
|
+
} if (rf & 2) {
|
|
702
|
+
const feedback_r20 = i0.ɵɵnextContext().$implicit;
|
|
703
|
+
i0.ɵɵadvance();
|
|
704
|
+
i0.ɵɵclassProp("correct", feedback_r20.IsCorrect)("incorrect", !feedback_r20.IsCorrect);
|
|
450
705
|
i0.ɵɵadvance();
|
|
451
|
-
i0.ɵɵ
|
|
706
|
+
i0.ɵɵclassProp("fa-check", feedback_r20.IsCorrect)("fa-times", !feedback_r20.IsCorrect);
|
|
707
|
+
i0.ɵɵadvance();
|
|
708
|
+
i0.ɵɵtextInterpolate1(" ", feedback_r20.IsCorrect ? "Marked Correct" : "Marked Incorrect", " ");
|
|
709
|
+
} }
|
|
710
|
+
function TestRunFormComponentExtended_div_116_div_2_div_1_div_16_Template(rf, ctx) { if (rf & 1) {
|
|
711
|
+
i0.ɵɵelementStart(0, "div", 229)(1, "p");
|
|
712
|
+
i0.ɵɵtext(2);
|
|
713
|
+
i0.ɵɵelementEnd()();
|
|
714
|
+
} if (rf & 2) {
|
|
715
|
+
const feedback_r20 = i0.ɵɵnextContext().$implicit;
|
|
716
|
+
i0.ɵɵadvance(2);
|
|
717
|
+
i0.ɵɵtextInterpolate(feedback_r20.CorrectionSummary);
|
|
452
718
|
} }
|
|
453
|
-
function
|
|
454
|
-
i0.ɵɵelementStart(0, "div",
|
|
455
|
-
i0.ɵɵelement(
|
|
456
|
-
i0.ɵɵtext(4);
|
|
719
|
+
function TestRunFormComponentExtended_div_116_div_2_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
720
|
+
i0.ɵɵelementStart(0, "div", 214)(1, "div", 215)(2, "div", 216)(3, "div", 217);
|
|
721
|
+
i0.ɵɵelement(4, "i", 78);
|
|
457
722
|
i0.ɵɵelementEnd();
|
|
458
|
-
i0.ɵɵelementStart(5, "
|
|
723
|
+
i0.ɵɵelementStart(5, "span", 218);
|
|
459
724
|
i0.ɵɵtext(6);
|
|
460
|
-
i0.ɵɵpipe(7, "date");
|
|
461
725
|
i0.ɵɵelementEnd()();
|
|
462
|
-
i0.ɵɵelementStart(
|
|
463
|
-
i0.ɵɵtext(
|
|
464
|
-
i0.ɵɵelementEnd();
|
|
465
|
-
i0.ɵɵ
|
|
726
|
+
i0.ɵɵelementStart(7, "div", 219);
|
|
727
|
+
i0.ɵɵtext(8);
|
|
728
|
+
i0.ɵɵelementEnd()();
|
|
729
|
+
i0.ɵɵelementStart(9, "div", 220)(10, "div", 221)(11, "div", 222);
|
|
730
|
+
i0.ɵɵtemplate(12, TestRunFormComponentExtended_div_116_div_2_div_1_i_12_Template, 1, 2, "i", 223);
|
|
466
731
|
i0.ɵɵelementEnd();
|
|
732
|
+
i0.ɵɵelementStart(13, "span", 224);
|
|
733
|
+
i0.ɵɵtext(14);
|
|
734
|
+
i0.ɵɵelementEnd()();
|
|
735
|
+
i0.ɵɵtemplate(15, TestRunFormComponentExtended_div_116_div_2_div_1_div_15_Template, 4, 9, "div", 225)(16, TestRunFormComponentExtended_div_116_div_2_div_1_div_16_Template, 3, 1, "div", 226);
|
|
736
|
+
i0.ɵɵelementEnd()();
|
|
467
737
|
} if (rf & 2) {
|
|
468
|
-
const
|
|
738
|
+
const feedback_r20 = ctx.$implicit;
|
|
739
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
740
|
+
i0.ɵɵadvance(6);
|
|
741
|
+
i0.ɵɵtextInterpolate(feedback_r20.ReviewerUser);
|
|
742
|
+
i0.ɵɵadvance(2);
|
|
743
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.getRelativeTime(feedback_r20.__mj_CreatedAt), " ");
|
|
469
744
|
i0.ɵɵadvance(4);
|
|
470
|
-
i0.ɵɵ
|
|
745
|
+
i0.ɵɵproperty("ngForOf", i0.ɵɵpureFunction0(6, _c2));
|
|
471
746
|
i0.ɵɵadvance(2);
|
|
472
|
-
i0.ɵɵtextInterpolate1("
|
|
473
|
-
i0.ɵɵadvance(3);
|
|
474
|
-
i0.ɵɵtextInterpolate1(" Rating: ", feedback_r11.Rating, "/10 ");
|
|
747
|
+
i0.ɵɵtextInterpolate1("", feedback_r20.Rating, "/10");
|
|
475
748
|
i0.ɵɵadvance();
|
|
476
|
-
i0.ɵɵproperty("ngIf",
|
|
749
|
+
i0.ɵɵproperty("ngIf", feedback_r20.IsCorrect !== null);
|
|
477
750
|
i0.ɵɵadvance();
|
|
478
|
-
i0.ɵɵproperty("ngIf",
|
|
751
|
+
i0.ɵɵproperty("ngIf", feedback_r20.CorrectionSummary);
|
|
479
752
|
} }
|
|
480
|
-
function
|
|
481
|
-
i0.ɵɵelementStart(0, "div",
|
|
482
|
-
i0.ɵɵtemplate(1,
|
|
753
|
+
function TestRunFormComponentExtended_div_116_div_2_Template(rf, ctx) { if (rf & 1) {
|
|
754
|
+
i0.ɵɵelementStart(0, "div", 212);
|
|
755
|
+
i0.ɵɵtemplate(1, TestRunFormComponentExtended_div_116_div_2_div_1_Template, 17, 7, "div", 213);
|
|
483
756
|
i0.ɵɵelementEnd();
|
|
484
757
|
} if (rf & 2) {
|
|
485
758
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
486
759
|
i0.ɵɵadvance();
|
|
487
760
|
i0.ɵɵproperty("ngForOf", ctx_r1.feedbacks);
|
|
488
761
|
} }
|
|
489
|
-
function
|
|
490
|
-
i0.ɵɵelementStart(0, "div",
|
|
491
|
-
i0.ɵɵelement(
|
|
492
|
-
i0.ɵɵ
|
|
493
|
-
i0.ɵɵ
|
|
762
|
+
function TestRunFormComponentExtended_div_116_div_3_Template(rf, ctx) { if (rf & 1) {
|
|
763
|
+
i0.ɵɵelementStart(0, "div", 206)(1, "div", 207);
|
|
764
|
+
i0.ɵɵelement(2, "i", 51);
|
|
765
|
+
i0.ɵɵelementEnd();
|
|
766
|
+
i0.ɵɵelementStart(3, "h3");
|
|
767
|
+
i0.ɵɵtext(4, "No Feedback Yet");
|
|
768
|
+
i0.ɵɵelementEnd();
|
|
769
|
+
i0.ɵɵelementStart(5, "p");
|
|
770
|
+
i0.ɵɵtext(6, "No one has reviewed this test run yet. Be the first to provide feedback!");
|
|
494
771
|
i0.ɵɵelementEnd()();
|
|
495
772
|
} }
|
|
496
|
-
function
|
|
497
|
-
i0.ɵɵelementStart(0, "div",
|
|
498
|
-
i0.ɵɵtemplate(1,
|
|
773
|
+
function TestRunFormComponentExtended_div_116_Template(rf, ctx) { if (rf & 1) {
|
|
774
|
+
i0.ɵɵelementStart(0, "div", 208);
|
|
775
|
+
i0.ɵɵtemplate(1, TestRunFormComponentExtended_div_116_div_1_Template, 3, 2, "div", 180)(2, TestRunFormComponentExtended_div_116_div_2_Template, 2, 1, "div", 209)(3, TestRunFormComponentExtended_div_116_div_3_Template, 7, 0, "div", 182);
|
|
499
776
|
i0.ɵɵelementEnd();
|
|
500
777
|
} if (rf & 2) {
|
|
501
778
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
779
|
+
i0.ɵɵproperty("@fadeIn", undefined);
|
|
780
|
+
i0.ɵɵadvance();
|
|
781
|
+
i0.ɵɵproperty("ngIf", ctx_r1.loadingFeedback);
|
|
502
782
|
i0.ɵɵadvance();
|
|
503
|
-
i0.ɵɵproperty("ngIf", ctx_r1.feedbacks.length > 0);
|
|
783
|
+
i0.ɵɵproperty("ngIf", !ctx_r1.loadingFeedback && ctx_r1.feedbacks.length > 0);
|
|
504
784
|
i0.ɵɵadvance();
|
|
505
785
|
i0.ɵɵproperty("ngIf", ctx_r1.feedbackLoaded && ctx_r1.feedbacks.length === 0);
|
|
506
786
|
} }
|
|
787
|
+
function TestRunFormComponentExtended_div_117_Template(rf, ctx) { if (rf & 1) {
|
|
788
|
+
i0.ɵɵelementStart(0, "div", 230);
|
|
789
|
+
i0.ɵɵelement(1, "mj-execution-context", 231);
|
|
790
|
+
i0.ɵɵelementEnd();
|
|
791
|
+
} if (rf & 2) {
|
|
792
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
793
|
+
i0.ɵɵproperty("@fadeIn", undefined);
|
|
794
|
+
i0.ɵɵadvance();
|
|
795
|
+
i0.ɵɵproperty("machineName", ctx_r1.record.MachineName)("machineId", ctx_r1.record.MachineID)("runByUserName", ctx_r1.record.RunByUserName)("runByUserEmail", ctx_r1.record.RunByUserEmail)("runContextDetailsJson", ctx_r1.record.RunContextDetails);
|
|
796
|
+
} }
|
|
797
|
+
function TestRunFormComponentExtended_div_118_Template(rf, ctx) { if (rf & 1) {
|
|
798
|
+
const _r21 = i0.ɵɵgetCurrentView();
|
|
799
|
+
i0.ɵɵelementStart(0, "div", 232)(1, "div", 233)(2, "div", 234);
|
|
800
|
+
i0.ɵɵelement(3, "i", 115);
|
|
801
|
+
i0.ɵɵelementStart(4, "h3");
|
|
802
|
+
i0.ɵɵtext(5, "Execution Log");
|
|
803
|
+
i0.ɵɵelementEnd()();
|
|
804
|
+
i0.ɵɵelementStart(6, "div", 235)(7, "button", 236);
|
|
805
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_div_118_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.copyLogToClipboard()); });
|
|
806
|
+
i0.ɵɵelement(8, "i", 237);
|
|
807
|
+
i0.ɵɵelementStart(9, "span", 22);
|
|
808
|
+
i0.ɵɵtext(10, "Copy");
|
|
809
|
+
i0.ɵɵelementEnd()()()();
|
|
810
|
+
i0.ɵɵelementStart(11, "div", 238);
|
|
811
|
+
i0.ɵɵelement(12, "mj-code-editor", 175);
|
|
812
|
+
i0.ɵɵelementEnd()();
|
|
813
|
+
} if (rf & 2) {
|
|
814
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
815
|
+
i0.ɵɵproperty("@fadeIn", undefined);
|
|
816
|
+
i0.ɵɵadvance(12);
|
|
817
|
+
i0.ɵɵproperty("value", ctx_r1.record.Log || "")("readonly", true)("toolbar", ctx_r1.jsonToolbar)("lineWrapping", true);
|
|
818
|
+
} }
|
|
507
819
|
let TestRunFormComponentExtended = class TestRunFormComponentExtended extends TestRunFormComponent {
|
|
508
|
-
constructor(elementRef, sharedService, router, route, cdr) {
|
|
820
|
+
constructor(elementRef, sharedService, router, route, cdr, testingDialogService, navigationService, appManager, viewContainerRef) {
|
|
509
821
|
super(elementRef, sharedService, router, route, cdr);
|
|
510
822
|
this.router = router;
|
|
511
823
|
this.cdr = cdr;
|
|
824
|
+
this.testingDialogService = testingDialogService;
|
|
825
|
+
this.navigationService = navigationService;
|
|
826
|
+
this.appManager = appManager;
|
|
827
|
+
this.viewContainerRef = viewContainerRef;
|
|
512
828
|
this.destroy$ = new Subject();
|
|
513
829
|
// UI state
|
|
514
830
|
this.activeTab = 'overview';
|
|
515
831
|
this.loading = false;
|
|
832
|
+
this.loadingAIRuns = false;
|
|
833
|
+
this.loadingFeedback = false;
|
|
516
834
|
this.error = null;
|
|
517
835
|
this.aiRunsLoaded = false;
|
|
518
836
|
this.feedbackLoaded = false;
|
|
837
|
+
this.isRefreshing = false;
|
|
838
|
+
this.autoRefreshEnabled = false;
|
|
519
839
|
// Related entities
|
|
520
840
|
this.test = null;
|
|
521
841
|
this.testSuiteRun = null;
|
|
@@ -526,20 +846,153 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
526
846
|
this.parsedData = {};
|
|
527
847
|
// Active comparison view
|
|
528
848
|
this.comparisonView = 'input';
|
|
849
|
+
// Code editor configuration
|
|
850
|
+
this.jsonToolbar = createCopyOnlyToolbar();
|
|
851
|
+
// Keyboard shortcuts active
|
|
852
|
+
this.keyboardShortcutsEnabled = true;
|
|
853
|
+
// Tags management
|
|
854
|
+
this.tags = [];
|
|
855
|
+
this.newTag = '';
|
|
856
|
+
this.editingTags = false;
|
|
857
|
+
this.savingTags = false;
|
|
858
|
+
this.originalTags = [];
|
|
529
859
|
}
|
|
530
860
|
async ngOnInit() {
|
|
531
861
|
await super.ngOnInit();
|
|
532
862
|
if (this.record && this.record.ID) {
|
|
533
863
|
await this.loadRelatedData();
|
|
534
864
|
this.parseJsonFields();
|
|
865
|
+
this.loadTags();
|
|
866
|
+
// Auto-refresh for running tests
|
|
867
|
+
if (this.record.Status === 'Running' || this.record.Status === 'Pending') {
|
|
868
|
+
this.startAutoRefresh();
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
loadTags() {
|
|
873
|
+
this.tags = TagsHelper.parseTags(this.record.Tags);
|
|
874
|
+
this.originalTags = [...this.tags];
|
|
875
|
+
}
|
|
876
|
+
startEditingTags() {
|
|
877
|
+
this.originalTags = [...this.tags];
|
|
878
|
+
this.editingTags = true;
|
|
879
|
+
this.cdr.markForCheck();
|
|
880
|
+
}
|
|
881
|
+
cancelEditingTags() {
|
|
882
|
+
this.tags = [...this.originalTags];
|
|
883
|
+
this.newTag = '';
|
|
884
|
+
this.editingTags = false;
|
|
885
|
+
this.cdr.markForCheck();
|
|
886
|
+
}
|
|
887
|
+
addTag() {
|
|
888
|
+
const tag = this.newTag.trim();
|
|
889
|
+
if (tag && !this.tags.includes(tag)) {
|
|
890
|
+
this.tags = [...this.tags, tag];
|
|
891
|
+
this.newTag = '';
|
|
892
|
+
this.cdr.markForCheck();
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
removeTag(tag) {
|
|
896
|
+
this.tags = this.tags.filter(t => t !== tag);
|
|
897
|
+
this.cdr.markForCheck();
|
|
898
|
+
}
|
|
899
|
+
async saveTags() {
|
|
900
|
+
// Auto-add any pending tag in the input before saving
|
|
901
|
+
const pendingTag = this.newTag.trim();
|
|
902
|
+
if (pendingTag && !this.tags.includes(pendingTag)) {
|
|
903
|
+
this.tags = [...this.tags, pendingTag];
|
|
904
|
+
this.newTag = '';
|
|
905
|
+
}
|
|
906
|
+
this.savingTags = true;
|
|
907
|
+
this.cdr.markForCheck();
|
|
908
|
+
try {
|
|
909
|
+
this.record.Tags = TagsHelper.toJson(this.tags);
|
|
910
|
+
const result = await this.record.Save();
|
|
911
|
+
if (result) {
|
|
912
|
+
this.originalTags = [...this.tags];
|
|
913
|
+
this.editingTags = false;
|
|
914
|
+
SharedService.Instance.CreateSimpleNotification('Tags saved', 'success', 2000);
|
|
915
|
+
}
|
|
916
|
+
else {
|
|
917
|
+
SharedService.Instance.CreateSimpleNotification('Failed to save tags', 'error', 3000);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
catch {
|
|
921
|
+
SharedService.Instance.CreateSimpleNotification('Failed to save tags', 'error', 3000);
|
|
922
|
+
}
|
|
923
|
+
finally {
|
|
924
|
+
this.savingTags = false;
|
|
925
|
+
this.cdr.markForCheck();
|
|
535
926
|
}
|
|
536
927
|
}
|
|
537
928
|
ngOnDestroy() {
|
|
538
929
|
this.destroy$.next();
|
|
539
930
|
this.destroy$.complete();
|
|
540
931
|
}
|
|
932
|
+
// Keyboard shortcuts
|
|
933
|
+
handleKeyboardShortcut(event) {
|
|
934
|
+
if (!this.keyboardShortcutsEnabled)
|
|
935
|
+
return;
|
|
936
|
+
// Cmd/Ctrl + R: Refresh
|
|
937
|
+
if ((event.metaKey || event.ctrlKey) && event.key === 'r' && !event.shiftKey) {
|
|
938
|
+
event.preventDefault();
|
|
939
|
+
this.refresh();
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
// Cmd/Ctrl + Shift + R: Re-run test
|
|
943
|
+
if ((event.metaKey || event.ctrlKey) && event.shiftKey && event.key === 'r') {
|
|
944
|
+
event.preventDefault();
|
|
945
|
+
this.reRunTest();
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
// Number keys for tabs (1-5)
|
|
949
|
+
if (!event.metaKey && !event.ctrlKey && !event.altKey) {
|
|
950
|
+
switch (event.key) {
|
|
951
|
+
case '1':
|
|
952
|
+
this.changeTab('overview');
|
|
953
|
+
break;
|
|
954
|
+
case '2':
|
|
955
|
+
this.changeTab('details');
|
|
956
|
+
break;
|
|
957
|
+
case '3':
|
|
958
|
+
this.changeTab('ai-runs');
|
|
959
|
+
break;
|
|
960
|
+
case '4':
|
|
961
|
+
this.changeTab('feedback');
|
|
962
|
+
break;
|
|
963
|
+
case '5':
|
|
964
|
+
if (this.record.Log)
|
|
965
|
+
this.changeTab('log');
|
|
966
|
+
break;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
startAutoRefresh() {
|
|
971
|
+
this.autoRefreshEnabled = true;
|
|
972
|
+
interval(5000)
|
|
973
|
+
.pipe(takeUntil(this.destroy$))
|
|
974
|
+
.subscribe(() => {
|
|
975
|
+
if (this.autoRefreshEnabled && (this.record.Status === 'Running' || this.record.Status === 'Pending')) {
|
|
976
|
+
this.silentRefresh();
|
|
977
|
+
}
|
|
978
|
+
else {
|
|
979
|
+
this.autoRefreshEnabled = false;
|
|
980
|
+
}
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
async silentRefresh() {
|
|
984
|
+
try {
|
|
985
|
+
await this.record.Load(this.record.ID);
|
|
986
|
+
this.parseJsonFields();
|
|
987
|
+
this.cdr.markForCheck();
|
|
988
|
+
}
|
|
989
|
+
catch {
|
|
990
|
+
// Silently fail on auto-refresh
|
|
991
|
+
}
|
|
992
|
+
}
|
|
541
993
|
async loadRelatedData() {
|
|
542
994
|
this.loading = true;
|
|
995
|
+
this.error = null;
|
|
543
996
|
try {
|
|
544
997
|
// Load test
|
|
545
998
|
if (this.record.TestID) {
|
|
@@ -561,16 +1014,22 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
561
1014
|
}
|
|
562
1015
|
catch (error) {
|
|
563
1016
|
console.error('Error loading related data:', error);
|
|
564
|
-
this.error = 'Failed to load related data';
|
|
1017
|
+
this.error = 'Failed to load related data. Click to retry.';
|
|
565
1018
|
}
|
|
566
1019
|
finally {
|
|
567
1020
|
this.loading = false;
|
|
568
1021
|
this.cdr.markForCheck();
|
|
569
1022
|
}
|
|
570
1023
|
}
|
|
1024
|
+
async retryLoad() {
|
|
1025
|
+
this.error = null;
|
|
1026
|
+
await this.loadRelatedData();
|
|
1027
|
+
}
|
|
571
1028
|
async loadAIRuns() {
|
|
572
1029
|
if (this.aiRunsLoaded)
|
|
573
1030
|
return;
|
|
1031
|
+
this.loadingAIRuns = true;
|
|
1032
|
+
this.cdr.markForCheck();
|
|
574
1033
|
try {
|
|
575
1034
|
const rv = new RunView();
|
|
576
1035
|
const [agentRuns, promptRuns] = await rv.RunViews([
|
|
@@ -583,7 +1042,7 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
583
1042
|
{
|
|
584
1043
|
EntityName: 'MJ: AI Prompt Runs',
|
|
585
1044
|
ExtraFilter: `TestRunID='${this.record.ID}'`,
|
|
586
|
-
OrderBy: '
|
|
1045
|
+
OrderBy: 'RunAt',
|
|
587
1046
|
ResultType: 'entity_object'
|
|
588
1047
|
}
|
|
589
1048
|
]);
|
|
@@ -594,15 +1053,21 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
594
1053
|
this.aiPromptRuns = promptRuns.Results || [];
|
|
595
1054
|
}
|
|
596
1055
|
this.aiRunsLoaded = true;
|
|
597
|
-
this.cdr.markForCheck();
|
|
598
1056
|
}
|
|
599
1057
|
catch (error) {
|
|
600
1058
|
console.error('Error loading AI runs:', error);
|
|
1059
|
+
SharedService.Instance.CreateSimpleNotification('Failed to load AI runs', 'error', 3000);
|
|
1060
|
+
}
|
|
1061
|
+
finally {
|
|
1062
|
+
this.loadingAIRuns = false;
|
|
1063
|
+
this.cdr.markForCheck();
|
|
601
1064
|
}
|
|
602
1065
|
}
|
|
603
1066
|
async loadFeedback() {
|
|
604
1067
|
if (this.feedbackLoaded)
|
|
605
1068
|
return;
|
|
1069
|
+
this.loadingFeedback = true;
|
|
1070
|
+
this.cdr.markForCheck();
|
|
606
1071
|
try {
|
|
607
1072
|
const rv = new RunView();
|
|
608
1073
|
const result = await rv.RunView({
|
|
@@ -615,10 +1080,14 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
615
1080
|
this.feedbacks = result.Results || [];
|
|
616
1081
|
}
|
|
617
1082
|
this.feedbackLoaded = true;
|
|
618
|
-
this.cdr.markForCheck();
|
|
619
1083
|
}
|
|
620
1084
|
catch (error) {
|
|
621
1085
|
console.error('Error loading feedback:', error);
|
|
1086
|
+
SharedService.Instance.CreateSimpleNotification('Failed to load feedback', 'error', 3000);
|
|
1087
|
+
}
|
|
1088
|
+
finally {
|
|
1089
|
+
this.loadingFeedback = false;
|
|
1090
|
+
this.cdr.markForCheck();
|
|
622
1091
|
}
|
|
623
1092
|
}
|
|
624
1093
|
parseJsonFields() {
|
|
@@ -657,26 +1126,31 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
657
1126
|
}
|
|
658
1127
|
getStatusColor() {
|
|
659
1128
|
switch (this.record.Status) {
|
|
660
|
-
case 'Passed': return '#
|
|
661
|
-
case 'Failed': return '#
|
|
662
|
-
case 'Error': return '#
|
|
663
|
-
case '
|
|
664
|
-
case '
|
|
665
|
-
case '
|
|
666
|
-
|
|
1129
|
+
case 'Passed': return '#10b981';
|
|
1130
|
+
case 'Failed': return '#ef4444';
|
|
1131
|
+
case 'Error': return '#f59e0b';
|
|
1132
|
+
case 'Timeout': return '#f97316';
|
|
1133
|
+
case 'Running': return '#3b82f6';
|
|
1134
|
+
case 'Pending': return '#8b5cf6';
|
|
1135
|
+
case 'Skipped': return '#6b7280';
|
|
1136
|
+
default: return '#9ca3af';
|
|
667
1137
|
}
|
|
668
1138
|
}
|
|
669
1139
|
getStatusIcon() {
|
|
670
1140
|
switch (this.record.Status) {
|
|
671
1141
|
case 'Passed': return 'fa-check-circle';
|
|
672
1142
|
case 'Failed': return 'fa-times-circle';
|
|
673
|
-
case 'Error': return 'fa-exclamation-
|
|
674
|
-
case '
|
|
675
|
-
case '
|
|
1143
|
+
case 'Error': return 'fa-exclamation-triangle';
|
|
1144
|
+
case 'Timeout': return 'fa-stopwatch';
|
|
1145
|
+
case 'Running': return 'fa-circle-notch fa-spin';
|
|
1146
|
+
case 'Pending': return 'fa-hourglass-half';
|
|
676
1147
|
case 'Skipped': return 'fa-forward';
|
|
677
1148
|
default: return 'fa-question-circle';
|
|
678
1149
|
}
|
|
679
1150
|
}
|
|
1151
|
+
getStatusClass() {
|
|
1152
|
+
return `status-${this.record.Status?.toLowerCase() || 'unknown'}`;
|
|
1153
|
+
}
|
|
680
1154
|
calculateDuration() {
|
|
681
1155
|
if (!this.record.DurationSeconds)
|
|
682
1156
|
return 'N/A';
|
|
@@ -702,11 +1176,29 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
702
1176
|
return 'N/A';
|
|
703
1177
|
return `$${cost.toFixed(6)}`;
|
|
704
1178
|
}
|
|
1179
|
+
getScorePercentage() {
|
|
1180
|
+
if (this.record.Score === null || this.record.Score === undefined)
|
|
1181
|
+
return 0;
|
|
1182
|
+
return Math.round(this.record.Score * 100);
|
|
1183
|
+
}
|
|
1184
|
+
getPassRatePercentage() {
|
|
1185
|
+
const total = this.record.TotalChecks || 0;
|
|
1186
|
+
const passed = this.record.PassedChecks || 0;
|
|
1187
|
+
if (total === 0)
|
|
1188
|
+
return 0;
|
|
1189
|
+
return Math.round((passed / total) * 100);
|
|
1190
|
+
}
|
|
705
1191
|
openTest() {
|
|
706
1192
|
if (this.test) {
|
|
707
1193
|
SharedService.Instance.OpenEntityRecord('MJ: Tests', CompositeKey.FromID(this.test.ID));
|
|
708
1194
|
}
|
|
709
1195
|
}
|
|
1196
|
+
navigateToTestingDashboard() {
|
|
1197
|
+
const testingApp = this.appManager.GetAppByName('Testing');
|
|
1198
|
+
if (testingApp) {
|
|
1199
|
+
this.navigationService.SwitchToApp(testingApp.ID);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
710
1202
|
openTestSuiteRun() {
|
|
711
1203
|
if (this.testSuiteRun) {
|
|
712
1204
|
SharedService.Instance.OpenEntityRecord('MJ: Test Suite Runs', CompositeKey.FromID(this.testSuiteRun.ID));
|
|
@@ -719,25 +1211,62 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
719
1211
|
SharedService.Instance.OpenEntityRecord('MJ: AI Prompt Runs', CompositeKey.FromID(runId));
|
|
720
1212
|
}
|
|
721
1213
|
async reRunTest() {
|
|
722
|
-
|
|
723
|
-
|
|
1214
|
+
if (!this.record.TestID) {
|
|
1215
|
+
SharedService.Instance.CreateSimpleNotification('Cannot re-run: Test ID not available', 'error', 3000);
|
|
1216
|
+
return;
|
|
1217
|
+
}
|
|
1218
|
+
this.testingDialogService.OpenTestDialog(this.record.TestID, this.viewContainerRef);
|
|
724
1219
|
}
|
|
725
1220
|
async refresh() {
|
|
726
|
-
|
|
1221
|
+
this.isRefreshing = true;
|
|
727
1222
|
this.cdr.markForCheck();
|
|
1223
|
+
try {
|
|
1224
|
+
await this.record.Load(this.record.ID);
|
|
1225
|
+
await this.loadRelatedData();
|
|
1226
|
+
this.parseJsonFields();
|
|
1227
|
+
// Reset lazy-loaded data to force reload
|
|
1228
|
+
this.aiRunsLoaded = false;
|
|
1229
|
+
this.feedbackLoaded = false;
|
|
1230
|
+
this.aiAgentRuns = [];
|
|
1231
|
+
this.aiPromptRuns = [];
|
|
1232
|
+
this.feedbacks = [];
|
|
1233
|
+
// Reload current tab data if needed
|
|
1234
|
+
if (this.activeTab === 'ai-runs') {
|
|
1235
|
+
await this.loadAIRuns();
|
|
1236
|
+
}
|
|
1237
|
+
else if (this.activeTab === 'feedback') {
|
|
1238
|
+
await this.loadFeedback();
|
|
1239
|
+
}
|
|
1240
|
+
SharedService.Instance.CreateSimpleNotification('Refreshed successfully', 'success', 2000);
|
|
1241
|
+
}
|
|
1242
|
+
catch {
|
|
1243
|
+
SharedService.Instance.CreateSimpleNotification('Failed to refresh', 'error', 3000);
|
|
1244
|
+
}
|
|
1245
|
+
finally {
|
|
1246
|
+
this.isRefreshing = false;
|
|
1247
|
+
this.cdr.markForCheck();
|
|
1248
|
+
}
|
|
728
1249
|
}
|
|
729
1250
|
getComparisonData() {
|
|
1251
|
+
let data;
|
|
730
1252
|
switch (this.comparisonView) {
|
|
731
|
-
case 'input':
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
1253
|
+
case 'input':
|
|
1254
|
+
data = this.parsedData.input;
|
|
1255
|
+
break;
|
|
1256
|
+
case 'expected':
|
|
1257
|
+
data = this.parsedData.expected;
|
|
1258
|
+
break;
|
|
1259
|
+
case 'actual':
|
|
1260
|
+
data = this.parsedData.actual;
|
|
1261
|
+
break;
|
|
735
1262
|
}
|
|
1263
|
+
return data ? JSON.stringify(data, null, 2) : '// No data available';
|
|
736
1264
|
}
|
|
737
1265
|
getCheckResults() {
|
|
738
|
-
|
|
1266
|
+
const details = this.parsedData.resultDetails;
|
|
1267
|
+
if (!details?.checkResults)
|
|
739
1268
|
return [];
|
|
740
|
-
return
|
|
1269
|
+
return details.checkResults;
|
|
741
1270
|
}
|
|
742
1271
|
getPassRate() {
|
|
743
1272
|
const total = this.record.TotalChecks || 0;
|
|
@@ -746,155 +1275,272 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
746
1275
|
return 0;
|
|
747
1276
|
return (passed / total) * 100;
|
|
748
1277
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
1278
|
+
async copyLogToClipboard() {
|
|
1279
|
+
if (this.record.Log) {
|
|
1280
|
+
try {
|
|
1281
|
+
await navigator.clipboard.writeText(this.record.Log);
|
|
1282
|
+
SharedService.Instance.CreateSimpleNotification('Log copied to clipboard', 'success', 2000);
|
|
1283
|
+
}
|
|
1284
|
+
catch {
|
|
1285
|
+
SharedService.Instance.CreateSimpleNotification('Failed to copy log', 'error', 2000);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
getFormattedResultDetails() {
|
|
1290
|
+
return this.parsedData.resultDetails
|
|
1291
|
+
? JSON.stringify(this.parsedData.resultDetails, null, 2)
|
|
1292
|
+
: '// No result details available';
|
|
1293
|
+
}
|
|
1294
|
+
// Helper for relative time display
|
|
1295
|
+
getRelativeTime(date) {
|
|
1296
|
+
if (!date)
|
|
1297
|
+
return 'N/A';
|
|
1298
|
+
const d = new Date(date);
|
|
1299
|
+
const now = new Date();
|
|
1300
|
+
const diffMs = now.getTime() - d.getTime();
|
|
1301
|
+
const diffMins = Math.floor(diffMs / 60000);
|
|
1302
|
+
const diffHours = Math.floor(diffMs / 3600000);
|
|
1303
|
+
const diffDays = Math.floor(diffMs / 86400000);
|
|
1304
|
+
if (diffMins < 1)
|
|
1305
|
+
return 'Just now';
|
|
1306
|
+
if (diffMins < 60)
|
|
1307
|
+
return `${diffMins}m ago`;
|
|
1308
|
+
if (diffHours < 24)
|
|
1309
|
+
return `${diffHours}h ago`;
|
|
1310
|
+
if (diffDays < 7)
|
|
1311
|
+
return `${diffDays}d ago`;
|
|
1312
|
+
return d.toLocaleDateString();
|
|
1313
|
+
}
|
|
1314
|
+
static { this.ɵfac = function TestRunFormComponentExtended_Factory(t) { return new (t || TestRunFormComponentExtended)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i1.SharedService), i0.ɵɵdirectiveInject(i2.Router), i0.ɵɵdirectiveInject(i2.ActivatedRoute), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i3.TestingDialogService), i0.ɵɵdirectiveInject(i1.NavigationService), i0.ɵɵdirectiveInject(i4.ApplicationManager), i0.ɵɵdirectiveInject(i0.ViewContainerRef)); }; }
|
|
1315
|
+
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestRunFormComponentExtended, selectors: [["mj-test-run-form"]], hostBindings: function TestRunFormComponentExtended_HostBindings(rf, ctx) { if (rf & 1) {
|
|
1316
|
+
i0.ɵɵlistener("keydown", function TestRunFormComponentExtended_keydown_HostBindingHandler($event) { return ctx.handleKeyboardShortcut($event); }, false, i0.ɵɵresolveDocument);
|
|
1317
|
+
} }, features: [i0.ɵɵInheritDefinitionFeature], decls: 137, vars: 59, consts: [[1, "test-run-form"], ["class", "error-banner", 3, "click", 4, "ngIf"], [1, "test-run-header"], ["aria-label", "Breadcrumb", 1, "breadcrumb"], ["href", "javascript:void(0)", 3, "click"], [1, "fas", "fa-vial"], [1, "breadcrumb-text"], [4, "ngIf"], [1, "current"], [1, "fas", "fa-chevron-right", "separator"], [1, "header-content"], [1, "header-left"], [1, "status-indicator"], [1, "fas", 3, "ngClass"], [1, "test-run-info"], [1, "run-id"], [1, "test-run-meta"], [1, "status-badge"], ["class", "meta-item", 4, "ngIf"], [1, "header-actions"], ["kendoButton", "", "title", "Re-run this test (Cmd+Shift+R)", 3, "click", "disabled"], [1, "fas", "fa-redo"], [1, "btn-text"], ["kendoButton", "", "title", "Refresh (Cmd+R)", 3, "click", "disabled"], [1, "fas", "fa-sync-alt"], [1, "metrics-bar"], [1, "metric-card"], [1, "metric-icon"], [1, "fas", "fa-clock"], [1, "metric-content"], [1, "metric-label"], [1, "metric-value"], [1, "metric-detail"], [1, "fas", "fa-stopwatch"], [1, "fas", "fa-star"], ["class", "metric-progress", 4, "ngIf"], [1, "fas", "fa-check-double"], [1, "fas", "fa-dollar-sign"], ["class", "secondary-info", 4, "ngIf"], ["class", "tags-bar", 4, "ngIf"], ["class", "tags-editor-panel", 4, "ngIf"], [1, "tabs-container"], ["role", "tablist", 1, "tabs"], ["role", "tab", "title", "Press 1", 1, "tab", 3, "click"], [1, "fas", "fa-chart-pie"], ["role", "tab", "title", "Press 2", 1, "tab", 3, "click"], [1, "fas", "fa-info-circle"], ["role", "tab", "title", "Press 3", 1, "tab", 3, "click"], [1, "fas", "fa-robot"], ["class", "tab-badge", 4, "ngIf"], ["role", "tab", "title", "Press 4", 1, "tab", 3, "click"], [1, "fas", "fa-comments"], ["role", "tab", "title", "Press 5", 1, "tab", 3, "click"], [1, "fas", "fa-microchip"], ["class", "tab", "role", "tab", "title", "Press 6", 3, "active", "click", 4, "ngIf"], [1, "tab-content"], ["class", "overview-tab", 4, "ngIf"], ["class", "details-tab", 4, "ngIf"], ["class", "ai-runs-tab", 4, "ngIf"], ["class", "feedback-tab", 4, "ngIf"], ["class", "execution-tab", 4, "ngIf"], ["class", "log-tab", 4, "ngIf"], ["title", "Keyboard Shortcuts", 1, "shortcuts-hint"], [1, "fas", "fa-keyboard"], [1, "shortcuts-popup"], [1, "error-banner", 3, "click"], [1, "fas", "fa-exclamation-triangle"], [1, "retry-btn"], [1, "fas", "fa-flask"], [1, "meta-item"], [1, "fas", "fa-sync-alt", "fa-spin"], [1, "metric-progress"], [1, "progress-bar"], [1, "secondary-info"], ["class", "info-chip", 4, "ngIf"], ["class", "info-chip clickable", 3, "click", 4, "ngIf"], [3, "entityName", "recordId", 4, "ngIf"], [1, "info-chip"], [1, "fas", "fa-user"], [1, "info-chip", "clickable", 3, "click"], [1, "fas", "fa-layer-group"], [3, "entityName", "recordId"], [1, "tags-bar"], [1, "tags-bar-content"], [1, "tags-bar-label"], [1, "fas", "fa-tags"], ["class", "tags-bar-chips", 4, "ngIf"], ["class", "tags-bar-empty", 4, "ngIf"], ["title", "Edit tags", 1, "tags-bar-edit", 3, "click"], [1, "fas", "fa-plus"], [1, "tags-bar-chips"], ["class", "tag-inline", 4, "ngFor", "ngForOf"], [1, "tag-inline"], [1, "tags-bar-empty"], [1, "tags-editor-panel"], [1, "tags-editor-header"], [1, "tags-editor-title"], [1, "tags-editor-body"], [1, "tags-editor-chips"], ["class", "tag-editable", 4, "ngFor", "ngForOf"], ["class", "tags-empty-hint", 4, "ngIf"], [1, "tags-editor-input"], ["type", "text", "placeholder", "Type a tag and press Enter...", 1, "tag-text-input", 3, "ngModelChange", "keyup.enter", "ngModel"], ["kendoButton", "", "fillMode", "flat", 3, "click", "disabled"], [1, "tags-editor-footer"], ["kendoButton", "", "themeColor", "primary", 3, "click", "disabled"], ["class", "fas fa-spinner fa-spin", 4, "ngIf"], ["kendoButton", "", "fillMode", "flat", 3, "click"], [1, "tag-editable"], ["title", "Remove tag", 1, "tag-remove-btn", 3, "click"], [1, "fas", "fa-times"], [1, "tags-empty-hint"], [1, "fas", "fa-spinner", "fa-spin"], [1, "tab-badge"], ["role", "tab", "title", "Press 6", 1, "tab", 3, "click"], [1, "fas", "fa-terminal"], [1, "overview-tab"], [1, "result-hero"], [1, "result-icon-wrapper"], [1, "result-icon"], ["class", "result-pulse", 4, "ngIf"], [1, "result-text"], [1, "result-details"], [1, "result-score"], [1, "result-divider"], [1, "result-checks"], ["class", "check-results", 4, "ngIf"], [1, "comparison-section"], [1, "section-header"], [1, "fas", "fa-exchange-alt"], [1, "comparison-tabs"], [1, "comparison-tab", 3, "click"], [1, "fas", "fa-sign-in-alt"], [1, "fas", "fa-bullseye"], [1, "fas", "fa-check-square"], [1, "comparison-content"], ["language", "json", 3, "value", "readonly", "toolbar", "lineWrapping"], [1, "result-pulse"], [1, "check-results"], [1, "fas", "fa-tasks"], [1, "check-summary"], [1, "check-list"], ["class", "check-item", 3, "passed", "failed", "animation-delay", 4, "ngFor", "ngForOf"], [1, "check-item"], [1, "check-status"], [1, "fas"], [1, "check-content"], [1, "check-name"], ["class", "check-message", 4, "ngIf"], ["class", "check-weight", 4, "ngIf"], [1, "check-message"], [1, "check-weight"], [1, "weight-label"], [1, "details-tab"], [1, "details-grid"], [1, "detail-card"], [1, "detail-icon"], [1, "fas", "fa-fingerprint"], [1, "detail-content"], [1, "detail-label"], [1, "detail-value", "monospace"], ["class", "detail-card clickable", 3, "click", 4, "ngIf"], [1, "fas", "fa-tag"], [1, "detail-value"], [1, "fas", "fa-play-circle"], [1, "fas", "fa-stop-circle"], [1, "fas", "fa-hourglass-half"], ["class", "error-section", 4, "ngIf"], ["class", "result-details-section", 4, "ngIf"], [1, "detail-card", "clickable", 3, "click"], [1, "detail-value", "link"], [1, "fas", "fa-external-link-alt", "detail-action"], [1, "error-section"], [1, "section-header", "error"], [1, "error-content"], [3, "value", "readonly", "toolbar", "lineWrapping"], [1, "result-details-section"], [1, "fas", "fa-file-code"], [1, "result-details-content"], [1, "ai-runs-tab"], ["class", "loading-state", 4, "ngIf"], ["class", "ai-section", 4, "ngIf"], ["class", "empty-state", 4, "ngIf"], [1, "loading-state"], [1, "skeleton-list"], ["class", "skeleton-card", 4, "ngFor", "ngForOf"], [1, "skeleton-card"], [1, "skeleton-icon"], [1, "skeleton-content"], [1, "skeleton-line", "wide"], [1, "skeleton-line", "narrow"], [1, "ai-section"], [1, "count-badge"], [1, "ai-run-list"], ["class", "ai-run-card", 3, "click", 4, "ngFor", "ngForOf"], [1, "ai-run-card", 3, "click"], [1, "ai-run-icon", "agent"], [1, "ai-run-content"], [1, "ai-run-name"], [1, "ai-run-meta"], [1, "status-chip"], ["class", "cost-chip", 4, "ngIf"], [1, "fas", "fa-chevron-right", "ai-run-arrow"], [1, "cost-chip"], [1, "fas", "fa-comment-dots"], [1, "ai-run-icon", "prompt"], [1, "empty-state"], [1, "empty-icon"], [1, "feedback-tab"], ["class", "feedback-list", 4, "ngIf"], [1, "skeleton-avatar"], [1, "skeleton-line", "medium"], [1, "feedback-list"], ["class", "feedback-item", 4, "ngFor", "ngForOf"], [1, "feedback-item"], [1, "feedback-header"], [1, "feedback-user"], [1, "user-avatar"], [1, "user-name"], [1, "feedback-date"], [1, "feedback-body"], [1, "feedback-rating"], [1, "rating-stars"], ["class", "fas fa-star", 3, "filled", 4, "ngFor", "ngForOf"], [1, "rating-value"], ["class", "feedback-verdict", 4, "ngIf"], ["class", "feedback-comments", 4, "ngIf"], [1, "feedback-verdict"], [1, "verdict-badge"], [1, "feedback-comments"], [1, "execution-tab"], [3, "machineName", "machineId", "runByUserName", "runByUserEmail", "runContextDetailsJson"], [1, "log-tab"], [1, "log-header"], [1, "log-title"], [1, "log-actions"], ["kendoButton", "", "look", "flat", 3, "click"], [1, "fas", "fa-copy"], [1, "log-container"]], template: function TestRunFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
|
|
1318
|
+
i0.ɵɵelementStart(0, "div", 0);
|
|
1319
|
+
i0.ɵɵtemplate(1, TestRunFormComponentExtended_div_1_Template, 7, 1, "div", 1);
|
|
1320
|
+
i0.ɵɵelementStart(2, "div", 2)(3, "nav", 3)(4, "ol")(5, "li")(6, "a", 4);
|
|
1321
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_a_click_6_listener() { return ctx.navigateToTestingDashboard(); });
|
|
1322
|
+
i0.ɵɵelement(7, "i", 5);
|
|
1323
|
+
i0.ɵɵelementStart(8, "span", 6);
|
|
1324
|
+
i0.ɵɵtext(9, "Testing");
|
|
1325
|
+
i0.ɵɵelementEnd()()();
|
|
1326
|
+
i0.ɵɵtemplate(10, TestRunFormComponentExtended_li_10_Template, 6, 1, "li", 7);
|
|
1327
|
+
i0.ɵɵelementStart(11, "li", 8);
|
|
1328
|
+
i0.ɵɵelement(12, "i", 9);
|
|
1329
|
+
i0.ɵɵelementStart(13, "span");
|
|
1330
|
+
i0.ɵɵtext(14);
|
|
1331
|
+
i0.ɵɵelementEnd()()()();
|
|
1332
|
+
i0.ɵɵelementStart(15, "div", 10)(16, "div", 11)(17, "div", 12);
|
|
1333
|
+
i0.ɵɵelement(18, "i", 13);
|
|
1334
|
+
i0.ɵɵelementEnd();
|
|
1335
|
+
i0.ɵɵelementStart(19, "div", 14)(20, "h1");
|
|
1336
|
+
i0.ɵɵtext(21, " Test Run ");
|
|
1337
|
+
i0.ɵɵelementStart(22, "span", 15);
|
|
1338
|
+
i0.ɵɵtext(23);
|
|
755
1339
|
i0.ɵɵelementEnd()();
|
|
756
|
-
i0.ɵɵelementStart(
|
|
757
|
-
i0.ɵɵ
|
|
1340
|
+
i0.ɵɵelementStart(24, "div", 16)(25, "span", 17);
|
|
1341
|
+
i0.ɵɵtext(26);
|
|
758
1342
|
i0.ɵɵelementEnd();
|
|
759
|
-
i0.ɵɵ
|
|
760
|
-
i0.ɵɵ
|
|
1343
|
+
i0.ɵɵtemplate(27, TestRunFormComponentExtended_span_27_Template, 3, 1, "span", 18)(28, TestRunFormComponentExtended_span_28_Template, 3, 0, "span", 18);
|
|
1344
|
+
i0.ɵɵelementEnd()()();
|
|
1345
|
+
i0.ɵɵelementStart(29, "div", 19)(30, "button", 20);
|
|
1346
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_30_listener() { return ctx.reRunTest(); });
|
|
1347
|
+
i0.ɵɵelement(31, "i", 21);
|
|
1348
|
+
i0.ɵɵelementStart(32, "span", 22);
|
|
1349
|
+
i0.ɵɵtext(33, "Re-run");
|
|
1350
|
+
i0.ɵɵelementEnd()();
|
|
1351
|
+
i0.ɵɵelementStart(34, "button", 23);
|
|
1352
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_34_listener() { return ctx.refresh(); });
|
|
1353
|
+
i0.ɵɵelement(35, "i", 24);
|
|
1354
|
+
i0.ɵɵelementStart(36, "span", 22);
|
|
1355
|
+
i0.ɵɵtext(37, "Refresh");
|
|
1356
|
+
i0.ɵɵelementEnd()()()();
|
|
1357
|
+
i0.ɵɵelementStart(38, "div", 25)(39, "div", 26)(40, "div", 27);
|
|
1358
|
+
i0.ɵɵelement(41, "i", 28);
|
|
761
1359
|
i0.ɵɵelementEnd();
|
|
762
|
-
i0.ɵɵelementStart(
|
|
763
|
-
i0.ɵɵ
|
|
764
|
-
i0.ɵɵtext(17);
|
|
1360
|
+
i0.ɵɵelementStart(42, "div", 29)(43, "div", 30);
|
|
1361
|
+
i0.ɵɵtext(44, "Started");
|
|
765
1362
|
i0.ɵɵelementEnd();
|
|
766
|
-
i0.ɵɵ
|
|
1363
|
+
i0.ɵɵelementStart(45, "div", 31);
|
|
1364
|
+
i0.ɵɵtext(46);
|
|
1365
|
+
i0.ɵɵelementEnd();
|
|
1366
|
+
i0.ɵɵelementStart(47, "div", 32);
|
|
1367
|
+
i0.ɵɵtext(48);
|
|
1368
|
+
i0.ɵɵpipe(49, "date");
|
|
767
1369
|
i0.ɵɵelementEnd()()();
|
|
768
|
-
i0.ɵɵelementStart(
|
|
769
|
-
i0.ɵɵ
|
|
770
|
-
i0.ɵɵ
|
|
1370
|
+
i0.ɵɵelementStart(50, "div", 26)(51, "div", 27);
|
|
1371
|
+
i0.ɵɵelement(52, "i", 33);
|
|
1372
|
+
i0.ɵɵelementEnd();
|
|
1373
|
+
i0.ɵɵelementStart(53, "div", 29)(54, "div", 30);
|
|
1374
|
+
i0.ɵɵtext(55, "Duration");
|
|
771
1375
|
i0.ɵɵelementEnd();
|
|
772
|
-
i0.ɵɵelementStart(
|
|
773
|
-
i0.ɵɵ
|
|
774
|
-
i0.ɵɵtext(23, " Refresh ");
|
|
1376
|
+
i0.ɵɵelementStart(56, "div", 31);
|
|
1377
|
+
i0.ɵɵtext(57);
|
|
775
1378
|
i0.ɵɵelementEnd()()();
|
|
776
|
-
i0.ɵɵelementStart(
|
|
777
|
-
i0.ɵɵ
|
|
1379
|
+
i0.ɵɵelementStart(58, "div", 26)(59, "div", 27);
|
|
1380
|
+
i0.ɵɵelement(60, "i", 34);
|
|
778
1381
|
i0.ɵɵelementEnd();
|
|
779
|
-
i0.ɵɵelementStart(
|
|
780
|
-
i0.ɵɵtext(
|
|
781
|
-
i0.ɵɵpipe(30, "date");
|
|
782
|
-
i0.ɵɵelementEnd()();
|
|
783
|
-
i0.ɵɵelementStart(31, "div", 18)(32, "div", 19);
|
|
784
|
-
i0.ɵɵtext(33, "Completed");
|
|
1382
|
+
i0.ɵɵelementStart(61, "div", 29)(62, "div", 30);
|
|
1383
|
+
i0.ɵɵtext(63, "Score");
|
|
785
1384
|
i0.ɵɵelementEnd();
|
|
786
|
-
i0.ɵɵelementStart(
|
|
787
|
-
i0.ɵɵtext(
|
|
788
|
-
i0.ɵɵpipe(36, "date");
|
|
789
|
-
i0.ɵɵelementEnd()();
|
|
790
|
-
i0.ɵɵelementStart(37, "div", 18)(38, "div", 19);
|
|
791
|
-
i0.ɵɵtext(39, "Duration");
|
|
1385
|
+
i0.ɵɵelementStart(64, "div", 31);
|
|
1386
|
+
i0.ɵɵtext(65);
|
|
792
1387
|
i0.ɵɵelementEnd();
|
|
793
|
-
i0.ɵɵ
|
|
794
|
-
i0.ɵɵtext(41);
|
|
1388
|
+
i0.ɵɵtemplate(66, TestRunFormComponentExtended_div_66_Template, 2, 4, "div", 35);
|
|
795
1389
|
i0.ɵɵelementEnd()();
|
|
796
|
-
i0.ɵɵelementStart(
|
|
797
|
-
i0.ɵɵ
|
|
1390
|
+
i0.ɵɵelementStart(67, "div", 26)(68, "div", 27);
|
|
1391
|
+
i0.ɵɵelement(69, "i", 36);
|
|
798
1392
|
i0.ɵɵelementEnd();
|
|
799
|
-
i0.ɵɵelementStart(
|
|
800
|
-
i0.ɵɵtext(
|
|
801
|
-
i0.ɵɵelementEnd()();
|
|
802
|
-
i0.ɵɵelementStart(47, "div", 18)(48, "div", 19);
|
|
803
|
-
i0.ɵɵtext(49, "Cost");
|
|
1393
|
+
i0.ɵɵelementStart(70, "div", 29)(71, "div", 30);
|
|
1394
|
+
i0.ɵɵtext(72, "Checks");
|
|
804
1395
|
i0.ɵɵelementEnd();
|
|
805
|
-
i0.ɵɵelementStart(
|
|
806
|
-
i0.ɵɵtext(
|
|
807
|
-
i0.ɵɵelementEnd()()();
|
|
808
|
-
i0.ɵɵelementStart(52, "div", 21)(53, "div", 22)(54, "span", 19);
|
|
809
|
-
i0.ɵɵtext(55, "Checks:");
|
|
1396
|
+
i0.ɵɵelementStart(73, "div", 31);
|
|
1397
|
+
i0.ɵɵtext(74);
|
|
810
1398
|
i0.ɵɵelementEnd();
|
|
811
|
-
i0.ɵɵ
|
|
812
|
-
i0.ɵɵtext(57);
|
|
1399
|
+
i0.ɵɵtemplate(75, TestRunFormComponentExtended_div_75_Template, 2, 4, "div", 35);
|
|
813
1400
|
i0.ɵɵelementEnd()();
|
|
814
|
-
i0.ɵɵelementStart(
|
|
815
|
-
i0.ɵɵ
|
|
1401
|
+
i0.ɵɵelementStart(76, "div", 26)(77, "div", 27);
|
|
1402
|
+
i0.ɵɵelement(78, "i", 37);
|
|
816
1403
|
i0.ɵɵelementEnd();
|
|
817
|
-
i0.ɵɵelementStart(
|
|
818
|
-
i0.ɵɵtext(
|
|
1404
|
+
i0.ɵɵelementStart(79, "div", 29)(80, "div", 30);
|
|
1405
|
+
i0.ɵɵtext(81, "Cost");
|
|
1406
|
+
i0.ɵɵelementEnd();
|
|
1407
|
+
i0.ɵɵelementStart(82, "div", 31);
|
|
1408
|
+
i0.ɵɵtext(83);
|
|
1409
|
+
i0.ɵɵelementEnd()()()();
|
|
1410
|
+
i0.ɵɵtemplate(84, TestRunFormComponentExtended_div_84_Template, 4, 3, "div", 38)(85, TestRunFormComponentExtended_div_85_Template, 9, 2, "div", 39)(86, TestRunFormComponentExtended_div_86_Template, 19, 7, "div", 40);
|
|
1411
|
+
i0.ɵɵelementEnd();
|
|
1412
|
+
i0.ɵɵelementStart(87, "div", 41)(88, "div", 42)(89, "button", 43);
|
|
1413
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_89_listener() { return ctx.changeTab("overview"); });
|
|
1414
|
+
i0.ɵɵelement(90, "i", 44);
|
|
1415
|
+
i0.ɵɵelementStart(91, "span");
|
|
1416
|
+
i0.ɵɵtext(92, "Overview");
|
|
819
1417
|
i0.ɵɵelementEnd()();
|
|
820
|
-
i0.ɵɵ
|
|
1418
|
+
i0.ɵɵelementStart(93, "button", 45);
|
|
1419
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_93_listener() { return ctx.changeTab("details"); });
|
|
1420
|
+
i0.ɵɵelement(94, "i", 46);
|
|
1421
|
+
i0.ɵɵelementStart(95, "span");
|
|
1422
|
+
i0.ɵɵtext(96, "Details");
|
|
821
1423
|
i0.ɵɵelementEnd()();
|
|
822
|
-
i0.ɵɵelementStart(
|
|
823
|
-
i0.ɵɵlistener("click", function
|
|
824
|
-
i0.ɵɵelement(
|
|
825
|
-
i0.ɵɵelementStart(
|
|
826
|
-
i0.ɵɵtext(
|
|
1424
|
+
i0.ɵɵelementStart(97, "button", 47);
|
|
1425
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_97_listener() { return ctx.changeTab("ai-runs"); });
|
|
1426
|
+
i0.ɵɵelement(98, "i", 48);
|
|
1427
|
+
i0.ɵɵelementStart(99, "span");
|
|
1428
|
+
i0.ɵɵtext(100, "AI Runs");
|
|
1429
|
+
i0.ɵɵelementEnd();
|
|
1430
|
+
i0.ɵɵtemplate(101, TestRunFormComponentExtended_span_101_Template, 2, 1, "span", 49);
|
|
1431
|
+
i0.ɵɵelementEnd();
|
|
1432
|
+
i0.ɵɵelementStart(102, "button", 50);
|
|
1433
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_102_listener() { return ctx.changeTab("feedback"); });
|
|
1434
|
+
i0.ɵɵelement(103, "i", 51);
|
|
1435
|
+
i0.ɵɵelementStart(104, "span");
|
|
1436
|
+
i0.ɵɵtext(105, "Feedback");
|
|
1437
|
+
i0.ɵɵelementEnd();
|
|
1438
|
+
i0.ɵɵtemplate(106, TestRunFormComponentExtended_span_106_Template, 2, 1, "span", 49);
|
|
1439
|
+
i0.ɵɵelementEnd();
|
|
1440
|
+
i0.ɵɵelementStart(107, "button", 52);
|
|
1441
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_107_listener() { return ctx.changeTab("execution"); });
|
|
1442
|
+
i0.ɵɵelement(108, "i", 53);
|
|
1443
|
+
i0.ɵɵelementStart(109, "span");
|
|
1444
|
+
i0.ɵɵtext(110, "Execution");
|
|
827
1445
|
i0.ɵɵelementEnd()();
|
|
828
|
-
i0.ɵɵ
|
|
829
|
-
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_70_listener() { return ctx.changeTab("details"); });
|
|
830
|
-
i0.ɵɵelement(71, "i", 28);
|
|
831
|
-
i0.ɵɵelementStart(72, "span");
|
|
832
|
-
i0.ɵɵtext(73, "Details");
|
|
1446
|
+
i0.ɵɵtemplate(111, TestRunFormComponentExtended_button_111_Template, 4, 3, "button", 54);
|
|
833
1447
|
i0.ɵɵelementEnd()();
|
|
834
|
-
i0.ɵɵelementStart(
|
|
835
|
-
i0.ɵɵ
|
|
836
|
-
i0.ɵɵelement(75, "i", 29);
|
|
837
|
-
i0.ɵɵelementStart(76, "span");
|
|
838
|
-
i0.ɵɵtext(77, "AI Runs");
|
|
1448
|
+
i0.ɵɵelementStart(112, "div", 55);
|
|
1449
|
+
i0.ɵɵtemplate(113, TestRunFormComponentExtended_div_113_Template, 34, 20, "div", 56)(114, TestRunFormComponentExtended_div_114_Template, 47, 15, "div", 57)(115, TestRunFormComponentExtended_div_115_Template, 5, 5, "div", 58)(116, TestRunFormComponentExtended_div_116_Template, 4, 4, "div", 59)(117, TestRunFormComponentExtended_div_117_Template, 2, 6, "div", 60)(118, TestRunFormComponentExtended_div_118_Template, 13, 5, "div", 61);
|
|
839
1450
|
i0.ɵɵelementEnd();
|
|
840
|
-
i0.ɵɵ
|
|
1451
|
+
i0.ɵɵelementStart(119, "div", 62);
|
|
1452
|
+
i0.ɵɵelement(120, "i", 63);
|
|
1453
|
+
i0.ɵɵelementStart(121, "div", 64)(122, "h4");
|
|
1454
|
+
i0.ɵɵtext(123, "Keyboard Shortcuts");
|
|
841
1455
|
i0.ɵɵelementEnd();
|
|
842
|
-
i0.ɵɵelementStart(
|
|
843
|
-
i0.ɵɵ
|
|
844
|
-
i0.ɵɵelement(80, "i", 31);
|
|
845
|
-
i0.ɵɵelementStart(81, "span");
|
|
846
|
-
i0.ɵɵtext(82, "Feedback");
|
|
1456
|
+
i0.ɵɵelementStart(124, "ul")(125, "li")(126, "kbd");
|
|
1457
|
+
i0.ɵɵtext(127, "1-6");
|
|
847
1458
|
i0.ɵɵelementEnd();
|
|
848
|
-
i0.ɵɵ
|
|
849
|
-
i0.ɵɵelementEnd()
|
|
850
|
-
i0.ɵɵelementStart(
|
|
851
|
-
i0.ɵɵ
|
|
852
|
-
i0.ɵɵelementEnd()
|
|
1459
|
+
i0.ɵɵtext(128, " Switch tabs");
|
|
1460
|
+
i0.ɵɵelementEnd();
|
|
1461
|
+
i0.ɵɵelementStart(129, "li")(130, "kbd");
|
|
1462
|
+
i0.ɵɵtext(131, "Cmd+R");
|
|
1463
|
+
i0.ɵɵelementEnd();
|
|
1464
|
+
i0.ɵɵtext(132, " Refresh");
|
|
1465
|
+
i0.ɵɵelementEnd();
|
|
1466
|
+
i0.ɵɵelementStart(133, "li")(134, "kbd");
|
|
1467
|
+
i0.ɵɵtext(135, "Cmd+Shift+R");
|
|
1468
|
+
i0.ɵɵelementEnd();
|
|
1469
|
+
i0.ɵɵtext(136, " Re-run test");
|
|
1470
|
+
i0.ɵɵelementEnd()()()()();
|
|
853
1471
|
} if (rf & 2) {
|
|
854
|
-
i0.ɵɵ
|
|
855
|
-
i0.ɵɵ
|
|
1472
|
+
i0.ɵɵclassProp("is-mobile", false);
|
|
1473
|
+
i0.ɵɵadvance();
|
|
1474
|
+
i0.ɵɵproperty("ngIf", ctx.error);
|
|
856
1475
|
i0.ɵɵadvance();
|
|
1476
|
+
i0.ɵɵclassMap(ctx.getStatusClass());
|
|
1477
|
+
i0.ɵɵadvance(8);
|
|
857
1478
|
i0.ɵɵproperty("ngIf", ctx.test);
|
|
858
|
-
i0.ɵɵadvance(
|
|
1479
|
+
i0.ɵɵadvance(4);
|
|
859
1480
|
i0.ɵɵtextInterpolate1("Run #", ctx.record.ID.substring(0, 8), "");
|
|
860
1481
|
i0.ɵɵadvance(3);
|
|
861
1482
|
i0.ɵɵstyleProp("background-color", ctx.getStatusColor());
|
|
862
|
-
i0.ɵɵadvance(6);
|
|
863
|
-
i0.ɵɵstyleProp("background-color", ctx.getStatusColor());
|
|
864
1483
|
i0.ɵɵadvance();
|
|
865
1484
|
i0.ɵɵproperty("ngClass", ctx.getStatusIcon());
|
|
1485
|
+
i0.ɵɵadvance(5);
|
|
1486
|
+
i0.ɵɵtextInterpolate1("#", ctx.record.ID.substring(0, 8), "");
|
|
1487
|
+
i0.ɵɵadvance(2);
|
|
1488
|
+
i0.ɵɵstyleProp("background-color", ctx.getStatusColor());
|
|
866
1489
|
i0.ɵɵadvance();
|
|
867
1490
|
i0.ɵɵtextInterpolate1(" ", ctx.record.Status, " ");
|
|
868
1491
|
i0.ɵɵadvance();
|
|
869
1492
|
i0.ɵɵproperty("ngIf", ctx.test);
|
|
1493
|
+
i0.ɵɵadvance();
|
|
1494
|
+
i0.ɵɵproperty("ngIf", ctx.autoRefreshEnabled);
|
|
1495
|
+
i0.ɵɵadvance(2);
|
|
1496
|
+
i0.ɵɵproperty("disabled", !ctx.record.TestID);
|
|
1497
|
+
i0.ɵɵadvance(4);
|
|
1498
|
+
i0.ɵɵproperty("disabled", ctx.isRefreshing);
|
|
1499
|
+
i0.ɵɵadvance();
|
|
1500
|
+
i0.ɵɵclassProp("fa-spin", ctx.isRefreshing);
|
|
870
1501
|
i0.ɵɵadvance(11);
|
|
871
|
-
i0.ɵɵtextInterpolate(
|
|
872
|
-
i0.ɵɵadvance(
|
|
873
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(
|
|
874
|
-
i0.ɵɵadvance(
|
|
1502
|
+
i0.ɵɵtextInterpolate(ctx.getRelativeTime(ctx.record.StartedAt));
|
|
1503
|
+
i0.ɵɵadvance(2);
|
|
1504
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(49, 56, ctx.record.StartedAt, "short"));
|
|
1505
|
+
i0.ɵɵadvance(9);
|
|
875
1506
|
i0.ɵɵtextInterpolate(ctx.calculateDuration());
|
|
876
|
-
i0.ɵɵadvance(
|
|
1507
|
+
i0.ɵɵadvance(8);
|
|
877
1508
|
i0.ɵɵtextInterpolate(ctx.formatScore(ctx.record.Score));
|
|
878
|
-
i0.ɵɵadvance(
|
|
879
|
-
i0.ɵɵ
|
|
880
|
-
i0.ɵɵadvance(
|
|
1509
|
+
i0.ɵɵadvance();
|
|
1510
|
+
i0.ɵɵproperty("ngIf", ctx.record.Score != null);
|
|
1511
|
+
i0.ɵɵadvance(8);
|
|
881
1512
|
i0.ɵɵtextInterpolate2("", ctx.record.PassedChecks, "/", ctx.record.TotalChecks, "");
|
|
882
|
-
i0.ɵɵadvance(5);
|
|
883
|
-
i0.ɵɵtextInterpolate(ctx.record.RunByUser);
|
|
884
1513
|
i0.ɵɵadvance();
|
|
885
|
-
i0.ɵɵproperty("ngIf", ctx.
|
|
1514
|
+
i0.ɵɵproperty("ngIf", ctx.record.TotalChecks);
|
|
1515
|
+
i0.ɵɵadvance(8);
|
|
1516
|
+
i0.ɵɵtextInterpolate(ctx.formatCost(ctx.record.CostUSD));
|
|
1517
|
+
i0.ɵɵadvance();
|
|
1518
|
+
i0.ɵɵproperty("ngIf", ctx.record.RunByUser || ctx.testSuiteRun || ctx.record.TargetLogEntityID);
|
|
1519
|
+
i0.ɵɵadvance();
|
|
1520
|
+
i0.ɵɵproperty("ngIf", !ctx.editingTags);
|
|
1521
|
+
i0.ɵɵadvance();
|
|
1522
|
+
i0.ɵɵproperty("ngIf", ctx.editingTags);
|
|
886
1523
|
i0.ɵɵadvance(3);
|
|
887
1524
|
i0.ɵɵclassProp("active", ctx.activeTab === "overview");
|
|
1525
|
+
i0.ɵɵattribute("aria-selected", ctx.activeTab === "overview");
|
|
888
1526
|
i0.ɵɵadvance(4);
|
|
889
1527
|
i0.ɵɵclassProp("active", ctx.activeTab === "details");
|
|
1528
|
+
i0.ɵɵattribute("aria-selected", ctx.activeTab === "details");
|
|
890
1529
|
i0.ɵɵadvance(4);
|
|
891
1530
|
i0.ɵɵclassProp("active", ctx.activeTab === "ai-runs");
|
|
1531
|
+
i0.ɵɵattribute("aria-selected", ctx.activeTab === "ai-runs");
|
|
892
1532
|
i0.ɵɵadvance(4);
|
|
893
1533
|
i0.ɵɵproperty("ngIf", ctx.aiRunsLoaded);
|
|
894
1534
|
i0.ɵɵadvance();
|
|
895
1535
|
i0.ɵɵclassProp("active", ctx.activeTab === "feedback");
|
|
1536
|
+
i0.ɵɵattribute("aria-selected", ctx.activeTab === "feedback");
|
|
896
1537
|
i0.ɵɵadvance(4);
|
|
897
1538
|
i0.ɵɵproperty("ngIf", ctx.feedbackLoaded);
|
|
1539
|
+
i0.ɵɵadvance();
|
|
1540
|
+
i0.ɵɵclassProp("active", ctx.activeTab === "execution");
|
|
1541
|
+
i0.ɵɵattribute("aria-selected", ctx.activeTab === "execution");
|
|
1542
|
+
i0.ɵɵadvance(4);
|
|
1543
|
+
i0.ɵɵproperty("ngIf", ctx.record.Log);
|
|
898
1544
|
i0.ɵɵadvance(2);
|
|
899
1545
|
i0.ɵɵproperty("ngIf", ctx.activeTab === "overview");
|
|
900
1546
|
i0.ɵɵadvance();
|
|
@@ -903,7 +1549,11 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
903
1549
|
i0.ɵɵproperty("ngIf", ctx.activeTab === "ai-runs");
|
|
904
1550
|
i0.ɵɵadvance();
|
|
905
1551
|
i0.ɵɵproperty("ngIf", ctx.activeTab === "feedback");
|
|
906
|
-
} }, dependencies: [i3.NgClass, i3.NgForOf, i3.NgIf, i4.ButtonComponent, i3.JsonPipe, i3.DatePipe], styles: [".test-run-form[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f8f9fa;\n}\n\n\n\n.test-run-header[_ngcontent-%COMP%] {\n background: white;\n border-bottom: 1px solid #e0e0e0;\n padding: 20px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: #666;\n margin-bottom: 16px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: #2196f3;\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.header-content[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n}\n\n.test-run-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 24px;\n}\n\n.test-run-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 24px;\n font-weight: 600;\n color: #333;\n}\n\n.test-run-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 12px;\n border-radius: 12px;\n color: white;\n font-size: 12px;\n font-weight: 600;\n}\n\n.test-type[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #666;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.metrics-bar[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(5, 1fr);\n gap: 16px;\n margin-bottom: 16px;\n}\n\n.metric-card[_ngcontent-%COMP%] {\n background: #f5f7fa;\n border-radius: 8px;\n padding: 12px;\n text-align: center;\n}\n\n.metric-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: #999;\n margin-bottom: 4px;\n}\n\n.metric-value[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 600;\n color: #333;\n}\n\n.secondary-metrics[_ngcontent-%COMP%] {\n display: flex;\n gap: 24px;\n padding-top: 12px;\n border-top: 1px solid #e0e0e0;\n}\n\n.metric-item[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n font-size: 14px;\n}\n\n.metric-item[_ngcontent-%COMP%] .metric-label[_ngcontent-%COMP%] {\n color: #666;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.metric-item[_ngcontent-%COMP%] .metric-value[_ngcontent-%COMP%] {\n color: #333;\n font-weight: 500;\n font-size: 14px;\n}\n\n.metric-item[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: #2196f3;\n text-decoration: none;\n}\n\n.metric-item[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n\n\n.tabs-container[_ngcontent-%COMP%] {\n background: white;\n border-bottom: 1px solid #e0e0e0;\n}\n\n.tabs[_ngcontent-%COMP%] {\n display: flex;\n padding: 0 20px;\n overflow-x: auto;\n}\n\n.tab[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 16px 20px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: #666;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.tab[_ngcontent-%COMP%]:hover {\n color: #2196f3;\n background: rgba(33, 150, 243, 0.05);\n}\n\n.tab.active[_ngcontent-%COMP%] {\n color: #2196f3;\n border-bottom-color: #2196f3;\n}\n\n.tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.tab-badge[_ngcontent-%COMP%] {\n background: #e0e0e0;\n color: #666;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active[_ngcontent-%COMP%] .tab-badge[_ngcontent-%COMP%] {\n background: #e3f2fd;\n color: #2196f3;\n}\n\n\n\n.tab-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n\n\n.overview-tab[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.result-hero[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 32px;\n text-align: center;\n border: 3px solid #e0e0e0;\n}\n\n.result-hero.passed[_ngcontent-%COMP%] {\n background: #e8f5e9;\n border-color: #4caf50;\n}\n\n.result-hero.failed[_ngcontent-%COMP%] {\n background: #ffebee;\n border-color: #f44336;\n}\n\n.result-icon[_ngcontent-%COMP%] {\n font-size: 64px;\n margin-bottom: 16px;\n}\n\n.result-hero.passed[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%] {\n color: #4caf50;\n}\n\n.result-hero.failed[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%] {\n color: #f44336;\n}\n\n.result-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0 0 12px 0;\n font-size: 32px;\n font-weight: 700;\n color: #333;\n}\n\n.result-score[_ngcontent-%COMP%] {\n font-size: 20px;\n font-weight: 600;\n color: #666;\n margin-bottom: 8px;\n}\n\n.result-checks[_ngcontent-%COMP%] {\n font-size: 16px;\n color: #999;\n}\n\n.check-results[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.check-results[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #333;\n}\n\n.check-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.check-item[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 12px;\n border-radius: 8px;\n border: 2px solid #e0e0e0;\n}\n\n.check-item.passed[_ngcontent-%COMP%] {\n background: #f1f8f4;\n border-color: #c8e6c9;\n}\n\n.check-item.failed[_ngcontent-%COMP%] {\n background: #fef5f5;\n border-color: #ffcdd2;\n}\n\n.check-icon[_ngcontent-%COMP%] {\n font-size: 20px;\n flex-shrink: 0;\n}\n\n.check-item.passed[_ngcontent-%COMP%] .check-icon[_ngcontent-%COMP%] {\n color: #4caf50;\n}\n\n.check-item.failed[_ngcontent-%COMP%] .check-icon[_ngcontent-%COMP%] {\n color: #f44336;\n}\n\n.check-content[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.check-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: #333;\n margin-bottom: 4px;\n}\n\n.check-details[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #666;\n line-height: 1.4;\n}\n\n.check-weight[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #999;\n margin-top: 4px;\n}\n\n.comparison-section[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.comparison-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #333;\n}\n\n.comparison-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n border-bottom: 2px solid #e0e0e0;\n}\n\n.comparison-tab[_ngcontent-%COMP%] {\n padding: 10px 20px;\n border: none;\n background: transparent;\n color: #666;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n border-bottom: 3px solid transparent;\n margin-bottom: -2px;\n transition: all 0.2s ease;\n}\n\n.comparison-tab[_ngcontent-%COMP%]:hover {\n color: #2196f3;\n}\n\n.comparison-tab.active[_ngcontent-%COMP%] {\n color: #2196f3;\n border-bottom-color: #2196f3;\n}\n\n.comparison-content[_ngcontent-%COMP%] {\n background: #1e1e1e;\n border-radius: 8px;\n padding: 16px;\n max-height: 400px;\n overflow-y: auto;\n}\n\n.comparison-content[_ngcontent-%COMP%] pre[_ngcontent-%COMP%] {\n margin: 0;\n font-family: 'Courier New', monospace;\n font-size: 13px;\n line-height: 1.5;\n color: #e0e0e0;\n white-space: pre-wrap;\n word-wrap: break-word;\n}\n\n\n\n.details-tab[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.details-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.detail-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: #999;\n}\n\n.detail-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #333;\n word-wrap: break-word;\n}\n\n.detail-value[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: #2196f3;\n text-decoration: none;\n}\n\n.detail-value[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n}\n\n.error-message[_ngcontent-%COMP%], .result-details-json[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.error-message[_ngcontent-%COMP%] h4[_ngcontent-%COMP%], .result-details-json[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 12px 0;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n}\n\n.error-message[_ngcontent-%COMP%] pre[_ngcontent-%COMP%], .result-details-json[_ngcontent-%COMP%] pre[_ngcontent-%COMP%] {\n margin: 0;\n font-family: 'Courier New', monospace;\n font-size: 13px;\n line-height: 1.5;\n color: #333;\n white-space: pre-wrap;\n word-wrap: break-word;\n background: #f5f7fa;\n padding: 16px;\n border-radius: 8px;\n}\n\n\n\n.ai-runs-tab[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.ai-runs-section[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.ai-runs-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #333;\n}\n\n.ai-run-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.ai-run-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: #f8f9fa;\n border: 2px solid transparent;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.ai-run-card[_ngcontent-%COMP%]:hover {\n background: #e3f2fd;\n border-color: #90caf9;\n}\n\n.ai-run-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #2196f3;\n color: white;\n border-radius: 8px;\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.ai-run-icon.prompt[_ngcontent-%COMP%] {\n background: #9c27b0;\n}\n\n.ai-run-content[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.ai-run-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: #333;\n margin-bottom: 4px;\n}\n\n.ai-run-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: #666;\n}\n\n.ai-run-card[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: #999;\n font-size: 14px;\n}\n\n\n\n.feedback-tab[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.feedback-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.feedback-item[_ngcontent-%COMP%] {\n padding: 16px;\n background: #f8f9fa;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n}\n\n.feedback-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.feedback-user[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n}\n\n.feedback-date[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #999;\n}\n\n.feedback-rating[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #666;\n margin-bottom: 8px;\n}\n\n.feedback-correct[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #666;\n margin-bottom: 8px;\n}\n\n.feedback-comments[_ngcontent-%COMP%] {\n font-size: 14px;\n line-height: 1.5;\n color: #333;\n padding: 12px;\n background: white;\n border-radius: 6px;\n border-left: 3px solid #2196f3;\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: #999;\n text-align: center;\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@media (max-width: 1200px) {\n .metrics-bar[_ngcontent-%COMP%] {\n grid-template-columns: repeat(3, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .metrics-bar[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .details-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .header-content[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .tabs[_ngcontent-%COMP%] {\n overflow-x: auto;\n }\n}"], changeDetection: 0 }); }
|
|
1552
|
+
i0.ɵɵadvance();
|
|
1553
|
+
i0.ɵɵproperty("ngIf", ctx.activeTab === "execution");
|
|
1554
|
+
i0.ɵɵadvance();
|
|
1555
|
+
i0.ɵɵproperty("ngIf", ctx.activeTab === "log");
|
|
1556
|
+
} }, dependencies: [i5.NgClass, i5.NgForOf, i5.NgIf, i6.DefaultValueAccessor, i6.NgControlStatus, i6.NgModel, i7.ButtonComponent, i8.CodeEditorComponent, i3.ExecutionContextComponent, i9.EntityLinkPillComponent, i5.DecimalPipe, i5.DatePipe], styles: ["\n\n\n\n\n\n\n\n[_nghost-%COMP%] {\n --test-primary: #2563eb;\n --test-primary-light: #3b82f6;\n --test-primary-dark: #1d4ed8;\n --test-success: #10b981;\n --test-success-light: #d1fae5;\n --test-error: #ef4444;\n --test-error-light: #fee2e2;\n --test-warning: #f59e0b;\n --test-warning-light: #fef3c7;\n --test-timeout: #f97316;\n --test-timeout-light: #ffedd5;\n --test-running: #3b82f6;\n --test-pending: #8b5cf6;\n --test-skipped: #6b7280;\n --test-bg: #f8fafc;\n --test-surface: #ffffff;\n --test-border: #e2e8f0;\n --test-text: #1e293b;\n --test-text-secondary: #64748b;\n --test-text-muted: #94a3b8;\n --test-radius-sm: 6px;\n --test-radius-md: 10px;\n --test-radius-lg: 16px;\n --test-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);\n --test-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n --test-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\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.test-run-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.error-banner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 12px 20px;\n background: linear-gradient(135deg, var(--test-error) 0%, #dc2626 100%);\n color: white;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n animation: _ngcontent-%COMP%_slideDown 0.3s ease-out;\n}\n\n.error-banner[_ngcontent-%COMP%]:hover {\n background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);\n}\n\n.error-banner[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.retry-btn[_ngcontent-%COMP%] {\n background: rgba(255, 255, 255, 0.2);\n border: 1px solid rgba(255, 255, 255, 0.3);\n color: white;\n padding: 6px 12px;\n border-radius: var(--test-radius-sm);\n cursor: pointer;\n font-size: 12px;\n font-weight: 600;\n transition: var(--test-transition);\n}\n\n.retry-btn[_ngcontent-%COMP%]:hover {\n background: rgba(255, 255, 255, 0.3);\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n transform: translateY(-100%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n\n\n\n\n.test-run-header[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n padding: 20px;\n position: relative;\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 flex-wrap: wrap;\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: var(--test-radius-sm);\n transition: var(--test-transition);\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover {\n background: rgba(37, 99, 235, 0.1);\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.header-content[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\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.status-indicator[_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: white;\n font-size: 24px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.status-indicator[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n\n\n.test-run-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.test-run-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-run-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] .run-id[_ngcontent-%COMP%] {\n color: var(--test-text-secondary);\n font-weight: 500;\n}\n\n.test-run-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: white;\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\n\n.meta-item[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n color: var(--test-text-secondary);\n}\n\n.meta-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\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.btn-text[_ngcontent-%COMP%] {\n margin-left: 6px;\n}\n\n\n\n\n\n.metrics-bar[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n margin-bottom: 16px;\n}\n\n.metric-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 14px;\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-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-surface);\n border-radius: var(--test-radius-sm);\n color: var(--test-primary);\n font-size: 16px;\n flex-shrink: 0;\n}\n\n.metric-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\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: 4px;\n}\n\n.metric-value[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.metric-detail[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--test-text-muted);\n margin-top: 2px;\n}\n\n\n\n.metric-progress[_ngcontent-%COMP%] {\n margin-top: 6px;\n height: 4px;\n background: var(--test-border);\n border-radius: 2px;\n overflow: hidden;\n}\n\n.progress-bar[_ngcontent-%COMP%] {\n height: 100%;\n border-radius: 2px;\n transition: width 0.5s ease-out;\n}\n\n\n\n.secondary-info[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding-top: 16px;\n border-top: 1px solid var(--test-border);\n flex-wrap: wrap;\n}\n\n.info-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--test-text-secondary);\n padding: 6px 12px;\n background: var(--test-bg);\n border-radius: 20px;\n transition: var(--test-transition);\n}\n\n.info-chip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.info-chip.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.info-chip.clickable[_ngcontent-%COMP%]:hover {\n background: rgba(37, 99, 235, 0.1);\n color: var(--test-primary);\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 position: relative;\n}\n\n.tab[_ngcontent-%COMP%]:hover {\n color: var(--test-primary);\n background: rgba(37, 99, 235, 0.05);\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: rgba(37, 99, 235, 0.15);\n color: var(--test-primary);\n}\n\n.shortcut-hint[_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 font-family: -apple-system, BlinkMacSystemFont, sans-serif;\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.result-hero[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 32px;\n text-align: center;\n border: 2px solid var(--test-border);\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.result-hero.passed[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #ecfdf5 0%, var(--test-success-light) 100%);\n border-color: var(--test-success);\n}\n\n.result-hero.failed[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fef2f2 0%, var(--test-error-light) 100%);\n border-color: var(--test-error);\n}\n\n.result-hero.error[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fffbeb 0%, var(--test-warning-light) 100%);\n border-color: var(--test-warning);\n}\n\n.result-hero.timeout[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fff7ed 0%, var(--test-timeout-light) 100%);\n border-color: var(--test-timeout);\n}\n\n.result-hero.running[_ngcontent-%COMP%], \n.result-hero.pending[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);\n border-color: var(--test-primary-light);\n}\n\n.result-icon-wrapper[_ngcontent-%COMP%] {\n position: relative;\n display: inline-block;\n margin-bottom: 16px;\n}\n\n.result-icon[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-surface);\n border-radius: 50%;\n font-size: 40px;\n margin: 0 auto;\n box-shadow: var(--test-shadow-md);\n}\n\n.result-hero.passed[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%] { color: var(--test-success); }\n.result-hero.failed[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%] { color: var(--test-error); }\n.result-hero.error[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%] { color: var(--test-warning); }\n.result-hero.timeout[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%] { color: var(--test-timeout); }\n.result-hero.running[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%], \n.result-hero.pending[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%] { color: var(--test-primary); }\n\n.result-pulse[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 100px;\n height: 100px;\n border-radius: 50%;\n background: rgba(59, 130, 246, 0.2);\n animation: _ngcontent-%COMP%_pulse 2s ease-in-out infinite;\n}\n\n@keyframes _ngcontent-%COMP%_pulse {\n 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.5; }\n 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0; }\n}\n\n.result-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0 0 12px 0;\n font-size: clamp(24px, 5vw, 32px);\n font-weight: 800;\n color: var(--test-text);\n}\n\n.result-details[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.result-score[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 600;\n color: var(--test-text-secondary);\n}\n\n.result-divider[_ngcontent-%COMP%] {\n color: var(--test-border);\n}\n\n.result-checks[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--test-text-muted);\n}\n\n\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 16px;\n gap: 12px;\n}\n\n.section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 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.section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.section-header.error[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-error);\n}\n\n.check-summary[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--test-text-secondary);\n}\n\n\n\n.check-results[_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.check-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.check-item[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 14px 16px;\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n transition: var(--test-transition);\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out backwards;\n}\n\n.check-item[_ngcontent-%COMP%]:hover {\n transform: translateX(4px);\n}\n\n.check-item.passed[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);\n border-color: #86efac;\n}\n\n.check-item.failed[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%);\n border-color: #fca5a5;\n}\n\n.check-status[_ngcontent-%COMP%] {\n font-size: 20px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.check-item.passed[_ngcontent-%COMP%] .check-status[_ngcontent-%COMP%] { color: var(--test-success); }\n.check-item.failed[_ngcontent-%COMP%] .check-status[_ngcontent-%COMP%] { color: var(--test-error); }\n\n.check-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.check-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.check-message[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--test-text-secondary);\n line-height: 1.5;\n word-wrap: break-word;\n}\n\n.check-weight[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n flex-shrink: 0;\n text-align: right;\n}\n\n.weight-label[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n\n\n.comparison-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.comparison-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}\n\n.comparison-tab[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 10px 16px;\n border: none;\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n border-radius: var(--test-radius-sm);\n transition: var(--test-transition);\n}\n\n.comparison-tab[_ngcontent-%COMP%]:hover {\n color: var(--test-text);\n background: rgba(0, 0, 0, 0.05);\n}\n\n.comparison-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.comparison-content[_ngcontent-%COMP%] {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n}\n\n\n\n\n\n.details-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.details-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.detail-card[_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 transition: var(--test-transition);\n}\n\n.detail-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.detail-card.clickable[_ngcontent-%COMP%]:hover {\n background: rgba(37, 99, 235, 0.05);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n}\n\n.detail-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n color: var(--test-primary);\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.detail-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.detail-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 margin-bottom: 4px;\n}\n\n.detail-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-text);\n word-wrap: break-word;\n font-weight: 500;\n}\n\n.detail-value.monospace[_ngcontent-%COMP%] {\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 12px;\n}\n\n.detail-value.link[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.detail-action[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 12px;\n transition: var(--test-transition);\n}\n\n.detail-card.clickable[_ngcontent-%COMP%]:hover .detail-action[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n\n\n.error-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.error-content[_ngcontent-%COMP%] {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid #fca5a5;\n}\n\n\n\n.result-details-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.result-details-content[_ngcontent-%COMP%] {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n}\n\n\n\n\n\n.ai-runs-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.ai-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.count-badge[_ngcontent-%COMP%] {\n background: var(--test-bg);\n color: var(--test-text-secondary);\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.ai-run-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.ai-run-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\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.ai-run-card[_ngcontent-%COMP%]:hover {\n background: rgba(37, 99, 235, 0.05);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n box-shadow: var(--test-shadow-sm);\n}\n\n.ai-run-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, var(--test-primary) 0%, var(--test-primary-dark) 100%);\n color: white;\n border-radius: var(--test-radius-md);\n font-size: 18px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-sm);\n}\n\n.ai-run-icon.agent[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, var(--test-primary) 0%, var(--test-primary-dark) 100%);\n}\n\n.ai-run-icon.prompt[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #9333ea 0%, #7c3aed 100%);\n}\n\n.ai-run-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.ai-run-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 6px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.ai-run-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 10px;\n font-size: 12px;\n color: var(--test-text-secondary);\n flex-wrap: wrap;\n}\n\n.status-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-chip.complete[_ngcontent-%COMP%], \n.status-chip.completed[_ngcontent-%COMP%], \n.status-chip.passed[_ngcontent-%COMP%] {\n background: var(--test-success-light);\n color: #059669;\n}\n\n.status-chip.failed[_ngcontent-%COMP%], \n.status-chip.error[_ngcontent-%COMP%] {\n background: var(--test-error-light);\n color: #dc2626;\n}\n\n.status-chip.running[_ngcontent-%COMP%] {\n background: #dbeafe;\n color: var(--test-primary);\n}\n\n.cost-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n color: var(--test-text-muted);\n}\n\n.ai-run-arrow[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.ai-run-card[_ngcontent-%COMP%]:hover .ai-run-arrow[_ngcontent-%COMP%] {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n\n\n\n\n.feedback-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.feedback-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.feedback-item[_ngcontent-%COMP%] {\n padding: 20px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n border: 1px solid var(--test-border);\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.feedback-item[_ngcontent-%COMP%]:hover {\n border-color: var(--test-primary-light);\n}\n\n.feedback-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.feedback-user[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.user-avatar[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n color: var(--test-primary);\n font-size: 14px;\n}\n\n.user-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.feedback-date[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.feedback-body[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.feedback-rating[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.rating-stars[_ngcontent-%COMP%] {\n display: flex;\n gap: 2px;\n}\n\n.rating-stars[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-border);\n}\n\n.rating-stars[_ngcontent-%COMP%] i.filled[_ngcontent-%COMP%] {\n color: #fbbf24;\n}\n\n.rating-value[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.feedback-verdict[_ngcontent-%COMP%] {\n display: flex;\n}\n\n.verdict-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.verdict-badge.correct[_ngcontent-%COMP%] {\n background: var(--test-success-light);\n color: #059669;\n}\n\n.verdict-badge.incorrect[_ngcontent-%COMP%] {\n background: var(--test-error-light);\n color: #dc2626;\n}\n\n.feedback-comments[_ngcontent-%COMP%] {\n padding: 14px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n border-left: 3px solid var(--test-primary);\n}\n\n.feedback-comments[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n line-height: 1.6;\n color: var(--test-text);\n}\n\n\n\n\n\n.log-tab[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0;\n height: 100%;\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.log-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n background: var(--test-surface);\n padding: 16px 20px;\n border-radius: var(--test-radius-lg) var(--test-radius-lg) 0 0;\n border: 1px solid var(--test-border);\n border-bottom: none;\n}\n\n.log-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.log-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-text-secondary);\n font-size: 16px;\n}\n\n.log-title[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.log-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.log-container[_ngcontent-%COMP%] {\n flex: 1;\n border-radius: 0 0 var(--test-radius-lg) var(--test-radius-lg);\n overflow: hidden;\n min-height: 300px;\n border: 1px solid var(--test-border);\n border-top: none;\n}\n\n\n\n\n\n.loading-state[_ngcontent-%COMP%] {\n padding: 20px;\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.skeleton-avatar[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n border-radius: var(--test-radius-md);\n background: linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-avatar[_ngcontent-%COMP%] {\n border-radius: 50%;\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, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 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.medium[_ngcontent-%COMP%] { width: 55%; }\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\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%] h3[_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;\n font-size: 14px;\n color: var(--test-text-secondary);\n max-width: 300px;\n}\n\n\n\n\n\n.shortcuts-hint[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: 100;\n}\n\n.shortcuts-hint[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: 50%;\n color: var(--test-text-muted);\n font-size: 16px;\n cursor: pointer;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.shortcuts-hint[_ngcontent-%COMP%]:hover > i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n border-color: var(--test-primary-light);\n}\n\n.shortcuts-popup[_ngcontent-%COMP%] {\n display: none;\n position: absolute;\n bottom: 50px;\n right: 0;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 16px;\n box-shadow: var(--test-shadow-lg);\n min-width: 200px;\n}\n\n.shortcuts-hint[_ngcontent-%COMP%]:hover .shortcuts-popup[_ngcontent-%COMP%] {\n display: block;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease-out;\n}\n\n.shortcuts-popup[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 12px 0;\n font-size: 14px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.shortcuts-popup[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.shortcuts-popup[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 6px 0;\n font-size: 13px;\n color: var(--test-text-secondary);\n}\n\n.shortcuts-popup[_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, 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(3, 1fr);\n }\n\n .details-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .shortcuts-hint[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n\n\n\n\n@media (max-width: 768px) {\n .test-run-form[_ngcontent-%COMP%] {\n height: auto;\n min-height: 100%;\n }\n\n .test-run-header[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .breadcrumb[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n }\n\n .breadcrumb[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] {\n font-size: 12px;\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 .status-indicator[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n font-size: 20px;\n }\n\n .test-run-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n\n .test-run-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-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n font-size: 14px;\n }\n\n .metric-value[_ngcontent-%COMP%] {\n font-size: 14px;\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 .shortcut-hint[_ngcontent-%COMP%] {\n display: none;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .result-hero[_ngcontent-%COMP%] {\n padding: 24px 20px;\n }\n\n .result-icon[_ngcontent-%COMP%] {\n width: 64px;\n height: 64px;\n font-size: 32px;\n }\n\n .result-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n font-size: 24px;\n }\n\n .result-score[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .check-results[_ngcontent-%COMP%], \n .comparison-section[_ngcontent-%COMP%], \n .ai-section[_ngcontent-%COMP%], \n .feedback-item[_ngcontent-%COMP%] {\n padding: 18px;\n }\n\n .check-item[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .comparison-tabs[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 4px;\n }\n\n .comparison-tab[_ngcontent-%COMP%] {\n text-align: center;\n }\n\n .details-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .detail-card[_ngcontent-%COMP%] {\n padding: 14px;\n }\n\n .ai-run-card[_ngcontent-%COMP%] {\n padding: 14px;\n }\n\n .ai-run-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 16px;\n }\n\n .ai-run-meta[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 4px;\n }\n\n .feedback-header[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .log-header[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 12px;\n align-items: stretch;\n }\n\n .log-actions[_ngcontent-%COMP%] {\n justify-content: stretch;\n }\n\n .log-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n flex: 1;\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-run-header[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .header-left[_ngcontent-%COMP%] {\n gap: 12px;\n }\n\n .status-indicator[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 18px;\n border-radius: 8px;\n }\n\n .test-run-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 .metric-card[_ngcontent-%COMP%] {\n padding: 10px;\n flex-direction: column;\n text-align: center;\n }\n\n .metric-icon[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n }\n\n .metric-label[_ngcontent-%COMP%] {\n font-size: 9px;\n }\n\n .metric-value[_ngcontent-%COMP%] {\n font-size: 14px;\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 .result-hero[_ngcontent-%COMP%] {\n padding: 20px 16px;\n }\n\n .result-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n font-size: 28px;\n }\n\n .result-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .result-score[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n\n .result-checks[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .check-item[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 8px;\n }\n\n .check-weight[_ngcontent-%COMP%] {\n text-align: left;\n }\n}\n\n\n\n\n\n@media (hover: none) and (pointer: coarse) {\n .tab[_ngcontent-%COMP%], \n .comparison-tab[_ngcontent-%COMP%], \n .ai-run-card[_ngcontent-%COMP%], \n .check-item[_ngcontent-%COMP%], \n .feedback-item[_ngcontent-%COMP%], \n .detail-card.clickable[_ngcontent-%COMP%] {\n -webkit-tap-highlight-color: transparent;\n }\n\n .ai-run-card[_ngcontent-%COMP%]:active, \n .detail-card.clickable[_ngcontent-%COMP%]:active {\n background: rgba(37, 99, 235, 0.1);\n transform: scale(0.98);\n }\n\n .tab[_ngcontent-%COMP%]:active {\n background: rgba(37, 99, 235, 0.1);\n }\n\n \n\n .tab[_ngcontent-%COMP%] {\n min-height: 48px;\n }\n\n .ai-run-card[_ngcontent-%COMP%], \n .detail-card[_ngcontent-%COMP%] {\n min-height: 64px;\n }\n}\n\n\n\n\n\n@media (prefers-contrast: high) {\n .status-badge[_ngcontent-%COMP%] {\n border: 2px solid currentColor;\n }\n\n .check-item[_ngcontent-%COMP%] {\n border-width: 2px;\n }\n\n .tab.active[_ngcontent-%COMP%] {\n border-bottom-width: 4px;\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-avatar[_ngcontent-%COMP%], \n .skeleton-line[_ngcontent-%COMP%] {\n animation: none;\n background: #e2e8f0;\n }\n\n .result-pulse[_ngcontent-%COMP%] {\n animation: none;\n display: none;\n }\n}\n\n\n\n\n\n@media print {\n .test-run-form[_ngcontent-%COMP%] {\n background: white;\n height: auto;\n }\n\n .header-actions[_ngcontent-%COMP%], \n .tabs-container[_ngcontent-%COMP%], \n .shortcuts-hint[_ngcontent-%COMP%], \n .log-actions[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n overflow: visible;\n padding: 0;\n }\n\n .result-hero[_ngcontent-%COMP%], \n .check-results[_ngcontent-%COMP%], \n .details-grid[_ngcontent-%COMP%], \n .ai-section[_ngcontent-%COMP%], \n .feedback-item[_ngcontent-%COMP%] {\n break-inside: avoid;\n box-shadow: none;\n border: 1px solid #ddd;\n }\n\n .comparison-content[_ngcontent-%COMP%], \n .log-container[_ngcontent-%COMP%] {\n max-height: none;\n overflow: visible;\n }\n}\n\n\n\n\n\n.tags-bar[_ngcontent-%COMP%] {\n margin-top: 16px;\n padding: 8px 14px;\n background: linear-gradient(135deg, rgba(37, 99, 235, 0.04) 0%, rgba(37, 99, 235, 0.08) 100%);\n border: 1px solid rgba(37, 99, 235, 0.15);\n border-radius: 8px;\n max-width: 600px;\n}\n\n.tags-bar-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.tags-bar-label[_ngcontent-%COMP%] {\n color: var(--test-text-secondary);\n font-size: 14px;\n}\n\n.tags-bar-label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n opacity: 0.6;\n}\n\n.tags-bar-chips[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n flex: 1;\n}\n\n.tag-inline[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n background: rgba(37, 99, 235, 0.1);\n color: var(--test-primary);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.01em;\n}\n\n.tags-bar-empty[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n opacity: 0.7;\n flex: 1;\n}\n\n.tags-bar-edit[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: transparent;\n border: 1px dashed var(--test-border);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--test-text-secondary);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.tags-bar-edit[_ngcontent-%COMP%]:hover {\n border-color: var(--test-primary);\n color: var(--test-primary);\n background: rgba(37, 99, 235, 0.05);\n}\n\n.tags-bar-edit[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n\n\n.tags-editor-panel[_ngcontent-%COMP%] {\n margin-top: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-primary);\n border-radius: var(--test-radius-md);\n overflow: hidden;\n box-shadow: 0 4px 12px rgba(37, 99, 235, 0.1);\n max-width: 600px;\n}\n\n.tags-editor-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n background: rgba(37, 99, 235, 0.08);\n border-bottom: 1px solid rgba(37, 99, 235, 0.2);\n}\n\n.tags-editor-title[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.tags-editor-body[_ngcontent-%COMP%] {\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.tags-editor-chips[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n min-height: 32px;\n}\n\n.tag-editable[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 8px 5px 12px;\n background: var(--test-surface);\n border: 1px solid var(--test-primary);\n color: var(--test-primary);\n border-radius: 14px;\n font-size: 12px;\n font-weight: 500;\n}\n\n.tag-remove-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n background: transparent;\n border: none;\n color: var(--test-primary);\n cursor: pointer;\n border-radius: 50%;\n font-size: 9px;\n opacity: 0.6;\n transition: var(--test-transition);\n}\n\n.tag-remove-btn[_ngcontent-%COMP%]:hover {\n opacity: 1;\n background: var(--test-error-light);\n color: var(--test-error);\n}\n\n.tags-empty-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n font-style: italic;\n padding: 4px 0;\n}\n\n.tags-editor-input[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.tag-text-input[_ngcontent-%COMP%] {\n flex: 1;\n padding: 10px 14px;\n border: 1px solid var(--test-border);\n border-radius: 8px;\n font-size: 13px;\n background: var(--test-bg);\n}\n\n.tag-text-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--test-primary);\n background: var(--test-surface);\n box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);\n}\n\n.tag-text-input[_ngcontent-%COMP%]::placeholder {\n color: var(--test-text-secondary);\n opacity: 0.6;\n}\n\n.tags-editor-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-start;\n gap: 8px;\n padding: 12px 16px;\n background: var(--test-bg);\n border-top: 1px solid var(--test-border);\n}\n\n\n\n@media (max-width: 768px) {\n .tags-bar[_ngcontent-%COMP%] {\n padding: 8px 12px;\n }\n\n .tags-bar-content[_ngcontent-%COMP%] {\n gap: 8px;\n }\n\n .tag-inline[_ngcontent-%COMP%] {\n padding: 3px 8px;\n font-size: 10px;\n }\n\n .tags-editor-panel[_ngcontent-%COMP%] {\n margin-top: 12px;\n }\n\n .tags-editor-body[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .tags-editor-footer[_ngcontent-%COMP%] {\n padding: 10px 12px;\n }\n}"], changeDetection: 0 }); }
|
|
907
1557
|
};
|
|
908
1558
|
TestRunFormComponentExtended = __decorate([
|
|
909
1559
|
RegisterClass(BaseFormComponent, 'MJ: Test Runs')
|
|
@@ -911,9 +1561,12 @@ TestRunFormComponentExtended = __decorate([
|
|
|
911
1561
|
export { TestRunFormComponentExtended };
|
|
912
1562
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TestRunFormComponentExtended, [{
|
|
913
1563
|
type: Component,
|
|
914
|
-
args: [{ selector: 'mj-test-run-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"test-run-form\">\n <!-- Header Section -->\n <div class=\"test-run-header\">\n <div class=\"breadcrumb\">\n <a href=\"javascript:void(0)\" (click)=\"openTest()\" *ngIf=\"test\">\n <i class=\"fas fa-flask\"></i> {{ test.Name }}\n </a>\n <i class=\"fas fa-chevron-right\" *ngIf=\"test\"></i>\n <span>Run #{{ record.ID.substring(0, 8) }}</span>\n </div>\n\n <div class=\"header-content\">\n <div class=\"header-left\">\n <div class=\"test-run-icon\" [style.background-color]=\"getStatusColor()\">\n <i class=\"fas fa-flask\"></i>\n </div>\n <div class=\"test-run-info\">\n <h1>Test Run</h1>\n <div class=\"test-run-meta\">\n <span class=\"status-badge\" [style.background-color]=\"getStatusColor()\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon()\"></i>\n {{ record.Status }}\n </span>\n <span class=\"test-type\" *ngIf=\"test\">{{ test.Type }}</span>\n </div>\n </div>\n </div>\n <div class=\"header-actions\">\n <button kendoButton (click)=\"reRunTest()\" icon=\"refresh\">\n Re-run Test\n </button>\n <button kendoButton (click)=\"refresh()\" icon=\"sync\">\n Refresh\n </button>\n </div>\n </div>\n\n <!-- Metrics Bar -->\n <div class=\"metrics-bar\">\n <div class=\"metric-card\">\n <div class=\"metric-label\">Started</div>\n <div class=\"metric-value\">{{ record.StartedAt | date:'short' }}</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-label\">Completed</div>\n <div class=\"metric-value\">{{ record.CompletedAt | date:'short' }}</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-label\">Duration</div>\n <div class=\"metric-value\">{{ calculateDuration() }}</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-label\">Score</div>\n <div class=\"metric-value\">{{ formatScore(record.Score) }}</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-label\">Cost</div>\n <div class=\"metric-value\">{{ formatCost(record.CostUSD) }}</div>\n </div>\n </div>\n\n <!-- Secondary Metrics -->\n <div class=\"secondary-metrics\">\n <div class=\"metric-item\">\n <span class=\"metric-label\">Checks:</span>\n <span class=\"metric-value\">{{ record.PassedChecks }}/{{ record.TotalChecks }}</span>\n </div>\n <div class=\"metric-item\">\n <span class=\"metric-label\">Run By:</span>\n <span class=\"metric-value\">{{ record.RunByUser }}</span>\n </div>\n <div class=\"metric-item\" *ngIf=\"testSuiteRun\">\n <span class=\"metric-label\">Part of Suite:</span>\n <a href=\"javascript:void(0)\" (click)=\"openTestSuiteRun()\">\n {{ testSuiteRun.ID }} (Seq: {{ record.Sequence }})\n </a>\n </div>\n </div>\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs-container\">\n <div class=\"tabs\">\n <button class=\"tab\" [class.active]=\"activeTab === 'overview'\" (click)=\"changeTab('overview')\">\n <i class=\"fas fa-th-large\"></i>\n <span>Overview</span>\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'details'\" (click)=\"changeTab('details')\">\n <i class=\"fas fa-list\"></i>\n <span>Details</span>\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'ai-runs'\" (click)=\"changeTab('ai-runs')\">\n <i class=\"fas fa-robot\"></i>\n <span>AI Runs</span>\n <span class=\"tab-badge\" *ngIf=\"aiRunsLoaded\">{{ aiAgentRuns.length + aiPromptRuns.length }}</span>\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'feedback'\" (click)=\"changeTab('feedback')\">\n <i class=\"fas fa-comments\"></i>\n <span>Feedback</span>\n <span class=\"tab-badge\" *ngIf=\"feedbackLoaded\">{{ feedbacks.length }}</span>\n </button>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tab-content\">\n <!-- Overview Tab -->\n <div class=\"overview-tab\" *ngIf=\"activeTab === 'overview'\">\n <!-- Result Hero -->\n <div class=\"result-hero\" [class.passed]=\"record.Status === 'Passed'\" [class.failed]=\"record.Status === 'Failed'\">\n <div class=\"result-icon\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon()\"></i>\n </div>\n <div class=\"result-text\">\n <h2>TEST {{ record.Status.toUpperCase() }}</h2>\n <div class=\"result-score\">Score: {{ formatScore(record.Score) }} / 1.0000</div>\n <div class=\"result-checks\">{{ record.PassedChecks }} of {{ record.TotalChecks }} checks passed</div>\n </div>\n </div>\n\n <!-- Check Results -->\n <div class=\"check-results\" *ngIf=\"getCheckResults().length > 0\">\n <h3>Check Results</h3>\n <div class=\"check-list\">\n <div class=\"check-item\" *ngFor=\"let check of getCheckResults()\" [class.passed]=\"check.passed\" [class.failed]=\"!check.passed\">\n <div class=\"check-icon\">\n <i class=\"fas\" [class.fa-check-circle]=\"check.passed\" [class.fa-times-circle]=\"!check.passed\"></i>\n </div>\n <div class=\"check-content\">\n <div class=\"check-name\">{{ check.name }}</div>\n <div class=\"check-details\">{{ check.message }}</div>\n <div class=\"check-weight\" *ngIf=\"check.weight\">Weight: {{ check.weight }}</div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Input / Expected / Actual Comparison -->\n <div class=\"comparison-section\">\n <h3>Data Comparison</h3>\n <div class=\"comparison-tabs\">\n <button class=\"comparison-tab\" [class.active]=\"comparisonView === 'input'\" (click)=\"setComparisonView('input')\">\n Input\n </button>\n <button class=\"comparison-tab\" [class.active]=\"comparisonView === 'expected'\" (click)=\"setComparisonView('expected')\">\n Expected\n </button>\n <button class=\"comparison-tab\" [class.active]=\"comparisonView === 'actual'\" (click)=\"setComparisonView('actual')\">\n Actual\n </button>\n </div>\n <div class=\"comparison-content\">\n <pre>{{ getComparisonData() | json }}</pre>\n </div>\n </div>\n </div>\n\n <!-- Details Tab -->\n <div class=\"details-tab\" *ngIf=\"activeTab === 'details'\">\n <div class=\"details-grid\">\n <div class=\"detail-item\">\n <div class=\"detail-label\">Test Run ID</div>\n <div class=\"detail-value\">{{ record.ID }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Test</div>\n <div class=\"detail-value\">\n <a href=\"javascript:void(0)\" (click)=\"openTest()\" *ngIf=\"test\">{{ test.Name }}</a>\n </div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Status</div>\n <div class=\"detail-value\">{{ record.Status }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Target Type</div>\n <div class=\"detail-value\">{{ record.TargetType || 'N/A' }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Started At</div>\n <div class=\"detail-value\">{{ record.StartedAt | date:'medium' }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Completed At</div>\n <div class=\"detail-value\">{{ record.CompletedAt | date:'medium' }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Duration</div>\n <div class=\"detail-value\">{{ calculateDuration() }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Score</div>\n <div class=\"detail-value\">{{ formatScore(record.Score) }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Cost</div>\n <div class=\"detail-value\">{{ formatCost(record.CostUSD) }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Passed Checks</div>\n <div class=\"detail-value\">{{ record.PassedChecks }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Failed Checks</div>\n <div class=\"detail-value\">{{ record.FailedChecks }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Total Checks</div>\n <div class=\"detail-value\">{{ record.TotalChecks }}</div>\n </div>\n </div>\n\n <div class=\"error-message\" *ngIf=\"record.ErrorMessage\">\n <h4>Error Message</h4>\n <pre>{{ record.ErrorMessage }}</pre>\n </div>\n\n <div class=\"result-details-json\" *ngIf=\"record.ResultDetails\">\n <h4>Full Result Details (JSON)</h4>\n <pre>{{ parsedData.resultDetails | json }}</pre>\n </div>\n </div>\n\n <!-- AI Runs Tab -->\n <div class=\"ai-runs-tab\" *ngIf=\"activeTab === 'ai-runs'\">\n <div class=\"ai-runs-section\" *ngIf=\"aiAgentRuns.length > 0\">\n <h3>AI Agent Runs ({{ aiAgentRuns.length }})</h3>\n <div class=\"ai-run-list\">\n <div class=\"ai-run-card\" *ngFor=\"let run of aiAgentRuns\" (click)=\"openAIAgentRun(run.ID)\">\n <div class=\"ai-run-icon\">\n <i class=\"fas fa-robot\"></i>\n </div>\n <div class=\"ai-run-content\">\n <div class=\"ai-run-name\">{{ run.Agent }}</div>\n <div class=\"ai-run-meta\">\n <span>{{ run.Status }}</span>\n <span *ngIf=\"run.TotalCost\">${{ run.TotalCost }}</span>\n </div>\n </div>\n <i class=\"fas fa-external-link-alt\"></i>\n </div>\n </div>\n </div>\n\n <div class=\"ai-runs-section\" *ngIf=\"aiPromptRuns.length > 0\">\n <h3>AI Prompt Runs ({{ aiPromptRuns.length }})</h3>\n <div class=\"ai-run-list\">\n <div class=\"ai-run-card\" *ngFor=\"let run of aiPromptRuns\" (click)=\"openAIPromptRun(run.ID)\">\n <div class=\"ai-run-icon prompt\">\n <i class=\"fas fa-comment-dots\"></i>\n </div>\n <div class=\"ai-run-content\">\n <div class=\"ai-run-name\">{{ run.Prompt || run.Model }}</div>\n <div class=\"ai-run-meta\">\n <span *ngIf=\"run.TotalCost\">${{ run.TotalCost }}</span>\n </div>\n </div>\n <i class=\"fas fa-external-link-alt\"></i>\n </div>\n </div>\n </div>\n\n <div class=\"no-data\" *ngIf=\"aiRunsLoaded && aiAgentRuns.length === 0 && aiPromptRuns.length === 0\">\n <i class=\"fas fa-inbox\"></i>\n <p>No AI runs associated with this test execution</p>\n </div>\n </div>\n\n <!-- Feedback Tab -->\n <div class=\"feedback-tab\" *ngIf=\"activeTab === 'feedback'\">\n <div class=\"feedback-list\" *ngIf=\"feedbacks.length > 0\">\n <div class=\"feedback-item\" *ngFor=\"let feedback of feedbacks\">\n <div class=\"feedback-header\">\n <div class=\"feedback-user\">\n <i class=\"fas fa-user\"></i>\n {{ feedback.ReviewerUserID }}\n </div>\n <div class=\"feedback-date\">\n {{ feedback.__mj_CreatedAt | date:'medium' }}\n </div>\n </div>\n <div class=\"feedback-rating\">\n Rating: {{ feedback.Rating }}/10\n </div>\n <div class=\"feedback-correct\" *ngIf=\"feedback.IsCorrect !== null\">\n Automated Result: {{ feedback.IsCorrect ? 'Correct' : 'Incorrect' }}\n </div>\n <div class=\"feedback-comments\" *ngIf=\"feedback.CorrectionSummary\">\n {{ feedback.CorrectionSummary }}\n </div>\n </div>\n </div>\n\n <div class=\"no-data\" *ngIf=\"feedbackLoaded && feedbacks.length === 0\">\n <i class=\"fas fa-inbox\"></i>\n <p>No feedback submitted for this test run</p>\n </div>\n </div>\n </div>\n</div>\n", styles: [".test-run-form {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f8f9fa;\n}\n\n/* Header */\n.test-run-header {\n background: white;\n border-bottom: 1px solid #e0e0e0;\n padding: 20px;\n}\n\n.breadcrumb {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: #666;\n margin-bottom: 16px;\n}\n\n.breadcrumb a {\n color: #2196f3;\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.breadcrumb a:hover {\n text-decoration: underline;\n}\n\n.header-content {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n}\n\n.header-left {\n display: flex;\n gap: 16px;\n}\n\n.test-run-icon {\n width: 56px;\n height: 56px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 24px;\n}\n\n.test-run-info h1 {\n margin: 0 0 8px 0;\n font-size: 24px;\n font-weight: 600;\n color: #333;\n}\n\n.test-run-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 12px;\n border-radius: 12px;\n color: white;\n font-size: 12px;\n font-weight: 600;\n}\n\n.test-type {\n font-size: 14px;\n color: #666;\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n}\n\n.metrics-bar {\n display: grid;\n grid-template-columns: repeat(5, 1fr);\n gap: 16px;\n margin-bottom: 16px;\n}\n\n.metric-card {\n background: #f5f7fa;\n border-radius: 8px;\n padding: 12px;\n text-align: center;\n}\n\n.metric-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: #999;\n margin-bottom: 4px;\n}\n\n.metric-value {\n font-size: 16px;\n font-weight: 600;\n color: #333;\n}\n\n.secondary-metrics {\n display: flex;\n gap: 24px;\n padding-top: 12px;\n border-top: 1px solid #e0e0e0;\n}\n\n.metric-item {\n display: flex;\n gap: 8px;\n font-size: 14px;\n}\n\n.metric-item .metric-label {\n color: #666;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.metric-item .metric-value {\n color: #333;\n font-weight: 500;\n font-size: 14px;\n}\n\n.metric-item a {\n color: #2196f3;\n text-decoration: none;\n}\n\n.metric-item a:hover {\n text-decoration: underline;\n}\n\n/* Tabs */\n.tabs-container {\n background: white;\n border-bottom: 1px solid #e0e0e0;\n}\n\n.tabs {\n display: flex;\n padding: 0 20px;\n overflow-x: auto;\n}\n\n.tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 16px 20px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: #666;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.tab:hover {\n color: #2196f3;\n background: rgba(33, 150, 243, 0.05);\n}\n\n.tab.active {\n color: #2196f3;\n border-bottom-color: #2196f3;\n}\n\n.tab i {\n font-size: 16px;\n}\n\n.tab-badge {\n background: #e0e0e0;\n color: #666;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active .tab-badge {\n background: #e3f2fd;\n color: #2196f3;\n}\n\n/* Tab Content */\n.tab-content {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n/* Overview Tab */\n.overview-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.result-hero {\n background: white;\n border-radius: 12px;\n padding: 32px;\n text-align: center;\n border: 3px solid #e0e0e0;\n}\n\n.result-hero.passed {\n background: #e8f5e9;\n border-color: #4caf50;\n}\n\n.result-hero.failed {\n background: #ffebee;\n border-color: #f44336;\n}\n\n.result-icon {\n font-size: 64px;\n margin-bottom: 16px;\n}\n\n.result-hero.passed .result-icon {\n color: #4caf50;\n}\n\n.result-hero.failed .result-icon {\n color: #f44336;\n}\n\n.result-text h2 {\n margin: 0 0 12px 0;\n font-size: 32px;\n font-weight: 700;\n color: #333;\n}\n\n.result-score {\n font-size: 20px;\n font-weight: 600;\n color: #666;\n margin-bottom: 8px;\n}\n\n.result-checks {\n font-size: 16px;\n color: #999;\n}\n\n.check-results {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.check-results h3 {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #333;\n}\n\n.check-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.check-item {\n display: flex;\n gap: 12px;\n padding: 12px;\n border-radius: 8px;\n border: 2px solid #e0e0e0;\n}\n\n.check-item.passed {\n background: #f1f8f4;\n border-color: #c8e6c9;\n}\n\n.check-item.failed {\n background: #fef5f5;\n border-color: #ffcdd2;\n}\n\n.check-icon {\n font-size: 20px;\n flex-shrink: 0;\n}\n\n.check-item.passed .check-icon {\n color: #4caf50;\n}\n\n.check-item.failed .check-icon {\n color: #f44336;\n}\n\n.check-content {\n flex: 1;\n}\n\n.check-name {\n font-size: 14px;\n font-weight: 600;\n color: #333;\n margin-bottom: 4px;\n}\n\n.check-details {\n font-size: 13px;\n color: #666;\n line-height: 1.4;\n}\n\n.check-weight {\n font-size: 12px;\n color: #999;\n margin-top: 4px;\n}\n\n.comparison-section {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.comparison-section h3 {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #333;\n}\n\n.comparison-tabs {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n border-bottom: 2px solid #e0e0e0;\n}\n\n.comparison-tab {\n padding: 10px 20px;\n border: none;\n background: transparent;\n color: #666;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n border-bottom: 3px solid transparent;\n margin-bottom: -2px;\n transition: all 0.2s ease;\n}\n\n.comparison-tab:hover {\n color: #2196f3;\n}\n\n.comparison-tab.active {\n color: #2196f3;\n border-bottom-color: #2196f3;\n}\n\n.comparison-content {\n background: #1e1e1e;\n border-radius: 8px;\n padding: 16px;\n max-height: 400px;\n overflow-y: auto;\n}\n\n.comparison-content pre {\n margin: 0;\n font-family: 'Courier New', monospace;\n font-size: 13px;\n line-height: 1.5;\n color: #e0e0e0;\n white-space: pre-wrap;\n word-wrap: break-word;\n}\n\n/* Details Tab */\n.details-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.details-grid {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.detail-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-label {\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: #999;\n}\n\n.detail-value {\n font-size: 14px;\n color: #333;\n word-wrap: break-word;\n}\n\n.detail-value a {\n color: #2196f3;\n text-decoration: none;\n}\n\n.detail-value a:hover {\n text-decoration: underline;\n}\n\n.error-message, .result-details-json {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.error-message h4, .result-details-json h4 {\n margin: 0 0 12px 0;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n}\n\n.error-message pre, .result-details-json pre {\n margin: 0;\n font-family: 'Courier New', monospace;\n font-size: 13px;\n line-height: 1.5;\n color: #333;\n white-space: pre-wrap;\n word-wrap: break-word;\n background: #f5f7fa;\n padding: 16px;\n border-radius: 8px;\n}\n\n/* AI Runs Tab */\n.ai-runs-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.ai-runs-section {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.ai-runs-section h3 {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #333;\n}\n\n.ai-run-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.ai-run-card {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: #f8f9fa;\n border: 2px solid transparent;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.ai-run-card:hover {\n background: #e3f2fd;\n border-color: #90caf9;\n}\n\n.ai-run-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #2196f3;\n color: white;\n border-radius: 8px;\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.ai-run-icon.prompt {\n background: #9c27b0;\n}\n\n.ai-run-content {\n flex: 1;\n}\n\n.ai-run-name {\n font-size: 14px;\n font-weight: 600;\n color: #333;\n margin-bottom: 4px;\n}\n\n.ai-run-meta {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: #666;\n}\n\n.ai-run-card > i {\n color: #999;\n font-size: 14px;\n}\n\n/* Feedback Tab */\n.feedback-tab {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.feedback-list {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.feedback-item {\n padding: 16px;\n background: #f8f9fa;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n}\n\n.feedback-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.feedback-user {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n}\n\n.feedback-date {\n font-size: 12px;\n color: #999;\n}\n\n.feedback-rating {\n font-size: 14px;\n color: #666;\n margin-bottom: 8px;\n}\n\n.feedback-correct {\n font-size: 14px;\n color: #666;\n margin-bottom: 8px;\n}\n\n.feedback-comments {\n font-size: 14px;\n line-height: 1.5;\n color: #333;\n padding: 12px;\n background: white;\n border-radius: 6px;\n border-left: 3px solid #2196f3;\n}\n\n/* No Data State */\n.no-data {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n color: #999;\n text-align: center;\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/* Responsive */\n@media (max-width: 1200px) {\n .metrics-bar {\n grid-template-columns: repeat(3, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .metrics-bar {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .details-grid {\n grid-template-columns: 1fr;\n }\n\n .header-content {\n flex-direction: column;\n gap: 16px;\n }\n\n .tabs {\n overflow-x: auto;\n }\n}\n"] }]
|
|
915
|
-
}], () => [{ type: i0.ElementRef }, { type: i1.SharedService }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: i0.ChangeDetectorRef }],
|
|
916
|
-
|
|
1564
|
+
args: [{ selector: 'mj-test-run-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"test-run-form\" [class.is-mobile]=\"false\">\n <!-- Error State -->\n <div class=\"error-banner\" *ngIf=\"error\" (click)=\"retryLoad()\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <span>{{ error }}</span>\n <button class=\"retry-btn\">\n <i class=\"fas fa-redo\"></i> Retry\n </button>\n </div>\n\n <!-- Header Section -->\n <div class=\"test-run-header\" [class]=\"getStatusClass()\">\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 *ngIf=\"test\">\n <i class=\"fas fa-chevron-right separator\"></i>\n <a href=\"javascript:void(0)\" (click)=\"openTest()\">\n <i class=\"fas fa-flask\"></i>\n <span class=\"breadcrumb-text\">{{ test.Name }}</span>\n </a>\n </li>\n <li class=\"current\">\n <i class=\"fas fa-chevron-right separator\"></i>\n <span>Run #{{ record.ID.substring(0, 8) }}</span>\n </li>\n </ol>\n </nav>\n\n <div class=\"header-content\">\n <div class=\"header-left\">\n <!-- Status Indicator -->\n <div class=\"status-indicator\" [style.background-color]=\"getStatusColor()\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon()\"></i>\n </div>\n\n <div class=\"test-run-info\">\n <h1>\n Test Run\n <span class=\"run-id\">#{{ record.ID.substring(0, 8) }}</span>\n </h1>\n <div class=\"test-run-meta\">\n <span class=\"status-badge\" [style.background-color]=\"getStatusColor()\">\n {{ record.Status }}\n </span>\n <span class=\"meta-item\" *ngIf=\"test\">\n <i class=\"fas fa-flask\"></i>\n {{ test.Type }}\n </span>\n <span class=\"meta-item\" *ngIf=\"autoRefreshEnabled\">\n <i class=\"fas fa-sync-alt fa-spin\"></i>\n Auto-refreshing\n </span>\n </div>\n </div>\n </div>\n\n <div class=\"header-actions\">\n <button kendoButton (click)=\"reRunTest()\" [disabled]=\"!record.TestID\" title=\"Re-run this test (Cmd+Shift+R)\">\n <i class=\"fas fa-redo\"></i>\n <span class=\"btn-text\">Re-run</span>\n </button>\n <button kendoButton (click)=\"refresh()\" [disabled]=\"isRefreshing\" title=\"Refresh (Cmd+R)\">\n <i class=\"fas fa-sync-alt\" [class.fa-spin]=\"isRefreshing\"></i>\n <span class=\"btn-text\">Refresh</span>\n </button>\n </div>\n </div>\n\n <!-- Metrics Bar -->\n <div class=\"metrics-bar\">\n <div class=\"metric-card\">\n <div class=\"metric-icon\">\n <i class=\"fas fa-clock\"></i>\n </div>\n <div class=\"metric-content\">\n <div class=\"metric-label\">Started</div>\n <div class=\"metric-value\">{{ getRelativeTime(record.StartedAt) }}</div>\n <div class=\"metric-detail\">{{ record.StartedAt | date:'short' }}</div>\n </div>\n </div>\n\n <div class=\"metric-card\">\n <div class=\"metric-icon\">\n <i class=\"fas fa-stopwatch\"></i>\n </div>\n <div class=\"metric-content\">\n <div class=\"metric-label\">Duration</div>\n <div class=\"metric-value\">{{ calculateDuration() }}</div>\n </div>\n </div>\n\n <div class=\"metric-card\">\n <div class=\"metric-icon\">\n <i class=\"fas fa-star\"></i>\n </div>\n <div class=\"metric-content\">\n <div class=\"metric-label\">Score</div>\n <div class=\"metric-value\">{{ formatScore(record.Score) }}</div>\n <div class=\"metric-progress\" *ngIf=\"record.Score != null\">\n <div class=\"progress-bar\" [style.width.%]=\"getScorePercentage()\" [style.background-color]=\"getStatusColor()\"></div>\n </div>\n </div>\n </div>\n\n <div class=\"metric-card\">\n <div class=\"metric-icon\">\n <i class=\"fas fa-check-double\"></i>\n </div>\n <div class=\"metric-content\">\n <div class=\"metric-label\">Checks</div>\n <div class=\"metric-value\">{{ record.PassedChecks }}/{{ record.TotalChecks }}</div>\n <div class=\"metric-progress\" *ngIf=\"record.TotalChecks\">\n <div class=\"progress-bar\" [style.width.%]=\"getPassRatePercentage()\" [style.background-color]=\"getStatusColor()\"></div>\n </div>\n </div>\n </div>\n\n <div class=\"metric-card\">\n <div class=\"metric-icon\">\n <i class=\"fas fa-dollar-sign\"></i>\n </div>\n <div class=\"metric-content\">\n <div class=\"metric-label\">Cost</div>\n <div class=\"metric-value\">{{ formatCost(record.CostUSD) }}</div>\n </div>\n </div>\n </div>\n\n <!-- Secondary Info -->\n <div class=\"secondary-info\" *ngIf=\"record.RunByUser || testSuiteRun || record.TargetLogEntityID\">\n <span class=\"info-chip\" *ngIf=\"record.RunByUser\">\n <i class=\"fas fa-user\"></i>\n {{ record.RunByUser }}\n </span>\n <span class=\"info-chip clickable\" *ngIf=\"testSuiteRun\" (click)=\"openTestSuiteRun()\">\n <i class=\"fas fa-layer-group\"></i>\n Part of Suite Run (Seq: {{ record.Sequence }})\n </span>\n <!-- Target Entity Link Pill -->\n <mj-entity-link-pill\n *ngIf=\"record.TargetLogEntityID && record.TargetLogID\"\n [entityName]=\"record.TargetLogEntity\"\n [recordId]=\"record.TargetLogID\">\n </mj-entity-link-pill>\n </div>\n\n <!-- Tags Section - Sleek inline design -->\n <div class=\"tags-bar\" *ngIf=\"!editingTags\">\n <div class=\"tags-bar-content\">\n <span class=\"tags-bar-label\"><i class=\"fas fa-tags\"></i></span>\n <div class=\"tags-bar-chips\" *ngIf=\"tags.length > 0\">\n <span class=\"tag-inline\" *ngFor=\"let tag of tags\">{{ tag }}</span>\n </div>\n <span class=\"tags-bar-empty\" *ngIf=\"tags.length === 0\">No tags</span>\n <button class=\"tags-bar-edit\" (click)=\"startEditingTags()\" title=\"Edit tags\">\n <i class=\"fas fa-plus\"></i> Add\n </button>\n </div>\n </div>\n\n <!-- Tags Editor - Expanded when editing -->\n <div class=\"tags-editor-panel\" *ngIf=\"editingTags\">\n <div class=\"tags-editor-header\">\n <span class=\"tags-editor-title\"><i class=\"fas fa-tags\"></i> Edit Tags</span>\n </div>\n <div class=\"tags-editor-body\">\n <div class=\"tags-editor-chips\">\n <span class=\"tag-editable\" *ngFor=\"let tag of tags\">\n {{ tag }}\n <button class=\"tag-remove-btn\" (click)=\"removeTag(tag)\" title=\"Remove tag\">\n <i class=\"fas fa-times\"></i>\n </button>\n </span>\n <span class=\"tags-empty-hint\" *ngIf=\"tags.length === 0\">No tags yet</span>\n </div>\n <div class=\"tags-editor-input\">\n <input type=\"text\"\n [(ngModel)]=\"newTag\"\n placeholder=\"Type a tag and press Enter...\"\n (keyup.enter)=\"addTag()\"\n class=\"tag-text-input\" />\n <button kendoButton (click)=\"addTag()\" [disabled]=\"!newTag.trim()\" fillMode=\"flat\">\n <i class=\"fas fa-plus\"></i>\n </button>\n </div>\n </div>\n <div class=\"tags-editor-footer\">\n <button kendoButton (click)=\"saveTags()\" themeColor=\"primary\" [disabled]=\"savingTags\">\n <i class=\"fas fa-spinner fa-spin\" *ngIf=\"savingTags\"></i>\n {{ savingTags ? 'Saving...' : 'Save' }}\n </button>\n <button kendoButton (click)=\"cancelEditingTags()\" fillMode=\"flat\">Cancel</button>\n </div>\n </div>\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs-container\">\n <div class=\"tabs\" role=\"tablist\">\n <button class=\"tab\" [class.active]=\"activeTab === 'overview'\" (click)=\"changeTab('overview')\"\n role=\"tab\" [attr.aria-selected]=\"activeTab === 'overview'\" title=\"Press 1\">\n <i class=\"fas fa-chart-pie\"></i>\n <span>Overview</span>\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'details'\" (click)=\"changeTab('details')\"\n role=\"tab\" [attr.aria-selected]=\"activeTab === 'details'\" title=\"Press 2\">\n <i class=\"fas fa-info-circle\"></i>\n <span>Details</span>\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'ai-runs'\" (click)=\"changeTab('ai-runs')\"\n role=\"tab\" [attr.aria-selected]=\"activeTab === 'ai-runs'\" title=\"Press 3\">\n <i class=\"fas fa-robot\"></i>\n <span>AI Runs</span>\n <span class=\"tab-badge\" *ngIf=\"aiRunsLoaded\">{{ aiAgentRuns.length + aiPromptRuns.length }}</span>\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'feedback'\" (click)=\"changeTab('feedback')\"\n role=\"tab\" [attr.aria-selected]=\"activeTab === 'feedback'\" title=\"Press 4\">\n <i class=\"fas fa-comments\"></i>\n <span>Feedback</span>\n <span class=\"tab-badge\" *ngIf=\"feedbackLoaded\">{{ feedbacks.length }}</span>\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'execution'\" (click)=\"changeTab('execution')\"\n role=\"tab\" [attr.aria-selected]=\"activeTab === 'execution'\" title=\"Press 5\">\n <i class=\"fas fa-microchip\"></i>\n <span>Execution</span>\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'log'\" (click)=\"changeTab('log')\" *ngIf=\"record.Log\"\n role=\"tab\" [attr.aria-selected]=\"activeTab === 'log'\" title=\"Press 6\">\n <i class=\"fas fa-terminal\"></i>\n <span>Log</span>\n </button>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tab-content\">\n <!-- Overview Tab -->\n <div class=\"overview-tab\" *ngIf=\"activeTab === 'overview'\" [@fadeIn]>\n <!-- Result Hero -->\n <div class=\"result-hero\" [class]=\"getStatusClass()\">\n <div class=\"result-icon-wrapper\">\n <div class=\"result-icon\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon()\"></i>\n </div>\n <div class=\"result-pulse\" *ngIf=\"record.Status === 'Running'\"></div>\n </div>\n <div class=\"result-text\">\n <h2>TEST {{ record.Status.toUpperCase() }}</h2>\n <div class=\"result-details\">\n <span class=\"result-score\">Score: {{ formatScore(record.Score) }}</span>\n <span class=\"result-divider\">|</span>\n <span class=\"result-checks\">{{ record.PassedChecks }} of {{ record.TotalChecks }} checks passed</span>\n </div>\n </div>\n </div>\n\n <!-- Check Results -->\n <div class=\"check-results\" *ngIf=\"getCheckResults().length > 0\">\n <div class=\"section-header\">\n <h3><i class=\"fas fa-tasks\"></i> Check Results</h3>\n <span class=\"check-summary\">{{ record.PassedChecks }} passed, {{ record.FailedChecks }} failed</span>\n </div>\n <div class=\"check-list\">\n <div class=\"check-item\" *ngFor=\"let check of getCheckResults(); let i = index\"\n [class.passed]=\"check.passed\" [class.failed]=\"!check.passed\"\n [style.animation-delay.ms]=\"i * 50\">\n <div class=\"check-status\">\n <i class=\"fas\" [class.fa-check-circle]=\"check.passed\" [class.fa-times-circle]=\"!check.passed\"></i>\n </div>\n <div class=\"check-content\">\n <div class=\"check-name\">{{ check.name }}</div>\n <div class=\"check-message\" *ngIf=\"check.message\">{{ check.message }}</div>\n </div>\n <div class=\"check-weight\" *ngIf=\"check.weight\">\n <span class=\"weight-label\">Weight:</span> {{ check.weight }}\n </div>\n </div>\n </div>\n </div>\n\n <!-- Data Comparison -->\n <div class=\"comparison-section\">\n <div class=\"section-header\">\n <h3><i class=\"fas fa-exchange-alt\"></i> Data Comparison</h3>\n </div>\n <div class=\"comparison-tabs\">\n <button class=\"comparison-tab\" [class.active]=\"comparisonView === 'input'\" (click)=\"setComparisonView('input')\">\n <i class=\"fas fa-sign-in-alt\"></i> Input\n </button>\n <button class=\"comparison-tab\" [class.active]=\"comparisonView === 'expected'\" (click)=\"setComparisonView('expected')\">\n <i class=\"fas fa-bullseye\"></i> Expected\n </button>\n <button class=\"comparison-tab\" [class.active]=\"comparisonView === 'actual'\" (click)=\"setComparisonView('actual')\">\n <i class=\"fas fa-check-square\"></i> Actual\n </button>\n </div>\n <div class=\"comparison-content\">\n <mj-code-editor\n [value]=\"getComparisonData()\"\n language=\"json\"\n [readonly]=\"true\"\n [toolbar]=\"jsonToolbar\"\n [lineWrapping]=\"true\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n\n <!-- Details Tab -->\n <div class=\"details-tab\" *ngIf=\"activeTab === 'details'\" [@fadeIn]>\n <div class=\"details-grid\">\n <div class=\"detail-card\">\n <div class=\"detail-icon\"><i class=\"fas fa-fingerprint\"></i></div>\n <div class=\"detail-content\">\n <div class=\"detail-label\">Test Run ID</div>\n <div class=\"detail-value monospace\">{{ record.ID }}</div>\n </div>\n </div>\n\n <div class=\"detail-card clickable\" *ngIf=\"test\" (click)=\"openTest()\">\n <div class=\"detail-icon\"><i class=\"fas fa-flask\"></i></div>\n <div class=\"detail-content\">\n <div class=\"detail-label\">Test</div>\n <div class=\"detail-value link\">{{ test.Name }}</div>\n </div>\n <i class=\"fas fa-external-link-alt detail-action\"></i>\n </div>\n\n <div class=\"detail-card\">\n <div class=\"detail-icon\"><i class=\"fas fa-tag\"></i></div>\n <div class=\"detail-content\">\n <div class=\"detail-label\">Target Type</div>\n <div class=\"detail-value\">{{ record.TargetType || 'N/A' }}</div>\n </div>\n </div>\n\n <div class=\"detail-card\">\n <div class=\"detail-icon\"><i class=\"fas fa-play-circle\"></i></div>\n <div class=\"detail-content\">\n <div class=\"detail-label\">Started At</div>\n <div class=\"detail-value\">{{ record.StartedAt | date:'medium' }}</div>\n </div>\n </div>\n\n <div class=\"detail-card\">\n <div class=\"detail-icon\"><i class=\"fas fa-stop-circle\"></i></div>\n <div class=\"detail-content\">\n <div class=\"detail-label\">Completed At</div>\n <div class=\"detail-value\">{{ record.CompletedAt | date:'medium' }}</div>\n </div>\n </div>\n\n <div class=\"detail-card\">\n <div class=\"detail-icon\"><i class=\"fas fa-hourglass-half\"></i></div>\n <div class=\"detail-content\">\n <div class=\"detail-label\">Duration</div>\n <div class=\"detail-value\">{{ calculateDuration() }}</div>\n </div>\n </div>\n </div>\n\n <!-- Error Message -->\n <div class=\"error-section\" *ngIf=\"record.ErrorMessage\">\n <div class=\"section-header error\">\n <h3><i class=\"fas fa-exclamation-triangle\"></i> Error Message</h3>\n </div>\n <div class=\"error-content\">\n <mj-code-editor\n [value]=\"record.ErrorMessage\"\n [readonly]=\"true\"\n [toolbar]=\"jsonToolbar\"\n [lineWrapping]=\"true\">\n </mj-code-editor>\n </div>\n </div>\n\n <!-- Result Details -->\n <div class=\"result-details-section\" *ngIf=\"parsedData.resultDetails\">\n <div class=\"section-header\">\n <h3><i class=\"fas fa-file-code\"></i> Result Details</h3>\n </div>\n <div class=\"result-details-content\">\n <mj-code-editor\n [value]=\"getFormattedResultDetails()\"\n language=\"json\"\n [readonly]=\"true\"\n [toolbar]=\"jsonToolbar\"\n [lineWrapping]=\"true\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n\n <!-- AI Runs Tab -->\n <div class=\"ai-runs-tab\" *ngIf=\"activeTab === 'ai-runs'\" [@fadeIn]>\n <!-- Loading State -->\n <div class=\"loading-state\" *ngIf=\"loadingAIRuns\">\n <div class=\"skeleton-list\">\n <div class=\"skeleton-card\" *ngFor=\"let i of [1,2,3]\">\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 </div>\n </div>\n\n <!-- AI Agent Runs -->\n <div class=\"ai-section\" *ngIf=\"!loadingAIRuns && aiAgentRuns.length > 0\">\n <div class=\"section-header\">\n <h3><i class=\"fas fa-robot\"></i> AI Agent Runs</h3>\n <span class=\"count-badge\">{{ aiAgentRuns.length }}</span>\n </div>\n <div class=\"ai-run-list\">\n <div class=\"ai-run-card\" *ngFor=\"let run of aiAgentRuns\" (click)=\"openAIAgentRun(run.ID)\">\n <div class=\"ai-run-icon agent\">\n <i class=\"fas fa-robot\"></i>\n </div>\n <div class=\"ai-run-content\">\n <div class=\"ai-run-name\">{{ run.Agent }}</div>\n <div class=\"ai-run-meta\">\n <span class=\"status-chip\" [class]=\"run.Status.toLowerCase()\">{{ run.Status }}</span>\n <span *ngIf=\"run.TotalCost\" class=\"cost-chip\">\n <i class=\"fas fa-dollar-sign\"></i> {{ run.TotalCost | number:'1.4-4' }}\n </span>\n </div>\n </div>\n <i class=\"fas fa-chevron-right ai-run-arrow\"></i>\n </div>\n </div>\n </div>\n\n <!-- AI Prompt Runs -->\n <div class=\"ai-section\" *ngIf=\"!loadingAIRuns && aiPromptRuns.length > 0\">\n <div class=\"section-header\">\n <h3><i class=\"fas fa-comment-dots\"></i> AI Prompt Runs</h3>\n <span class=\"count-badge\">{{ aiPromptRuns.length }}</span>\n </div>\n <div class=\"ai-run-list\">\n <div class=\"ai-run-card\" *ngFor=\"let run of aiPromptRuns\" (click)=\"openAIPromptRun(run.ID)\">\n <div class=\"ai-run-icon prompt\">\n <i class=\"fas fa-comment-dots\"></i>\n </div>\n <div class=\"ai-run-content\">\n <div class=\"ai-run-name\">{{ run.Prompt || run.Model }}</div>\n <div class=\"ai-run-meta\">\n <span *ngIf=\"run.TotalCost\" class=\"cost-chip\">\n <i class=\"fas fa-dollar-sign\"></i> {{ run.TotalCost | number:'1.4-4' }}\n </span>\n </div>\n </div>\n <i class=\"fas fa-chevron-right ai-run-arrow\"></i>\n </div>\n </div>\n </div>\n\n <!-- Empty State -->\n <div class=\"empty-state\" *ngIf=\"aiRunsLoaded && aiAgentRuns.length === 0 && aiPromptRuns.length === 0\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-robot\"></i>\n </div>\n <h3>No AI Runs</h3>\n <p>This test execution didn't involve any AI agent or prompt runs.</p>\n </div>\n </div>\n\n <!-- Feedback Tab -->\n <div class=\"feedback-tab\" *ngIf=\"activeTab === 'feedback'\" [@fadeIn]>\n <!-- Loading State -->\n <div class=\"loading-state\" *ngIf=\"loadingFeedback\">\n <div class=\"skeleton-list\">\n <div class=\"skeleton-card\" *ngFor=\"let i of [1,2]\">\n <div class=\"skeleton-avatar\"></div>\n <div class=\"skeleton-content\">\n <div class=\"skeleton-line wide\"></div>\n <div class=\"skeleton-line narrow\"></div>\n <div class=\"skeleton-line medium\"></div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Feedback List -->\n <div class=\"feedback-list\" *ngIf=\"!loadingFeedback && feedbacks.length > 0\">\n <div class=\"feedback-item\" *ngFor=\"let feedback of feedbacks\">\n <div class=\"feedback-header\">\n <div class=\"feedback-user\">\n <div class=\"user-avatar\">\n <i class=\"fas fa-user\"></i>\n </div>\n <span class=\"user-name\">{{ feedback.ReviewerUser }}</span>\n </div>\n <div class=\"feedback-date\">\n {{ getRelativeTime(feedback.__mj_CreatedAt) }}\n </div>\n </div>\n <div class=\"feedback-body\">\n <div class=\"feedback-rating\">\n <div class=\"rating-stars\">\n <i class=\"fas fa-star\" *ngFor=\"let s of [1,2,3,4,5,6,7,8,9,10]\"\n [class.filled]=\"s <= (feedback.Rating || 0)\"></i>\n </div>\n <span class=\"rating-value\">{{ feedback.Rating }}/10</span>\n </div>\n <div class=\"feedback-verdict\" *ngIf=\"feedback.IsCorrect !== null\">\n <span class=\"verdict-badge\" [class.correct]=\"feedback.IsCorrect\" [class.incorrect]=\"!feedback.IsCorrect\">\n <i class=\"fas\" [class.fa-check]=\"feedback.IsCorrect\" [class.fa-times]=\"!feedback.IsCorrect\"></i>\n {{ feedback.IsCorrect ? 'Marked Correct' : 'Marked Incorrect' }}\n </span>\n </div>\n <div class=\"feedback-comments\" *ngIf=\"feedback.CorrectionSummary\">\n <p>{{ feedback.CorrectionSummary }}</p>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Empty State -->\n <div class=\"empty-state\" *ngIf=\"feedbackLoaded && feedbacks.length === 0\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-comments\"></i>\n </div>\n <h3>No Feedback Yet</h3>\n <p>No one has reviewed this test run yet. Be the first to provide feedback!</p>\n </div>\n </div>\n\n <!-- Execution Context Tab -->\n <div class=\"execution-tab\" *ngIf=\"activeTab === 'execution'\" [@fadeIn]>\n <mj-execution-context\n [machineName]=\"record.MachineName\"\n [machineId]=\"record.MachineID\"\n [runByUserName]=\"record.RunByUserName\"\n [runByUserEmail]=\"record.RunByUserEmail\"\n [runContextDetailsJson]=\"record.RunContextDetails\">\n </mj-execution-context>\n </div>\n\n <!-- Execution Log Tab -->\n <div class=\"log-tab\" *ngIf=\"activeTab === 'log'\" [@fadeIn]>\n <div class=\"log-header\">\n <div class=\"log-title\">\n <i class=\"fas fa-terminal\"></i>\n <h3>Execution Log</h3>\n </div>\n <div class=\"log-actions\">\n <button kendoButton (click)=\"copyLogToClipboard()\" look=\"flat\">\n <i class=\"fas fa-copy\"></i>\n <span class=\"btn-text\">Copy</span>\n </button>\n </div>\n </div>\n <div class=\"log-container\">\n <mj-code-editor\n [value]=\"record.Log || ''\"\n [readonly]=\"true\"\n [toolbar]=\"jsonToolbar\"\n [lineWrapping]=\"true\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n\n <!-- Keyboard Shortcuts Help (shown on hover of ? icon) -->\n <div class=\"shortcuts-hint\" title=\"Keyboard Shortcuts\">\n <i class=\"fas fa-keyboard\"></i>\n <div class=\"shortcuts-popup\">\n <h4>Keyboard Shortcuts</h4>\n <ul>\n <li><kbd>1-6</kbd> Switch tabs</li>\n <li><kbd>Cmd+R</kbd> Refresh</li>\n <li><kbd>Cmd+Shift+R</kbd> Re-run test</li>\n </ul>\n </div>\n </div>\n</div>\n", styles: ["/* ===========================\n Test Run Form - World-Class UX\n Premium Testing Dashboard Styles\n =========================== */\n\n/* CSS Custom Properties for Theming - using :host for Angular encapsulation */\n:host {\n --test-primary: #2563eb;\n --test-primary-light: #3b82f6;\n --test-primary-dark: #1d4ed8;\n --test-success: #10b981;\n --test-success-light: #d1fae5;\n --test-error: #ef4444;\n --test-error-light: #fee2e2;\n --test-warning: #f59e0b;\n --test-warning-light: #fef3c7;\n --test-timeout: #f97316;\n --test-timeout-light: #ffedd5;\n --test-running: #3b82f6;\n --test-pending: #8b5cf6;\n --test-skipped: #6b7280;\n --test-bg: #f8fafc;\n --test-surface: #ffffff;\n --test-border: #e2e8f0;\n --test-text: #1e293b;\n --test-text-secondary: #64748b;\n --test-text-muted: #94a3b8;\n --test-radius-sm: 6px;\n --test-radius-md: 10px;\n --test-radius-lg: 16px;\n --test-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);\n --test-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n --test-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n --test-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: block;\n height: 100%;\n}\n\n/* Base Container */\n.test-run-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 Error Banner\n =========================== */\n.error-banner {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 12px 20px;\n background: linear-gradient(135deg, var(--test-error) 0%, #dc2626 100%);\n color: white;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n animation: slideDown 0.3s ease-out;\n}\n\n.error-banner:hover {\n background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);\n}\n\n.error-banner i {\n font-size: 16px;\n}\n\n.retry-btn {\n background: rgba(255, 255, 255, 0.2);\n border: 1px solid rgba(255, 255, 255, 0.3);\n color: white;\n padding: 6px 12px;\n border-radius: var(--test-radius-sm);\n cursor: pointer;\n font-size: 12px;\n font-weight: 600;\n transition: var(--test-transition);\n}\n\n.retry-btn:hover {\n background: rgba(255, 255, 255, 0.3);\n}\n\n@keyframes slideDown {\n from {\n transform: translateY(-100%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n/* ===========================\n Header Section\n =========================== */\n.test-run-header {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n padding: 20px;\n position: relative;\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 flex-wrap: wrap;\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: var(--test-radius-sm);\n transition: var(--test-transition);\n}\n\n.breadcrumb a:hover {\n background: rgba(37, 99, 235, 0.1);\n text-decoration: none;\n}\n\n.breadcrumb .separator {\n font-size: 10px;\n color: var(--test-text-muted);\n margin: 0 4px;\n}\n\n.breadcrumb .current {\n color: var(--test-text-secondary);\n font-weight: 500;\n}\n\n.breadcrumb-text {\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Header Content */\n.header-content {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n gap: 16px;\n}\n\n.header-left {\n display: flex;\n gap: 16px;\n flex: 1;\n min-width: 0;\n}\n\n/* Status Indicator */\n.status-indicator {\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: white;\n font-size: 24px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.status-indicator:hover {\n transform: scale(1.05);\n}\n\n/* Test Run Info */\n.test-run-info {\n flex: 1;\n min-width: 0;\n}\n\n.test-run-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-run-info h1 .run-id {\n color: var(--test-text-secondary);\n font-weight: 500;\n}\n\n.test-run-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: white;\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/* Meta Item */\n.meta-item {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n color: var(--test-text-secondary);\n}\n\n.meta-item i {\n font-size: 12px;\n}\n\n/* Header Actions */\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.btn-text {\n margin-left: 6px;\n}\n\n/* ===========================\n Metrics Bar\n =========================== */\n.metrics-bar {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 12px;\n margin-bottom: 16px;\n}\n\n.metric-card {\n display: flex;\n align-items: center;\n gap: 12px;\n background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 14px;\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-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-surface);\n border-radius: var(--test-radius-sm);\n color: var(--test-primary);\n font-size: 16px;\n flex-shrink: 0;\n}\n\n.metric-content {\n flex: 1;\n min-width: 0;\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: 4px;\n}\n\n.metric-value {\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.metric-detail {\n font-size: 11px;\n color: var(--test-text-muted);\n margin-top: 2px;\n}\n\n/* Progress bar in metric card */\n.metric-progress {\n margin-top: 6px;\n height: 4px;\n background: var(--test-border);\n border-radius: 2px;\n overflow: hidden;\n}\n\n.progress-bar {\n height: 100%;\n border-radius: 2px;\n transition: width 0.5s ease-out;\n}\n\n/* Secondary Info */\n.secondary-info {\n display: flex;\n gap: 12px;\n padding-top: 16px;\n border-top: 1px solid var(--test-border);\n flex-wrap: wrap;\n}\n\n.info-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--test-text-secondary);\n padding: 6px 12px;\n background: var(--test-bg);\n border-radius: 20px;\n transition: var(--test-transition);\n}\n\n.info-chip i {\n font-size: 12px;\n}\n\n.info-chip.clickable {\n cursor: pointer;\n}\n\n.info-chip.clickable:hover {\n background: rgba(37, 99, 235, 0.1);\n color: var(--test-primary);\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 position: relative;\n}\n\n.tab:hover {\n color: var(--test-primary);\n background: rgba(37, 99, 235, 0.05);\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: rgba(37, 99, 235, 0.15);\n color: var(--test-primary);\n}\n\n.shortcut-hint {\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 font-family: -apple-system, BlinkMacSystemFont, sans-serif;\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/* Result Hero Card */\n.result-hero {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 32px;\n text-align: center;\n border: 2px solid var(--test-border);\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.result-hero.passed {\n background: linear-gradient(135deg, #ecfdf5 0%, var(--test-success-light) 100%);\n border-color: var(--test-success);\n}\n\n.result-hero.failed {\n background: linear-gradient(135deg, #fef2f2 0%, var(--test-error-light) 100%);\n border-color: var(--test-error);\n}\n\n.result-hero.error {\n background: linear-gradient(135deg, #fffbeb 0%, var(--test-warning-light) 100%);\n border-color: var(--test-warning);\n}\n\n.result-hero.timeout {\n background: linear-gradient(135deg, #fff7ed 0%, var(--test-timeout-light) 100%);\n border-color: var(--test-timeout);\n}\n\n.result-hero.running,\n.result-hero.pending {\n background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);\n border-color: var(--test-primary-light);\n}\n\n.result-icon-wrapper {\n position: relative;\n display: inline-block;\n margin-bottom: 16px;\n}\n\n.result-icon {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-surface);\n border-radius: 50%;\n font-size: 40px;\n margin: 0 auto;\n box-shadow: var(--test-shadow-md);\n}\n\n.result-hero.passed .result-icon { color: var(--test-success); }\n.result-hero.failed .result-icon { color: var(--test-error); }\n.result-hero.error .result-icon { color: var(--test-warning); }\n.result-hero.timeout .result-icon { color: var(--test-timeout); }\n.result-hero.running .result-icon,\n.result-hero.pending .result-icon { color: var(--test-primary); }\n\n.result-pulse {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 100px;\n height: 100px;\n border-radius: 50%;\n background: rgba(59, 130, 246, 0.2);\n animation: pulse 2s ease-in-out infinite;\n}\n\n@keyframes pulse {\n 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.5; }\n 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0; }\n}\n\n.result-text h2 {\n margin: 0 0 12px 0;\n font-size: clamp(24px, 5vw, 32px);\n font-weight: 800;\n color: var(--test-text);\n}\n\n.result-details {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.result-score {\n font-size: 18px;\n font-weight: 600;\n color: var(--test-text-secondary);\n}\n\n.result-divider {\n color: var(--test-border);\n}\n\n.result-checks {\n font-size: 16px;\n color: var(--test-text-muted);\n}\n\n/* Section Headers */\n.section-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 16px;\n gap: 12px;\n}\n\n.section-header h3 {\n margin: 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.section-header h3 i {\n color: var(--test-primary);\n}\n\n.section-header.error h3 i {\n color: var(--test-error);\n}\n\n.check-summary {\n font-size: 13px;\n color: var(--test-text-secondary);\n}\n\n/* Check Results Section */\n.check-results {\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.check-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.check-item {\n display: flex;\n gap: 12px;\n padding: 14px 16px;\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n transition: var(--test-transition);\n animation: fadeIn 0.3s ease-out backwards;\n}\n\n.check-item:hover {\n transform: translateX(4px);\n}\n\n.check-item.passed {\n background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);\n border-color: #86efac;\n}\n\n.check-item.failed {\n background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%);\n border-color: #fca5a5;\n}\n\n.check-status {\n font-size: 20px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.check-item.passed .check-status { color: var(--test-success); }\n.check-item.failed .check-status { color: var(--test-error); }\n\n.check-content {\n flex: 1;\n min-width: 0;\n}\n\n.check-name {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.check-message {\n font-size: 13px;\n color: var(--test-text-secondary);\n line-height: 1.5;\n word-wrap: break-word;\n}\n\n.check-weight {\n font-size: 12px;\n color: var(--test-text-muted);\n flex-shrink: 0;\n text-align: right;\n}\n\n.weight-label {\n font-weight: 500;\n}\n\n/* Comparison Section */\n.comparison-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.comparison-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}\n\n.comparison-tab {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 10px 16px;\n border: none;\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n border-radius: var(--test-radius-sm);\n transition: var(--test-transition);\n}\n\n.comparison-tab:hover {\n color: var(--test-text);\n background: rgba(0, 0, 0, 0.05);\n}\n\n.comparison-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.comparison-content {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n}\n\n/* ===========================\n Details Tab\n =========================== */\n.details-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: fadeIn 0.3s ease-out;\n}\n\n.details-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n gap: 12px;\n}\n\n.detail-card {\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 transition: var(--test-transition);\n}\n\n.detail-card.clickable {\n cursor: pointer;\n}\n\n.detail-card.clickable:hover {\n background: rgba(37, 99, 235, 0.05);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n}\n\n.detail-icon {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n color: var(--test-primary);\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.detail-content {\n flex: 1;\n min-width: 0;\n}\n\n.detail-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 margin-bottom: 4px;\n}\n\n.detail-value {\n font-size: 14px;\n color: var(--test-text);\n word-wrap: break-word;\n font-weight: 500;\n}\n\n.detail-value.monospace {\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 12px;\n}\n\n.detail-value.link {\n color: var(--test-primary);\n}\n\n.detail-action {\n color: var(--test-text-muted);\n font-size: 12px;\n transition: var(--test-transition);\n}\n\n.detail-card.clickable:hover .detail-action {\n color: var(--test-primary);\n}\n\n/* Error Section */\n.error-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.error-content {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid #fca5a5;\n}\n\n/* Result Details Section */\n.result-details-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.result-details-content {\n border-radius: var(--test-radius-md);\n overflow: hidden;\n border: 1px solid var(--test-border);\n}\n\n/* ===========================\n AI Runs Tab\n =========================== */\n.ai-runs-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: fadeIn 0.3s ease-out;\n}\n\n.ai-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.count-badge {\n background: var(--test-bg);\n color: var(--test-text-secondary);\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.ai-run-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.ai-run-card {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\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.ai-run-card:hover {\n background: rgba(37, 99, 235, 0.05);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n box-shadow: var(--test-shadow-sm);\n}\n\n.ai-run-icon {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, var(--test-primary) 0%, var(--test-primary-dark) 100%);\n color: white;\n border-radius: var(--test-radius-md);\n font-size: 18px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-sm);\n}\n\n.ai-run-icon.agent {\n background: linear-gradient(135deg, var(--test-primary) 0%, var(--test-primary-dark) 100%);\n}\n\n.ai-run-icon.prompt {\n background: linear-gradient(135deg, #9333ea 0%, #7c3aed 100%);\n}\n\n.ai-run-content {\n flex: 1;\n min-width: 0;\n}\n\n.ai-run-name {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 6px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.ai-run-meta {\n display: flex;\n gap: 10px;\n font-size: 12px;\n color: var(--test-text-secondary);\n flex-wrap: wrap;\n}\n\n.status-chip {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-chip.complete,\n.status-chip.completed,\n.status-chip.passed {\n background: var(--test-success-light);\n color: #059669;\n}\n\n.status-chip.failed,\n.status-chip.error {\n background: var(--test-error-light);\n color: #dc2626;\n}\n\n.status-chip.running {\n background: #dbeafe;\n color: var(--test-primary);\n}\n\n.cost-chip {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n color: var(--test-text-muted);\n}\n\n.ai-run-arrow {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.ai-run-card:hover .ai-run-arrow {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n/* ===========================\n Feedback Tab\n =========================== */\n.feedback-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n.feedback-list {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.feedback-item {\n padding: 20px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n border: 1px solid var(--test-border);\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.feedback-item:hover {\n border-color: var(--test-primary-light);\n}\n\n.feedback-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.feedback-user {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.user-avatar {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n color: var(--test-primary);\n font-size: 14px;\n}\n\n.user-name {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.feedback-date {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.feedback-body {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.feedback-rating {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.rating-stars {\n display: flex;\n gap: 2px;\n}\n\n.rating-stars i {\n font-size: 14px;\n color: var(--test-border);\n}\n\n.rating-stars i.filled {\n color: #fbbf24;\n}\n\n.rating-value {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.feedback-verdict {\n display: flex;\n}\n\n.verdict-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.verdict-badge.correct {\n background: var(--test-success-light);\n color: #059669;\n}\n\n.verdict-badge.incorrect {\n background: var(--test-error-light);\n color: #dc2626;\n}\n\n.feedback-comments {\n padding: 14px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n border-left: 3px solid var(--test-primary);\n}\n\n.feedback-comments p {\n margin: 0;\n font-size: 14px;\n line-height: 1.6;\n color: var(--test-text);\n}\n\n/* ===========================\n Log Tab\n =========================== */\n.log-tab {\n display: flex;\n flex-direction: column;\n gap: 0;\n height: 100%;\n animation: fadeIn 0.3s ease-out;\n}\n\n.log-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n background: var(--test-surface);\n padding: 16px 20px;\n border-radius: var(--test-radius-lg) var(--test-radius-lg) 0 0;\n border: 1px solid var(--test-border);\n border-bottom: none;\n}\n\n.log-title {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.log-title i {\n color: var(--test-text-secondary);\n font-size: 16px;\n}\n\n.log-title h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.log-actions {\n display: flex;\n gap: 8px;\n}\n\n.log-container {\n flex: 1;\n border-radius: 0 0 var(--test-radius-lg) var(--test-radius-lg);\n overflow: hidden;\n min-height: 300px;\n border: 1px solid var(--test-border);\n border-top: none;\n}\n\n/* ===========================\n Loading States & Skeletons\n =========================== */\n.loading-state {\n padding: 20px;\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.skeleton-avatar {\n width: 44px;\n height: 44px;\n border-radius: var(--test-radius-md);\n background: linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-avatar {\n border-radius: 50%;\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, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-line.wide { width: 70%; }\n.skeleton-line.medium { width: 55%; }\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/* ===========================\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 h3 {\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;\n font-size: 14px;\n color: var(--test-text-secondary);\n max-width: 300px;\n}\n\n/* ===========================\n Keyboard Shortcuts Help\n =========================== */\n.shortcuts-hint {\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: 100;\n}\n\n.shortcuts-hint > i {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: 50%;\n color: var(--test-text-muted);\n font-size: 16px;\n cursor: pointer;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.shortcuts-hint:hover > i {\n color: var(--test-primary);\n border-color: var(--test-primary-light);\n}\n\n.shortcuts-popup {\n display: none;\n position: absolute;\n bottom: 50px;\n right: 0;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 16px;\n box-shadow: var(--test-shadow-lg);\n min-width: 200px;\n}\n\n.shortcuts-hint:hover .shortcuts-popup {\n display: block;\n animation: fadeIn 0.2s ease-out;\n}\n\n.shortcuts-popup h4 {\n margin: 0 0 12px 0;\n font-size: 14px;\n font-weight: 700;\n color: var(--test-text);\n}\n\n.shortcuts-popup ul {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.shortcuts-popup li {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 6px 0;\n font-size: 13px;\n color: var(--test-text-secondary);\n}\n\n.shortcuts-popup 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, 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(3, 1fr);\n }\n\n .details-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .shortcuts-hint {\n display: none;\n }\n}\n\n/* ===========================\n Responsive Design - Mobile\n =========================== */\n@media (max-width: 768px) {\n .test-run-form {\n height: auto;\n min-height: 100%;\n }\n\n .test-run-header {\n padding: 16px;\n }\n\n .breadcrumb {\n margin-bottom: 12px;\n }\n\n .breadcrumb ol {\n font-size: 12px;\n }\n\n .header-content {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-left {\n width: 100%;\n }\n\n .status-indicator {\n width: 48px;\n height: 48px;\n font-size: 20px;\n }\n\n .test-run-info h1 {\n font-size: 18px;\n }\n\n .test-run-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-icon {\n width: 36px;\n height: 36px;\n font-size: 14px;\n }\n\n .metric-value {\n font-size: 14px;\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 .shortcut-hint {\n display: none;\n }\n\n .tab-content {\n padding: 16px;\n }\n\n .result-hero {\n padding: 24px 20px;\n }\n\n .result-icon {\n width: 64px;\n height: 64px;\n font-size: 32px;\n }\n\n .result-text h2 {\n font-size: 24px;\n }\n\n .result-score {\n font-size: 16px;\n }\n\n .check-results,\n .comparison-section,\n .ai-section,\n .feedback-item {\n padding: 18px;\n }\n\n .check-item {\n padding: 12px;\n }\n\n .comparison-tabs {\n flex-direction: column;\n gap: 4px;\n }\n\n .comparison-tab {\n text-align: center;\n }\n\n .details-grid {\n grid-template-columns: 1fr;\n }\n\n .detail-card {\n padding: 14px;\n }\n\n .ai-run-card {\n padding: 14px;\n }\n\n .ai-run-icon {\n width: 40px;\n height: 40px;\n font-size: 16px;\n }\n\n .ai-run-meta {\n flex-direction: column;\n gap: 4px;\n }\n\n .feedback-header {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .log-header {\n flex-direction: column;\n gap: 12px;\n align-items: stretch;\n }\n\n .log-actions {\n justify-content: stretch;\n }\n\n .log-actions button {\n flex: 1;\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-run-header {\n padding: 12px;\n }\n\n .header-left {\n gap: 12px;\n }\n\n .status-indicator {\n width: 40px;\n height: 40px;\n font-size: 18px;\n border-radius: 8px;\n }\n\n .test-run-info h1 {\n font-size: 16px;\n }\n\n .metrics-bar {\n grid-template-columns: 1fr 1fr;\n }\n\n .metric-card {\n padding: 10px;\n flex-direction: column;\n text-align: center;\n }\n\n .metric-icon {\n margin-bottom: 8px;\n }\n\n .metric-label {\n font-size: 9px;\n }\n\n .metric-value {\n font-size: 14px;\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 .result-hero {\n padding: 20px 16px;\n }\n\n .result-icon {\n width: 56px;\n height: 56px;\n font-size: 28px;\n }\n\n .result-text h2 {\n font-size: 20px;\n }\n\n .result-score {\n font-size: 14px;\n }\n\n .result-checks {\n font-size: 12px;\n }\n\n .section-header h3 {\n font-size: 16px;\n }\n\n .check-item {\n flex-direction: column;\n gap: 8px;\n }\n\n .check-weight {\n text-align: left;\n }\n}\n\n/* ===========================\n Touch Device Optimizations\n =========================== */\n@media (hover: none) and (pointer: coarse) {\n .tab,\n .comparison-tab,\n .ai-run-card,\n .check-item,\n .feedback-item,\n .detail-card.clickable {\n -webkit-tap-highlight-color: transparent;\n }\n\n .ai-run-card:active,\n .detail-card.clickable:active {\n background: rgba(37, 99, 235, 0.1);\n transform: scale(0.98);\n }\n\n .tab:active {\n background: rgba(37, 99, 235, 0.1);\n }\n\n /* Larger touch targets */\n .tab {\n min-height: 48px;\n }\n\n .ai-run-card,\n .detail-card {\n min-height: 64px;\n }\n}\n\n/* ===========================\n High Contrast Mode\n =========================== */\n@media (prefers-contrast: high) {\n .status-badge {\n border: 2px solid currentColor;\n }\n\n .check-item {\n border-width: 2px;\n }\n\n .tab.active {\n border-bottom-width: 4px;\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-avatar,\n .skeleton-line {\n animation: none;\n background: #e2e8f0;\n }\n\n .result-pulse {\n animation: none;\n display: none;\n }\n}\n\n/* ===========================\n Print Styles\n =========================== */\n@media print {\n .test-run-form {\n background: white;\n height: auto;\n }\n\n .header-actions,\n .tabs-container,\n .shortcuts-hint,\n .log-actions {\n display: none !important;\n }\n\n .tab-content {\n overflow: visible;\n padding: 0;\n }\n\n .result-hero,\n .check-results,\n .details-grid,\n .ai-section,\n .feedback-item {\n break-inside: avoid;\n box-shadow: none;\n border: 1px solid #ddd;\n }\n\n .comparison-content,\n .log-container {\n max-height: none;\n overflow: visible;\n }\n}\n\n/* ===========================\n Tags Bar - Sleek Inline Display\n =========================== */\n.tags-bar {\n margin-top: 16px;\n padding: 8px 14px;\n background: linear-gradient(135deg, rgba(37, 99, 235, 0.04) 0%, rgba(37, 99, 235, 0.08) 100%);\n border: 1px solid rgba(37, 99, 235, 0.15);\n border-radius: 8px;\n max-width: 600px;\n}\n\n.tags-bar-content {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.tags-bar-label {\n color: var(--test-text-secondary);\n font-size: 14px;\n}\n\n.tags-bar-label i {\n opacity: 0.6;\n}\n\n.tags-bar-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n flex: 1;\n}\n\n.tag-inline {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n background: rgba(37, 99, 235, 0.1);\n color: var(--test-primary);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n letter-spacing: 0.01em;\n}\n\n.tags-bar-empty {\n font-size: 12px;\n color: var(--test-text-secondary);\n opacity: 0.7;\n flex: 1;\n}\n\n.tags-bar-edit {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: transparent;\n border: 1px dashed var(--test-border);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--test-text-secondary);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.tags-bar-edit:hover {\n border-color: var(--test-primary);\n color: var(--test-primary);\n background: rgba(37, 99, 235, 0.05);\n}\n\n.tags-bar-edit i {\n font-size: 10px;\n}\n\n/* ===========================\n Tags Editor Panel - Expanded Edit Mode\n =========================== */\n.tags-editor-panel {\n margin-top: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-primary);\n border-radius: var(--test-radius-md);\n overflow: hidden;\n box-shadow: 0 4px 12px rgba(37, 99, 235, 0.1);\n max-width: 600px;\n}\n\n.tags-editor-header {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n background: rgba(37, 99, 235, 0.08);\n border-bottom: 1px solid rgba(37, 99, 235, 0.2);\n}\n\n.tags-editor-title {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.tags-editor-body {\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.tags-editor-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n min-height: 32px;\n}\n\n.tag-editable {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 8px 5px 12px;\n background: var(--test-surface);\n border: 1px solid var(--test-primary);\n color: var(--test-primary);\n border-radius: 14px;\n font-size: 12px;\n font-weight: 500;\n}\n\n.tag-remove-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n background: transparent;\n border: none;\n color: var(--test-primary);\n cursor: pointer;\n border-radius: 50%;\n font-size: 9px;\n opacity: 0.6;\n transition: var(--test-transition);\n}\n\n.tag-remove-btn:hover {\n opacity: 1;\n background: var(--test-error-light);\n color: var(--test-error);\n}\n\n.tags-empty-hint {\n font-size: 12px;\n color: var(--test-text-secondary);\n font-style: italic;\n padding: 4px 0;\n}\n\n.tags-editor-input {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.tag-text-input {\n flex: 1;\n padding: 10px 14px;\n border: 1px solid var(--test-border);\n border-radius: 8px;\n font-size: 13px;\n background: var(--test-bg);\n}\n\n.tag-text-input:focus {\n outline: none;\n border-color: var(--test-primary);\n background: var(--test-surface);\n box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);\n}\n\n.tag-text-input::placeholder {\n color: var(--test-text-secondary);\n opacity: 0.6;\n}\n\n.tags-editor-footer {\n display: flex;\n justify-content: flex-start;\n gap: 8px;\n padding: 12px 16px;\n background: var(--test-bg);\n border-top: 1px solid var(--test-border);\n}\n\n/* Mobile Responsive for Tags */\n@media (max-width: 768px) {\n .tags-bar {\n padding: 8px 12px;\n }\n\n .tags-bar-content {\n gap: 8px;\n }\n\n .tag-inline {\n padding: 3px 8px;\n font-size: 10px;\n }\n\n .tags-editor-panel {\n margin-top: 12px;\n }\n\n .tags-editor-body {\n padding: 12px;\n }\n\n .tags-editor-footer {\n padding: 10px 12px;\n }\n}\n"] }]
|
|
1565
|
+
}], () => [{ type: i0.ElementRef }, { type: i1.SharedService }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: i0.ChangeDetectorRef }, { type: i3.TestingDialogService }, { type: i1.NavigationService }, { type: i4.ApplicationManager }, { type: i0.ViewContainerRef }], { handleKeyboardShortcut: [{
|
|
1566
|
+
type: HostListener,
|
|
1567
|
+
args: ['document:keydown', ['$event']]
|
|
1568
|
+
}] }); })();
|
|
1569
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestRunFormComponentExtended, { className: "TestRunFormComponentExtended", filePath: "src/lib/custom/Tests/test-run-form.component.ts", lineNumber: 36 }); })();
|
|
917
1570
|
export function LoadTestRunFormComponentExtended() {
|
|
918
1571
|
// Prevents tree-shaking
|
|
919
1572
|
}
|