@memberjunction/ng-core-entity-forms 2.129.0 → 2.130.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/custom/Tests/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 +94 -8
- package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.js +1527 -276
- package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.d.ts +48 -8
- package/dist/lib/custom/Tests/test-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.js +1078 -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 +227 -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 +3307 -200
- 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 +86 -2
- 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 +1975 -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,584 @@ 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) {
|
|
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;
|
|
512
827
|
this.destroy$ = new Subject();
|
|
513
828
|
// UI state
|
|
514
829
|
this.activeTab = 'overview';
|
|
515
830
|
this.loading = false;
|
|
831
|
+
this.loadingAIRuns = false;
|
|
832
|
+
this.loadingFeedback = false;
|
|
516
833
|
this.error = null;
|
|
517
834
|
this.aiRunsLoaded = false;
|
|
518
835
|
this.feedbackLoaded = false;
|
|
836
|
+
this.isRefreshing = false;
|
|
837
|
+
this.autoRefreshEnabled = false;
|
|
519
838
|
// Related entities
|
|
520
839
|
this.test = null;
|
|
521
840
|
this.testSuiteRun = null;
|
|
@@ -526,20 +845,153 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
526
845
|
this.parsedData = {};
|
|
527
846
|
// Active comparison view
|
|
528
847
|
this.comparisonView = 'input';
|
|
848
|
+
// Code editor configuration
|
|
849
|
+
this.jsonToolbar = createCopyOnlyToolbar();
|
|
850
|
+
// Keyboard shortcuts active
|
|
851
|
+
this.keyboardShortcutsEnabled = true;
|
|
852
|
+
// Tags management
|
|
853
|
+
this.tags = [];
|
|
854
|
+
this.newTag = '';
|
|
855
|
+
this.editingTags = false;
|
|
856
|
+
this.savingTags = false;
|
|
857
|
+
this.originalTags = [];
|
|
529
858
|
}
|
|
530
859
|
async ngOnInit() {
|
|
531
860
|
await super.ngOnInit();
|
|
532
861
|
if (this.record && this.record.ID) {
|
|
533
862
|
await this.loadRelatedData();
|
|
534
863
|
this.parseJsonFields();
|
|
864
|
+
this.loadTags();
|
|
865
|
+
// Auto-refresh for running tests
|
|
866
|
+
if (this.record.Status === 'Running' || this.record.Status === 'Pending') {
|
|
867
|
+
this.startAutoRefresh();
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
loadTags() {
|
|
872
|
+
this.tags = TagsHelper.parseTags(this.record.Tags);
|
|
873
|
+
this.originalTags = [...this.tags];
|
|
874
|
+
}
|
|
875
|
+
startEditingTags() {
|
|
876
|
+
this.originalTags = [...this.tags];
|
|
877
|
+
this.editingTags = true;
|
|
878
|
+
this.cdr.markForCheck();
|
|
879
|
+
}
|
|
880
|
+
cancelEditingTags() {
|
|
881
|
+
this.tags = [...this.originalTags];
|
|
882
|
+
this.newTag = '';
|
|
883
|
+
this.editingTags = false;
|
|
884
|
+
this.cdr.markForCheck();
|
|
885
|
+
}
|
|
886
|
+
addTag() {
|
|
887
|
+
const tag = this.newTag.trim();
|
|
888
|
+
if (tag && !this.tags.includes(tag)) {
|
|
889
|
+
this.tags = [...this.tags, tag];
|
|
890
|
+
this.newTag = '';
|
|
891
|
+
this.cdr.markForCheck();
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
removeTag(tag) {
|
|
895
|
+
this.tags = this.tags.filter(t => t !== tag);
|
|
896
|
+
this.cdr.markForCheck();
|
|
897
|
+
}
|
|
898
|
+
async saveTags() {
|
|
899
|
+
// Auto-add any pending tag in the input before saving
|
|
900
|
+
const pendingTag = this.newTag.trim();
|
|
901
|
+
if (pendingTag && !this.tags.includes(pendingTag)) {
|
|
902
|
+
this.tags = [...this.tags, pendingTag];
|
|
903
|
+
this.newTag = '';
|
|
904
|
+
}
|
|
905
|
+
this.savingTags = true;
|
|
906
|
+
this.cdr.markForCheck();
|
|
907
|
+
try {
|
|
908
|
+
this.record.Tags = TagsHelper.toJson(this.tags);
|
|
909
|
+
const result = await this.record.Save();
|
|
910
|
+
if (result) {
|
|
911
|
+
this.originalTags = [...this.tags];
|
|
912
|
+
this.editingTags = false;
|
|
913
|
+
SharedService.Instance.CreateSimpleNotification('Tags saved', 'success', 2000);
|
|
914
|
+
}
|
|
915
|
+
else {
|
|
916
|
+
SharedService.Instance.CreateSimpleNotification('Failed to save tags', 'error', 3000);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
catch {
|
|
920
|
+
SharedService.Instance.CreateSimpleNotification('Failed to save tags', 'error', 3000);
|
|
921
|
+
}
|
|
922
|
+
finally {
|
|
923
|
+
this.savingTags = false;
|
|
924
|
+
this.cdr.markForCheck();
|
|
535
925
|
}
|
|
536
926
|
}
|
|
537
927
|
ngOnDestroy() {
|
|
538
928
|
this.destroy$.next();
|
|
539
929
|
this.destroy$.complete();
|
|
540
930
|
}
|
|
931
|
+
// Keyboard shortcuts
|
|
932
|
+
handleKeyboardShortcut(event) {
|
|
933
|
+
if (!this.keyboardShortcutsEnabled)
|
|
934
|
+
return;
|
|
935
|
+
// Cmd/Ctrl + R: Refresh
|
|
936
|
+
if ((event.metaKey || event.ctrlKey) && event.key === 'r' && !event.shiftKey) {
|
|
937
|
+
event.preventDefault();
|
|
938
|
+
this.refresh();
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
// Cmd/Ctrl + Shift + R: Re-run test
|
|
942
|
+
if ((event.metaKey || event.ctrlKey) && event.shiftKey && event.key === 'r') {
|
|
943
|
+
event.preventDefault();
|
|
944
|
+
this.reRunTest();
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
// Number keys for tabs (1-5)
|
|
948
|
+
if (!event.metaKey && !event.ctrlKey && !event.altKey) {
|
|
949
|
+
switch (event.key) {
|
|
950
|
+
case '1':
|
|
951
|
+
this.changeTab('overview');
|
|
952
|
+
break;
|
|
953
|
+
case '2':
|
|
954
|
+
this.changeTab('details');
|
|
955
|
+
break;
|
|
956
|
+
case '3':
|
|
957
|
+
this.changeTab('ai-runs');
|
|
958
|
+
break;
|
|
959
|
+
case '4':
|
|
960
|
+
this.changeTab('feedback');
|
|
961
|
+
break;
|
|
962
|
+
case '5':
|
|
963
|
+
if (this.record.Log)
|
|
964
|
+
this.changeTab('log');
|
|
965
|
+
break;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
startAutoRefresh() {
|
|
970
|
+
this.autoRefreshEnabled = true;
|
|
971
|
+
interval(5000)
|
|
972
|
+
.pipe(takeUntil(this.destroy$))
|
|
973
|
+
.subscribe(() => {
|
|
974
|
+
if (this.autoRefreshEnabled && (this.record.Status === 'Running' || this.record.Status === 'Pending')) {
|
|
975
|
+
this.silentRefresh();
|
|
976
|
+
}
|
|
977
|
+
else {
|
|
978
|
+
this.autoRefreshEnabled = false;
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
async silentRefresh() {
|
|
983
|
+
try {
|
|
984
|
+
await this.record.Load(this.record.ID);
|
|
985
|
+
this.parseJsonFields();
|
|
986
|
+
this.cdr.markForCheck();
|
|
987
|
+
}
|
|
988
|
+
catch {
|
|
989
|
+
// Silently fail on auto-refresh
|
|
990
|
+
}
|
|
991
|
+
}
|
|
541
992
|
async loadRelatedData() {
|
|
542
993
|
this.loading = true;
|
|
994
|
+
this.error = null;
|
|
543
995
|
try {
|
|
544
996
|
// Load test
|
|
545
997
|
if (this.record.TestID) {
|
|
@@ -561,16 +1013,22 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
561
1013
|
}
|
|
562
1014
|
catch (error) {
|
|
563
1015
|
console.error('Error loading related data:', error);
|
|
564
|
-
this.error = 'Failed to load related data';
|
|
1016
|
+
this.error = 'Failed to load related data. Click to retry.';
|
|
565
1017
|
}
|
|
566
1018
|
finally {
|
|
567
1019
|
this.loading = false;
|
|
568
1020
|
this.cdr.markForCheck();
|
|
569
1021
|
}
|
|
570
1022
|
}
|
|
1023
|
+
async retryLoad() {
|
|
1024
|
+
this.error = null;
|
|
1025
|
+
await this.loadRelatedData();
|
|
1026
|
+
}
|
|
571
1027
|
async loadAIRuns() {
|
|
572
1028
|
if (this.aiRunsLoaded)
|
|
573
1029
|
return;
|
|
1030
|
+
this.loadingAIRuns = true;
|
|
1031
|
+
this.cdr.markForCheck();
|
|
574
1032
|
try {
|
|
575
1033
|
const rv = new RunView();
|
|
576
1034
|
const [agentRuns, promptRuns] = await rv.RunViews([
|
|
@@ -583,7 +1041,7 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
583
1041
|
{
|
|
584
1042
|
EntityName: 'MJ: AI Prompt Runs',
|
|
585
1043
|
ExtraFilter: `TestRunID='${this.record.ID}'`,
|
|
586
|
-
OrderBy: '
|
|
1044
|
+
OrderBy: 'RunAt',
|
|
587
1045
|
ResultType: 'entity_object'
|
|
588
1046
|
}
|
|
589
1047
|
]);
|
|
@@ -594,15 +1052,21 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
594
1052
|
this.aiPromptRuns = promptRuns.Results || [];
|
|
595
1053
|
}
|
|
596
1054
|
this.aiRunsLoaded = true;
|
|
597
|
-
this.cdr.markForCheck();
|
|
598
1055
|
}
|
|
599
1056
|
catch (error) {
|
|
600
1057
|
console.error('Error loading AI runs:', error);
|
|
1058
|
+
SharedService.Instance.CreateSimpleNotification('Failed to load AI runs', 'error', 3000);
|
|
1059
|
+
}
|
|
1060
|
+
finally {
|
|
1061
|
+
this.loadingAIRuns = false;
|
|
1062
|
+
this.cdr.markForCheck();
|
|
601
1063
|
}
|
|
602
1064
|
}
|
|
603
1065
|
async loadFeedback() {
|
|
604
1066
|
if (this.feedbackLoaded)
|
|
605
1067
|
return;
|
|
1068
|
+
this.loadingFeedback = true;
|
|
1069
|
+
this.cdr.markForCheck();
|
|
606
1070
|
try {
|
|
607
1071
|
const rv = new RunView();
|
|
608
1072
|
const result = await rv.RunView({
|
|
@@ -615,10 +1079,14 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
615
1079
|
this.feedbacks = result.Results || [];
|
|
616
1080
|
}
|
|
617
1081
|
this.feedbackLoaded = true;
|
|
618
|
-
this.cdr.markForCheck();
|
|
619
1082
|
}
|
|
620
1083
|
catch (error) {
|
|
621
1084
|
console.error('Error loading feedback:', error);
|
|
1085
|
+
SharedService.Instance.CreateSimpleNotification('Failed to load feedback', 'error', 3000);
|
|
1086
|
+
}
|
|
1087
|
+
finally {
|
|
1088
|
+
this.loadingFeedback = false;
|
|
1089
|
+
this.cdr.markForCheck();
|
|
622
1090
|
}
|
|
623
1091
|
}
|
|
624
1092
|
parseJsonFields() {
|
|
@@ -657,26 +1125,31 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
657
1125
|
}
|
|
658
1126
|
getStatusColor() {
|
|
659
1127
|
switch (this.record.Status) {
|
|
660
|
-
case 'Passed': return '#
|
|
661
|
-
case 'Failed': return '#
|
|
662
|
-
case 'Error': return '#
|
|
663
|
-
case '
|
|
664
|
-
case '
|
|
665
|
-
case '
|
|
666
|
-
|
|
1128
|
+
case 'Passed': return '#10b981';
|
|
1129
|
+
case 'Failed': return '#ef4444';
|
|
1130
|
+
case 'Error': return '#f59e0b';
|
|
1131
|
+
case 'Timeout': return '#f97316';
|
|
1132
|
+
case 'Running': return '#3b82f6';
|
|
1133
|
+
case 'Pending': return '#8b5cf6';
|
|
1134
|
+
case 'Skipped': return '#6b7280';
|
|
1135
|
+
default: return '#9ca3af';
|
|
667
1136
|
}
|
|
668
1137
|
}
|
|
669
1138
|
getStatusIcon() {
|
|
670
1139
|
switch (this.record.Status) {
|
|
671
1140
|
case 'Passed': return 'fa-check-circle';
|
|
672
1141
|
case 'Failed': return 'fa-times-circle';
|
|
673
|
-
case 'Error': return 'fa-exclamation-
|
|
674
|
-
case '
|
|
675
|
-
case '
|
|
1142
|
+
case 'Error': return 'fa-exclamation-triangle';
|
|
1143
|
+
case 'Timeout': return 'fa-stopwatch';
|
|
1144
|
+
case 'Running': return 'fa-circle-notch fa-spin';
|
|
1145
|
+
case 'Pending': return 'fa-hourglass-half';
|
|
676
1146
|
case 'Skipped': return 'fa-forward';
|
|
677
1147
|
default: return 'fa-question-circle';
|
|
678
1148
|
}
|
|
679
1149
|
}
|
|
1150
|
+
getStatusClass() {
|
|
1151
|
+
return `status-${this.record.Status?.toLowerCase() || 'unknown'}`;
|
|
1152
|
+
}
|
|
680
1153
|
calculateDuration() {
|
|
681
1154
|
if (!this.record.DurationSeconds)
|
|
682
1155
|
return 'N/A';
|
|
@@ -702,11 +1175,29 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
702
1175
|
return 'N/A';
|
|
703
1176
|
return `$${cost.toFixed(6)}`;
|
|
704
1177
|
}
|
|
1178
|
+
getScorePercentage() {
|
|
1179
|
+
if (this.record.Score === null || this.record.Score === undefined)
|
|
1180
|
+
return 0;
|
|
1181
|
+
return Math.round(this.record.Score * 100);
|
|
1182
|
+
}
|
|
1183
|
+
getPassRatePercentage() {
|
|
1184
|
+
const total = this.record.TotalChecks || 0;
|
|
1185
|
+
const passed = this.record.PassedChecks || 0;
|
|
1186
|
+
if (total === 0)
|
|
1187
|
+
return 0;
|
|
1188
|
+
return Math.round((passed / total) * 100);
|
|
1189
|
+
}
|
|
705
1190
|
openTest() {
|
|
706
1191
|
if (this.test) {
|
|
707
1192
|
SharedService.Instance.OpenEntityRecord('MJ: Tests', CompositeKey.FromID(this.test.ID));
|
|
708
1193
|
}
|
|
709
1194
|
}
|
|
1195
|
+
navigateToTestingDashboard() {
|
|
1196
|
+
const testingApp = this.appManager.GetAppByName('Testing');
|
|
1197
|
+
if (testingApp) {
|
|
1198
|
+
this.navigationService.SwitchToApp(testingApp.ID);
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
710
1201
|
openTestSuiteRun() {
|
|
711
1202
|
if (this.testSuiteRun) {
|
|
712
1203
|
SharedService.Instance.OpenEntityRecord('MJ: Test Suite Runs', CompositeKey.FromID(this.testSuiteRun.ID));
|
|
@@ -719,25 +1210,62 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
719
1210
|
SharedService.Instance.OpenEntityRecord('MJ: AI Prompt Runs', CompositeKey.FromID(runId));
|
|
720
1211
|
}
|
|
721
1212
|
async reRunTest() {
|
|
722
|
-
|
|
723
|
-
|
|
1213
|
+
if (!this.record.TestID) {
|
|
1214
|
+
SharedService.Instance.CreateSimpleNotification('Cannot re-run: Test ID not available', 'error', 3000);
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1217
|
+
this.testingDialogService.OpenTestDialog(this.record.TestID);
|
|
724
1218
|
}
|
|
725
1219
|
async refresh() {
|
|
726
|
-
|
|
1220
|
+
this.isRefreshing = true;
|
|
727
1221
|
this.cdr.markForCheck();
|
|
1222
|
+
try {
|
|
1223
|
+
await this.record.Load(this.record.ID);
|
|
1224
|
+
await this.loadRelatedData();
|
|
1225
|
+
this.parseJsonFields();
|
|
1226
|
+
// Reset lazy-loaded data to force reload
|
|
1227
|
+
this.aiRunsLoaded = false;
|
|
1228
|
+
this.feedbackLoaded = false;
|
|
1229
|
+
this.aiAgentRuns = [];
|
|
1230
|
+
this.aiPromptRuns = [];
|
|
1231
|
+
this.feedbacks = [];
|
|
1232
|
+
// Reload current tab data if needed
|
|
1233
|
+
if (this.activeTab === 'ai-runs') {
|
|
1234
|
+
await this.loadAIRuns();
|
|
1235
|
+
}
|
|
1236
|
+
else if (this.activeTab === 'feedback') {
|
|
1237
|
+
await this.loadFeedback();
|
|
1238
|
+
}
|
|
1239
|
+
SharedService.Instance.CreateSimpleNotification('Refreshed successfully', 'success', 2000);
|
|
1240
|
+
}
|
|
1241
|
+
catch {
|
|
1242
|
+
SharedService.Instance.CreateSimpleNotification('Failed to refresh', 'error', 3000);
|
|
1243
|
+
}
|
|
1244
|
+
finally {
|
|
1245
|
+
this.isRefreshing = false;
|
|
1246
|
+
this.cdr.markForCheck();
|
|
1247
|
+
}
|
|
728
1248
|
}
|
|
729
1249
|
getComparisonData() {
|
|
1250
|
+
let data;
|
|
730
1251
|
switch (this.comparisonView) {
|
|
731
|
-
case 'input':
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
1252
|
+
case 'input':
|
|
1253
|
+
data = this.parsedData.input;
|
|
1254
|
+
break;
|
|
1255
|
+
case 'expected':
|
|
1256
|
+
data = this.parsedData.expected;
|
|
1257
|
+
break;
|
|
1258
|
+
case 'actual':
|
|
1259
|
+
data = this.parsedData.actual;
|
|
1260
|
+
break;
|
|
735
1261
|
}
|
|
1262
|
+
return data ? JSON.stringify(data, null, 2) : '// No data available';
|
|
736
1263
|
}
|
|
737
1264
|
getCheckResults() {
|
|
738
|
-
|
|
1265
|
+
const details = this.parsedData.resultDetails;
|
|
1266
|
+
if (!details?.checkResults)
|
|
739
1267
|
return [];
|
|
740
|
-
return
|
|
1268
|
+
return details.checkResults;
|
|
741
1269
|
}
|
|
742
1270
|
getPassRate() {
|
|
743
1271
|
const total = this.record.TotalChecks || 0;
|
|
@@ -746,155 +1274,272 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
746
1274
|
return 0;
|
|
747
1275
|
return (passed / total) * 100;
|
|
748
1276
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
1277
|
+
async copyLogToClipboard() {
|
|
1278
|
+
if (this.record.Log) {
|
|
1279
|
+
try {
|
|
1280
|
+
await navigator.clipboard.writeText(this.record.Log);
|
|
1281
|
+
SharedService.Instance.CreateSimpleNotification('Log copied to clipboard', 'success', 2000);
|
|
1282
|
+
}
|
|
1283
|
+
catch {
|
|
1284
|
+
SharedService.Instance.CreateSimpleNotification('Failed to copy log', 'error', 2000);
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
getFormattedResultDetails() {
|
|
1289
|
+
return this.parsedData.resultDetails
|
|
1290
|
+
? JSON.stringify(this.parsedData.resultDetails, null, 2)
|
|
1291
|
+
: '// No result details available';
|
|
1292
|
+
}
|
|
1293
|
+
// Helper for relative time display
|
|
1294
|
+
getRelativeTime(date) {
|
|
1295
|
+
if (!date)
|
|
1296
|
+
return 'N/A';
|
|
1297
|
+
const d = new Date(date);
|
|
1298
|
+
const now = new Date();
|
|
1299
|
+
const diffMs = now.getTime() - d.getTime();
|
|
1300
|
+
const diffMins = Math.floor(diffMs / 60000);
|
|
1301
|
+
const diffHours = Math.floor(diffMs / 3600000);
|
|
1302
|
+
const diffDays = Math.floor(diffMs / 86400000);
|
|
1303
|
+
if (diffMins < 1)
|
|
1304
|
+
return 'Just now';
|
|
1305
|
+
if (diffMins < 60)
|
|
1306
|
+
return `${diffMins}m ago`;
|
|
1307
|
+
if (diffHours < 24)
|
|
1308
|
+
return `${diffHours}h ago`;
|
|
1309
|
+
if (diffDays < 7)
|
|
1310
|
+
return `${diffDays}d ago`;
|
|
1311
|
+
return d.toLocaleDateString();
|
|
1312
|
+
}
|
|
1313
|
+
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)); }; }
|
|
1314
|
+
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestRunFormComponentExtended, selectors: [["mj-test-run-form"]], hostBindings: function TestRunFormComponentExtended_HostBindings(rf, ctx) { if (rf & 1) {
|
|
1315
|
+
i0.ɵɵlistener("keydown", function TestRunFormComponentExtended_keydown_HostBindingHandler($event) { return ctx.handleKeyboardShortcut($event); }, false, i0.ɵɵresolveDocument);
|
|
1316
|
+
} }, 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) {
|
|
1317
|
+
i0.ɵɵelementStart(0, "div", 0);
|
|
1318
|
+
i0.ɵɵtemplate(1, TestRunFormComponentExtended_div_1_Template, 7, 1, "div", 1);
|
|
1319
|
+
i0.ɵɵelementStart(2, "div", 2)(3, "nav", 3)(4, "ol")(5, "li")(6, "a", 4);
|
|
1320
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_a_click_6_listener() { return ctx.navigateToTestingDashboard(); });
|
|
1321
|
+
i0.ɵɵelement(7, "i", 5);
|
|
1322
|
+
i0.ɵɵelementStart(8, "span", 6);
|
|
1323
|
+
i0.ɵɵtext(9, "Testing");
|
|
1324
|
+
i0.ɵɵelementEnd()()();
|
|
1325
|
+
i0.ɵɵtemplate(10, TestRunFormComponentExtended_li_10_Template, 6, 1, "li", 7);
|
|
1326
|
+
i0.ɵɵelementStart(11, "li", 8);
|
|
1327
|
+
i0.ɵɵelement(12, "i", 9);
|
|
1328
|
+
i0.ɵɵelementStart(13, "span");
|
|
1329
|
+
i0.ɵɵtext(14);
|
|
1330
|
+
i0.ɵɵelementEnd()()()();
|
|
1331
|
+
i0.ɵɵelementStart(15, "div", 10)(16, "div", 11)(17, "div", 12);
|
|
1332
|
+
i0.ɵɵelement(18, "i", 13);
|
|
1333
|
+
i0.ɵɵelementEnd();
|
|
1334
|
+
i0.ɵɵelementStart(19, "div", 14)(20, "h1");
|
|
1335
|
+
i0.ɵɵtext(21, " Test Run ");
|
|
1336
|
+
i0.ɵɵelementStart(22, "span", 15);
|
|
1337
|
+
i0.ɵɵtext(23);
|
|
755
1338
|
i0.ɵɵelementEnd()();
|
|
756
|
-
i0.ɵɵelementStart(
|
|
757
|
-
i0.ɵɵ
|
|
1339
|
+
i0.ɵɵelementStart(24, "div", 16)(25, "span", 17);
|
|
1340
|
+
i0.ɵɵtext(26);
|
|
758
1341
|
i0.ɵɵelementEnd();
|
|
759
|
-
i0.ɵɵ
|
|
760
|
-
i0.ɵɵ
|
|
1342
|
+
i0.ɵɵtemplate(27, TestRunFormComponentExtended_span_27_Template, 3, 1, "span", 18)(28, TestRunFormComponentExtended_span_28_Template, 3, 0, "span", 18);
|
|
1343
|
+
i0.ɵɵelementEnd()()();
|
|
1344
|
+
i0.ɵɵelementStart(29, "div", 19)(30, "button", 20);
|
|
1345
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_30_listener() { return ctx.reRunTest(); });
|
|
1346
|
+
i0.ɵɵelement(31, "i", 21);
|
|
1347
|
+
i0.ɵɵelementStart(32, "span", 22);
|
|
1348
|
+
i0.ɵɵtext(33, "Re-run");
|
|
1349
|
+
i0.ɵɵelementEnd()();
|
|
1350
|
+
i0.ɵɵelementStart(34, "button", 23);
|
|
1351
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_34_listener() { return ctx.refresh(); });
|
|
1352
|
+
i0.ɵɵelement(35, "i", 24);
|
|
1353
|
+
i0.ɵɵelementStart(36, "span", 22);
|
|
1354
|
+
i0.ɵɵtext(37, "Refresh");
|
|
1355
|
+
i0.ɵɵelementEnd()()()();
|
|
1356
|
+
i0.ɵɵelementStart(38, "div", 25)(39, "div", 26)(40, "div", 27);
|
|
1357
|
+
i0.ɵɵelement(41, "i", 28);
|
|
761
1358
|
i0.ɵɵelementEnd();
|
|
762
|
-
i0.ɵɵelementStart(
|
|
763
|
-
i0.ɵɵ
|
|
764
|
-
i0.ɵɵtext(17);
|
|
1359
|
+
i0.ɵɵelementStart(42, "div", 29)(43, "div", 30);
|
|
1360
|
+
i0.ɵɵtext(44, "Started");
|
|
765
1361
|
i0.ɵɵelementEnd();
|
|
766
|
-
i0.ɵɵ
|
|
1362
|
+
i0.ɵɵelementStart(45, "div", 31);
|
|
1363
|
+
i0.ɵɵtext(46);
|
|
1364
|
+
i0.ɵɵelementEnd();
|
|
1365
|
+
i0.ɵɵelementStart(47, "div", 32);
|
|
1366
|
+
i0.ɵɵtext(48);
|
|
1367
|
+
i0.ɵɵpipe(49, "date");
|
|
767
1368
|
i0.ɵɵelementEnd()()();
|
|
768
|
-
i0.ɵɵelementStart(
|
|
769
|
-
i0.ɵɵ
|
|
770
|
-
i0.ɵɵ
|
|
1369
|
+
i0.ɵɵelementStart(50, "div", 26)(51, "div", 27);
|
|
1370
|
+
i0.ɵɵelement(52, "i", 33);
|
|
1371
|
+
i0.ɵɵelementEnd();
|
|
1372
|
+
i0.ɵɵelementStart(53, "div", 29)(54, "div", 30);
|
|
1373
|
+
i0.ɵɵtext(55, "Duration");
|
|
771
1374
|
i0.ɵɵelementEnd();
|
|
772
|
-
i0.ɵɵelementStart(
|
|
773
|
-
i0.ɵɵ
|
|
774
|
-
i0.ɵɵtext(23, " Refresh ");
|
|
1375
|
+
i0.ɵɵelementStart(56, "div", 31);
|
|
1376
|
+
i0.ɵɵtext(57);
|
|
775
1377
|
i0.ɵɵelementEnd()()();
|
|
776
|
-
i0.ɵɵelementStart(
|
|
777
|
-
i0.ɵɵ
|
|
1378
|
+
i0.ɵɵelementStart(58, "div", 26)(59, "div", 27);
|
|
1379
|
+
i0.ɵɵelement(60, "i", 34);
|
|
778
1380
|
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");
|
|
1381
|
+
i0.ɵɵelementStart(61, "div", 29)(62, "div", 30);
|
|
1382
|
+
i0.ɵɵtext(63, "Score");
|
|
785
1383
|
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");
|
|
1384
|
+
i0.ɵɵelementStart(64, "div", 31);
|
|
1385
|
+
i0.ɵɵtext(65);
|
|
792
1386
|
i0.ɵɵelementEnd();
|
|
793
|
-
i0.ɵɵ
|
|
794
|
-
i0.ɵɵtext(41);
|
|
1387
|
+
i0.ɵɵtemplate(66, TestRunFormComponentExtended_div_66_Template, 2, 4, "div", 35);
|
|
795
1388
|
i0.ɵɵelementEnd()();
|
|
796
|
-
i0.ɵɵelementStart(
|
|
797
|
-
i0.ɵɵ
|
|
1389
|
+
i0.ɵɵelementStart(67, "div", 26)(68, "div", 27);
|
|
1390
|
+
i0.ɵɵelement(69, "i", 36);
|
|
798
1391
|
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");
|
|
1392
|
+
i0.ɵɵelementStart(70, "div", 29)(71, "div", 30);
|
|
1393
|
+
i0.ɵɵtext(72, "Checks");
|
|
804
1394
|
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:");
|
|
1395
|
+
i0.ɵɵelementStart(73, "div", 31);
|
|
1396
|
+
i0.ɵɵtext(74);
|
|
810
1397
|
i0.ɵɵelementEnd();
|
|
811
|
-
i0.ɵɵ
|
|
812
|
-
i0.ɵɵtext(57);
|
|
1398
|
+
i0.ɵɵtemplate(75, TestRunFormComponentExtended_div_75_Template, 2, 4, "div", 35);
|
|
813
1399
|
i0.ɵɵelementEnd()();
|
|
814
|
-
i0.ɵɵelementStart(
|
|
815
|
-
i0.ɵɵ
|
|
1400
|
+
i0.ɵɵelementStart(76, "div", 26)(77, "div", 27);
|
|
1401
|
+
i0.ɵɵelement(78, "i", 37);
|
|
816
1402
|
i0.ɵɵelementEnd();
|
|
817
|
-
i0.ɵɵelementStart(
|
|
818
|
-
i0.ɵɵtext(
|
|
1403
|
+
i0.ɵɵelementStart(79, "div", 29)(80, "div", 30);
|
|
1404
|
+
i0.ɵɵtext(81, "Cost");
|
|
1405
|
+
i0.ɵɵelementEnd();
|
|
1406
|
+
i0.ɵɵelementStart(82, "div", 31);
|
|
1407
|
+
i0.ɵɵtext(83);
|
|
1408
|
+
i0.ɵɵelementEnd()()()();
|
|
1409
|
+
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);
|
|
1410
|
+
i0.ɵɵelementEnd();
|
|
1411
|
+
i0.ɵɵelementStart(87, "div", 41)(88, "div", 42)(89, "button", 43);
|
|
1412
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_89_listener() { return ctx.changeTab("overview"); });
|
|
1413
|
+
i0.ɵɵelement(90, "i", 44);
|
|
1414
|
+
i0.ɵɵelementStart(91, "span");
|
|
1415
|
+
i0.ɵɵtext(92, "Overview");
|
|
819
1416
|
i0.ɵɵelementEnd()();
|
|
820
|
-
i0.ɵɵ
|
|
1417
|
+
i0.ɵɵelementStart(93, "button", 45);
|
|
1418
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_93_listener() { return ctx.changeTab("details"); });
|
|
1419
|
+
i0.ɵɵelement(94, "i", 46);
|
|
1420
|
+
i0.ɵɵelementStart(95, "span");
|
|
1421
|
+
i0.ɵɵtext(96, "Details");
|
|
821
1422
|
i0.ɵɵelementEnd()();
|
|
822
|
-
i0.ɵɵelementStart(
|
|
823
|
-
i0.ɵɵlistener("click", function
|
|
824
|
-
i0.ɵɵelement(
|
|
825
|
-
i0.ɵɵelementStart(
|
|
826
|
-
i0.ɵɵtext(
|
|
1423
|
+
i0.ɵɵelementStart(97, "button", 47);
|
|
1424
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_97_listener() { return ctx.changeTab("ai-runs"); });
|
|
1425
|
+
i0.ɵɵelement(98, "i", 48);
|
|
1426
|
+
i0.ɵɵelementStart(99, "span");
|
|
1427
|
+
i0.ɵɵtext(100, "AI Runs");
|
|
1428
|
+
i0.ɵɵelementEnd();
|
|
1429
|
+
i0.ɵɵtemplate(101, TestRunFormComponentExtended_span_101_Template, 2, 1, "span", 49);
|
|
1430
|
+
i0.ɵɵelementEnd();
|
|
1431
|
+
i0.ɵɵelementStart(102, "button", 50);
|
|
1432
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_102_listener() { return ctx.changeTab("feedback"); });
|
|
1433
|
+
i0.ɵɵelement(103, "i", 51);
|
|
1434
|
+
i0.ɵɵelementStart(104, "span");
|
|
1435
|
+
i0.ɵɵtext(105, "Feedback");
|
|
1436
|
+
i0.ɵɵelementEnd();
|
|
1437
|
+
i0.ɵɵtemplate(106, TestRunFormComponentExtended_span_106_Template, 2, 1, "span", 49);
|
|
1438
|
+
i0.ɵɵelementEnd();
|
|
1439
|
+
i0.ɵɵelementStart(107, "button", 52);
|
|
1440
|
+
i0.ɵɵlistener("click", function TestRunFormComponentExtended_Template_button_click_107_listener() { return ctx.changeTab("execution"); });
|
|
1441
|
+
i0.ɵɵelement(108, "i", 53);
|
|
1442
|
+
i0.ɵɵelementStart(109, "span");
|
|
1443
|
+
i0.ɵɵtext(110, "Execution");
|
|
827
1444
|
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");
|
|
1445
|
+
i0.ɵɵtemplate(111, TestRunFormComponentExtended_button_111_Template, 4, 3, "button", 54);
|
|
833
1446
|
i0.ɵɵelementEnd()();
|
|
834
|
-
i0.ɵɵelementStart(
|
|
835
|
-
i0.ɵɵ
|
|
836
|
-
i0.ɵɵelement(75, "i", 29);
|
|
837
|
-
i0.ɵɵelementStart(76, "span");
|
|
838
|
-
i0.ɵɵtext(77, "AI Runs");
|
|
1447
|
+
i0.ɵɵelementStart(112, "div", 55);
|
|
1448
|
+
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
1449
|
i0.ɵɵelementEnd();
|
|
840
|
-
i0.ɵɵ
|
|
1450
|
+
i0.ɵɵelementStart(119, "div", 62);
|
|
1451
|
+
i0.ɵɵelement(120, "i", 63);
|
|
1452
|
+
i0.ɵɵelementStart(121, "div", 64)(122, "h4");
|
|
1453
|
+
i0.ɵɵtext(123, "Keyboard Shortcuts");
|
|
841
1454
|
i0.ɵɵelementEnd();
|
|
842
|
-
i0.ɵɵelementStart(
|
|
843
|
-
i0.ɵɵ
|
|
844
|
-
i0.ɵɵelement(80, "i", 31);
|
|
845
|
-
i0.ɵɵelementStart(81, "span");
|
|
846
|
-
i0.ɵɵtext(82, "Feedback");
|
|
1455
|
+
i0.ɵɵelementStart(124, "ul")(125, "li")(126, "kbd");
|
|
1456
|
+
i0.ɵɵtext(127, "1-6");
|
|
847
1457
|
i0.ɵɵelementEnd();
|
|
848
|
-
i0.ɵɵ
|
|
849
|
-
i0.ɵɵelementEnd()
|
|
850
|
-
i0.ɵɵelementStart(
|
|
851
|
-
i0.ɵɵ
|
|
852
|
-
i0.ɵɵelementEnd()
|
|
1458
|
+
i0.ɵɵtext(128, " Switch tabs");
|
|
1459
|
+
i0.ɵɵelementEnd();
|
|
1460
|
+
i0.ɵɵelementStart(129, "li")(130, "kbd");
|
|
1461
|
+
i0.ɵɵtext(131, "Cmd+R");
|
|
1462
|
+
i0.ɵɵelementEnd();
|
|
1463
|
+
i0.ɵɵtext(132, " Refresh");
|
|
1464
|
+
i0.ɵɵelementEnd();
|
|
1465
|
+
i0.ɵɵelementStart(133, "li")(134, "kbd");
|
|
1466
|
+
i0.ɵɵtext(135, "Cmd+Shift+R");
|
|
1467
|
+
i0.ɵɵelementEnd();
|
|
1468
|
+
i0.ɵɵtext(136, " Re-run test");
|
|
1469
|
+
i0.ɵɵelementEnd()()()()();
|
|
853
1470
|
} if (rf & 2) {
|
|
854
|
-
i0.ɵɵ
|
|
855
|
-
i0.ɵɵ
|
|
1471
|
+
i0.ɵɵclassProp("is-mobile", false);
|
|
1472
|
+
i0.ɵɵadvance();
|
|
1473
|
+
i0.ɵɵproperty("ngIf", ctx.error);
|
|
856
1474
|
i0.ɵɵadvance();
|
|
1475
|
+
i0.ɵɵclassMap(ctx.getStatusClass());
|
|
1476
|
+
i0.ɵɵadvance(8);
|
|
857
1477
|
i0.ɵɵproperty("ngIf", ctx.test);
|
|
858
|
-
i0.ɵɵadvance(
|
|
1478
|
+
i0.ɵɵadvance(4);
|
|
859
1479
|
i0.ɵɵtextInterpolate1("Run #", ctx.record.ID.substring(0, 8), "");
|
|
860
1480
|
i0.ɵɵadvance(3);
|
|
861
1481
|
i0.ɵɵstyleProp("background-color", ctx.getStatusColor());
|
|
862
|
-
i0.ɵɵadvance(6);
|
|
863
|
-
i0.ɵɵstyleProp("background-color", ctx.getStatusColor());
|
|
864
1482
|
i0.ɵɵadvance();
|
|
865
1483
|
i0.ɵɵproperty("ngClass", ctx.getStatusIcon());
|
|
1484
|
+
i0.ɵɵadvance(5);
|
|
1485
|
+
i0.ɵɵtextInterpolate1("#", ctx.record.ID.substring(0, 8), "");
|
|
1486
|
+
i0.ɵɵadvance(2);
|
|
1487
|
+
i0.ɵɵstyleProp("background-color", ctx.getStatusColor());
|
|
866
1488
|
i0.ɵɵadvance();
|
|
867
1489
|
i0.ɵɵtextInterpolate1(" ", ctx.record.Status, " ");
|
|
868
1490
|
i0.ɵɵadvance();
|
|
869
1491
|
i0.ɵɵproperty("ngIf", ctx.test);
|
|
1492
|
+
i0.ɵɵadvance();
|
|
1493
|
+
i0.ɵɵproperty("ngIf", ctx.autoRefreshEnabled);
|
|
1494
|
+
i0.ɵɵadvance(2);
|
|
1495
|
+
i0.ɵɵproperty("disabled", !ctx.record.TestID);
|
|
1496
|
+
i0.ɵɵadvance(4);
|
|
1497
|
+
i0.ɵɵproperty("disabled", ctx.isRefreshing);
|
|
1498
|
+
i0.ɵɵadvance();
|
|
1499
|
+
i0.ɵɵclassProp("fa-spin", ctx.isRefreshing);
|
|
870
1500
|
i0.ɵɵadvance(11);
|
|
871
|
-
i0.ɵɵtextInterpolate(
|
|
872
|
-
i0.ɵɵadvance(
|
|
873
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(
|
|
874
|
-
i0.ɵɵadvance(
|
|
1501
|
+
i0.ɵɵtextInterpolate(ctx.getRelativeTime(ctx.record.StartedAt));
|
|
1502
|
+
i0.ɵɵadvance(2);
|
|
1503
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(49, 56, ctx.record.StartedAt, "short"));
|
|
1504
|
+
i0.ɵɵadvance(9);
|
|
875
1505
|
i0.ɵɵtextInterpolate(ctx.calculateDuration());
|
|
876
|
-
i0.ɵɵadvance(
|
|
1506
|
+
i0.ɵɵadvance(8);
|
|
877
1507
|
i0.ɵɵtextInterpolate(ctx.formatScore(ctx.record.Score));
|
|
878
|
-
i0.ɵɵadvance(
|
|
879
|
-
i0.ɵɵ
|
|
880
|
-
i0.ɵɵadvance(
|
|
1508
|
+
i0.ɵɵadvance();
|
|
1509
|
+
i0.ɵɵproperty("ngIf", ctx.record.Score != null);
|
|
1510
|
+
i0.ɵɵadvance(8);
|
|
881
1511
|
i0.ɵɵtextInterpolate2("", ctx.record.PassedChecks, "/", ctx.record.TotalChecks, "");
|
|
882
|
-
i0.ɵɵadvance(5);
|
|
883
|
-
i0.ɵɵtextInterpolate(ctx.record.RunByUser);
|
|
884
1512
|
i0.ɵɵadvance();
|
|
885
|
-
i0.ɵɵproperty("ngIf", ctx.
|
|
1513
|
+
i0.ɵɵproperty("ngIf", ctx.record.TotalChecks);
|
|
1514
|
+
i0.ɵɵadvance(8);
|
|
1515
|
+
i0.ɵɵtextInterpolate(ctx.formatCost(ctx.record.CostUSD));
|
|
1516
|
+
i0.ɵɵadvance();
|
|
1517
|
+
i0.ɵɵproperty("ngIf", ctx.record.RunByUser || ctx.testSuiteRun || ctx.record.TargetLogEntityID);
|
|
1518
|
+
i0.ɵɵadvance();
|
|
1519
|
+
i0.ɵɵproperty("ngIf", !ctx.editingTags);
|
|
1520
|
+
i0.ɵɵadvance();
|
|
1521
|
+
i0.ɵɵproperty("ngIf", ctx.editingTags);
|
|
886
1522
|
i0.ɵɵadvance(3);
|
|
887
1523
|
i0.ɵɵclassProp("active", ctx.activeTab === "overview");
|
|
1524
|
+
i0.ɵɵattribute("aria-selected", ctx.activeTab === "overview");
|
|
888
1525
|
i0.ɵɵadvance(4);
|
|
889
1526
|
i0.ɵɵclassProp("active", ctx.activeTab === "details");
|
|
1527
|
+
i0.ɵɵattribute("aria-selected", ctx.activeTab === "details");
|
|
890
1528
|
i0.ɵɵadvance(4);
|
|
891
1529
|
i0.ɵɵclassProp("active", ctx.activeTab === "ai-runs");
|
|
1530
|
+
i0.ɵɵattribute("aria-selected", ctx.activeTab === "ai-runs");
|
|
892
1531
|
i0.ɵɵadvance(4);
|
|
893
1532
|
i0.ɵɵproperty("ngIf", ctx.aiRunsLoaded);
|
|
894
1533
|
i0.ɵɵadvance();
|
|
895
1534
|
i0.ɵɵclassProp("active", ctx.activeTab === "feedback");
|
|
1535
|
+
i0.ɵɵattribute("aria-selected", ctx.activeTab === "feedback");
|
|
896
1536
|
i0.ɵɵadvance(4);
|
|
897
1537
|
i0.ɵɵproperty("ngIf", ctx.feedbackLoaded);
|
|
1538
|
+
i0.ɵɵadvance();
|
|
1539
|
+
i0.ɵɵclassProp("active", ctx.activeTab === "execution");
|
|
1540
|
+
i0.ɵɵattribute("aria-selected", ctx.activeTab === "execution");
|
|
1541
|
+
i0.ɵɵadvance(4);
|
|
1542
|
+
i0.ɵɵproperty("ngIf", ctx.record.Log);
|
|
898
1543
|
i0.ɵɵadvance(2);
|
|
899
1544
|
i0.ɵɵproperty("ngIf", ctx.activeTab === "overview");
|
|
900
1545
|
i0.ɵɵadvance();
|
|
@@ -903,7 +1548,11 @@ let TestRunFormComponentExtended = class TestRunFormComponentExtended extends Te
|
|
|
903
1548
|
i0.ɵɵproperty("ngIf", ctx.activeTab === "ai-runs");
|
|
904
1549
|
i0.ɵɵadvance();
|
|
905
1550
|
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 }); }
|
|
1551
|
+
i0.ɵɵadvance();
|
|
1552
|
+
i0.ɵɵproperty("ngIf", ctx.activeTab === "execution");
|
|
1553
|
+
i0.ɵɵadvance();
|
|
1554
|
+
i0.ɵɵproperty("ngIf", ctx.activeTab === "log");
|
|
1555
|
+
} }, 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
1556
|
};
|
|
908
1557
|
TestRunFormComponentExtended = __decorate([
|
|
909
1558
|
RegisterClass(BaseFormComponent, 'MJ: Test Runs')
|
|
@@ -911,9 +1560,12 @@ TestRunFormComponentExtended = __decorate([
|
|
|
911
1560
|
export { TestRunFormComponentExtended };
|
|
912
1561
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TestRunFormComponentExtended, [{
|
|
913
1562
|
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
|
-
|
|
1563
|
+
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"] }]
|
|
1564
|
+
}], () => [{ type: i0.ElementRef }, { type: i1.SharedService }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: i0.ChangeDetectorRef }, { type: i3.TestingDialogService }, { type: i1.NavigationService }, { type: i4.ApplicationManager }], { handleKeyboardShortcut: [{
|
|
1565
|
+
type: HostListener,
|
|
1566
|
+
args: ['document:keydown', ['$event']]
|
|
1567
|
+
}] }); })();
|
|
1568
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestRunFormComponentExtended, { className: "TestRunFormComponentExtended", filePath: "src/lib/custom/Tests/test-run-form.component.ts", lineNumber: 36 }); })();
|
|
917
1569
|
export function LoadTestRunFormComponentExtended() {
|
|
918
1570
|
// Prevents tree-shaking
|
|
919
1571
|
}
|