@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.
Files changed (95) hide show
  1. package/dist/lib/custom/Tests/entity-link-pill.component.d.ts +44 -0
  2. package/dist/lib/custom/Tests/entity-link-pill.component.d.ts.map +1 -0
  3. package/dist/lib/custom/Tests/entity-link-pill.component.js +124 -0
  4. package/dist/lib/custom/Tests/entity-link-pill.component.js.map +1 -0
  5. package/dist/lib/custom/Tests/test-form.component.d.ts +94 -8
  6. package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
  7. package/dist/lib/custom/Tests/test-form.component.js +1527 -276
  8. package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
  9. package/dist/lib/custom/Tests/test-run-form.component.d.ts +48 -8
  10. package/dist/lib/custom/Tests/test-run-form.component.d.ts.map +1 -1
  11. package/dist/lib/custom/Tests/test-run-form.component.js +1078 -426
  12. package/dist/lib/custom/Tests/test-run-form.component.js.map +1 -1
  13. package/dist/lib/custom/Tests/test-suite-form.component.d.ts +227 -5
  14. package/dist/lib/custom/Tests/test-suite-form.component.d.ts.map +1 -1
  15. package/dist/lib/custom/Tests/test-suite-form.component.js +3307 -200
  16. package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
  17. package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts +86 -2
  18. package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts.map +1 -1
  19. package/dist/lib/custom/Tests/test-suite-run-form.component.js +1975 -262
  20. package/dist/lib/custom/Tests/test-suite-run-form.component.js.map +1 -1
  21. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts +9 -2
  22. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
  23. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +275 -244
  24. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
  25. package/dist/lib/custom/custom-forms.module.d.ts +27 -26
  26. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
  27. package/dist/lib/custom/custom-forms.module.js +9 -3
  28. package/dist/lib/custom/custom-forms.module.js.map +1 -1
  29. package/dist/lib/generated/Entities/AIAgent/aiagent.form.component.d.ts.map +1 -1
  30. package/dist/lib/generated/Entities/AIAgent/aiagent.form.component.js +154 -122
  31. package/dist/lib/generated/Entities/AIAgent/aiagent.form.component.js.map +1 -1
  32. package/dist/lib/generated/Entities/AIAgentModality/aiagentmodality.form.component.d.ts +11 -0
  33. package/dist/lib/generated/Entities/AIAgentModality/aiagentmodality.form.component.d.ts.map +1 -0
  34. package/dist/lib/generated/Entities/AIAgentModality/aiagentmodality.form.component.js +75 -0
  35. package/dist/lib/generated/Entities/AIAgentModality/aiagentmodality.form.component.js.map +1 -0
  36. package/dist/lib/generated/Entities/AIArchitecture/aiarchitecture.form.component.d.ts +11 -0
  37. package/dist/lib/generated/Entities/AIArchitecture/aiarchitecture.form.component.d.ts.map +1 -0
  38. package/dist/lib/generated/Entities/AIArchitecture/aiarchitecture.form.component.js +121 -0
  39. package/dist/lib/generated/Entities/AIArchitecture/aiarchitecture.form.component.js.map +1 -0
  40. package/dist/lib/generated/Entities/AIConfiguration/aiconfiguration.form.component.d.ts.map +1 -1
  41. package/dist/lib/generated/Entities/AIConfiguration/aiconfiguration.form.component.js +77 -41
  42. package/dist/lib/generated/Entities/AIConfiguration/aiconfiguration.form.component.js.map +1 -1
  43. package/dist/lib/generated/Entities/AIModality/aimodality.form.component.d.ts +11 -0
  44. package/dist/lib/generated/Entities/AIModality/aimodality.form.component.d.ts.map +1 -0
  45. package/dist/lib/generated/Entities/AIModality/aimodality.form.component.js +167 -0
  46. package/dist/lib/generated/Entities/AIModality/aimodality.form.component.js.map +1 -0
  47. package/dist/lib/generated/Entities/AIModel/aimodel.form.component.d.ts.map +1 -1
  48. package/dist/lib/generated/Entities/AIModel/aimodel.form.component.js +160 -102
  49. package/dist/lib/generated/Entities/AIModel/aimodel.form.component.js.map +1 -1
  50. package/dist/lib/generated/Entities/AIModelArchitecture/aimodelarchitecture.form.component.d.ts +11 -0
  51. package/dist/lib/generated/Entities/AIModelArchitecture/aimodelarchitecture.form.component.d.ts.map +1 -0
  52. package/dist/lib/generated/Entities/AIModelArchitecture/aimodelarchitecture.form.component.js +73 -0
  53. package/dist/lib/generated/Entities/AIModelArchitecture/aimodelarchitecture.form.component.js.map +1 -0
  54. package/dist/lib/generated/Entities/AIModelModality/aimodelmodality.form.component.d.ts +11 -0
  55. package/dist/lib/generated/Entities/AIModelModality/aimodelmodality.form.component.d.ts.map +1 -0
  56. package/dist/lib/generated/Entities/AIModelModality/aimodelmodality.form.component.js +89 -0
  57. package/dist/lib/generated/Entities/AIModelModality/aimodelmodality.form.component.js.map +1 -0
  58. package/dist/lib/generated/Entities/AIModelType/aimodeltype.form.component.d.ts.map +1 -1
  59. package/dist/lib/generated/Entities/AIModelType/aimodeltype.form.component.js +27 -13
  60. package/dist/lib/generated/Entities/AIModelType/aimodeltype.form.component.js.map +1 -1
  61. package/dist/lib/generated/Entities/ConversationDetail/conversationdetail.form.component.d.ts.map +1 -1
  62. package/dist/lib/generated/Entities/ConversationDetail/conversationdetail.form.component.js +39 -21
  63. package/dist/lib/generated/Entities/ConversationDetail/conversationdetail.form.component.js.map +1 -1
  64. package/dist/lib/generated/Entities/ConversationDetailAttachment/conversationdetailattachment.form.component.d.ts +11 -0
  65. package/dist/lib/generated/Entities/ConversationDetailAttachment/conversationdetailattachment.form.component.d.ts.map +1 -0
  66. package/dist/lib/generated/Entities/ConversationDetailAttachment/conversationdetailattachment.form.component.js +95 -0
  67. package/dist/lib/generated/Entities/ConversationDetailAttachment/conversationdetailattachment.form.component.js.map +1 -0
  68. package/dist/lib/generated/Entities/Entity/entity.form.component.d.ts.map +1 -1
  69. package/dist/lib/generated/Entities/Entity/entity.form.component.js +61 -43
  70. package/dist/lib/generated/Entities/Entity/entity.form.component.js.map +1 -1
  71. package/dist/lib/generated/Entities/File/file.form.component.d.ts.map +1 -1
  72. package/dist/lib/generated/Entities/File/file.form.component.js +22 -4
  73. package/dist/lib/generated/Entities/File/file.form.component.js.map +1 -1
  74. package/dist/lib/generated/Entities/FileStorageProvider/filestorageprovider.form.component.d.ts.map +1 -1
  75. package/dist/lib/generated/Entities/FileStorageProvider/filestorageprovider.form.component.js +40 -4
  76. package/dist/lib/generated/Entities/FileStorageProvider/filestorageprovider.form.component.js.map +1 -1
  77. package/dist/lib/generated/Entities/Test/test.form.component.js +17 -15
  78. package/dist/lib/generated/Entities/Test/test.form.component.js.map +1 -1
  79. package/dist/lib/generated/Entities/TestRun/testrun.form.component.d.ts.map +1 -1
  80. package/dist/lib/generated/Entities/TestRun/testrun.form.component.js +55 -43
  81. package/dist/lib/generated/Entities/TestRun/testrun.form.component.js.map +1 -1
  82. package/dist/lib/generated/Entities/TestRunFeedback/testrunfeedback.form.component.d.ts.map +1 -1
  83. package/dist/lib/generated/Entities/TestRunFeedback/testrunfeedback.form.component.js +9 -15
  84. package/dist/lib/generated/Entities/TestRunFeedback/testrunfeedback.form.component.js.map +1 -1
  85. package/dist/lib/generated/Entities/TestSuite/testsuite.form.component.d.ts.map +1 -1
  86. package/dist/lib/generated/Entities/TestSuite/testsuite.form.component.js +39 -19
  87. package/dist/lib/generated/Entities/TestSuite/testsuite.form.component.js.map +1 -1
  88. package/dist/lib/generated/Entities/TestSuiteRun/testsuiterun.form.component.d.ts.map +1 -1
  89. package/dist/lib/generated/Entities/TestSuiteRun/testsuiterun.form.component.js +40 -16
  90. package/dist/lib/generated/Entities/TestSuiteRun/testsuiterun.form.component.js.map +1 -1
  91. package/dist/lib/generated/generated-forms.module.d.ts +145 -134
  92. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
  93. package/dist/lib/generated/generated-forms.module.js +168 -87
  94. package/dist/lib/generated/generated-forms.module.js.map +1 -1
  95. package/package.json +28 -27
@@ -4,27 +4,36 @@ 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';
11
+ import { UserInfoEngine } from '@memberjunction/core-entities';
10
12
  import { BaseFormComponent } from '@memberjunction/ng-base-forms';
11
13
  import { RegisterClass } from '@memberjunction/global';
12
14
  import { SharedService } from '@memberjunction/ng-shared';
13
15
  import { TestSuiteRunFormComponent } from '../../generated/Entities/TestSuiteRun/testsuiterun.form.component';
16
+ import { TagsHelper, calculateEvaluationMetrics, normalizeExecutionStatus, getNeedsReviewItems } from '@memberjunction/ng-testing';
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 "@angular/common";
18
- import * as i4 from "@progress/kendo-angular-buttons";
20
+ import * as i3 from "@memberjunction/ng-testing";
21
+ import * as i4 from "@angular/common";
22
+ import * as i5 from "@angular/forms";
23
+ import * as i6 from "@progress/kendo-angular-dialog";
24
+ import * as i7 from "@progress/kendo-angular-buttons";
25
+ import * as i8 from "./entity-link-pill.component";
26
+ const _c0 = () => [1, 2, 3, 4, 5];
27
+ const _c1 = () => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
19
28
  function TestSuiteRunFormComponentExtended_div_2_Template(rf, ctx) { if (rf & 1) {
20
29
  const _r1 = i0.ɵɵgetCurrentView();
21
- i0.ɵɵelementStart(0, "div", 42)(1, "a", 43);
30
+ i0.ɵɵelementStart(0, "div", 61)(1, "a", 62);
22
31
  i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_2_Template_a_click_1_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openTestSuite()); });
23
- i0.ɵɵelement(2, "i", 44);
32
+ i0.ɵɵelement(2, "i", 63);
24
33
  i0.ɵɵtext(3);
25
34
  i0.ɵɵelementEnd();
26
- i0.ɵɵelement(4, "i", 45);
27
- i0.ɵɵelementStart(5, "span");
35
+ i0.ɵɵelement(4, "i", 64);
36
+ i0.ɵɵelementStart(5, "span", 65);
28
37
  i0.ɵɵtext(6);
29
38
  i0.ɵɵelementEnd()();
30
39
  } if (rf & 2) {
@@ -35,25 +44,140 @@ function TestSuiteRunFormComponentExtended_div_2_Template(rf, ctx) { if (rf & 1)
35
44
  i0.ɵɵtextInterpolate1("Run #", ctx_r1.record.ID.substring(0, 8), "");
36
45
  } }
37
46
  function TestSuiteRunFormComponentExtended_span_14_Template(rf, ctx) { if (rf & 1) {
38
- i0.ɵɵelementStart(0, "span", 46);
47
+ i0.ɵɵelementStart(0, "span", 66);
48
+ i0.ɵɵelement(1, "i", 67);
49
+ i0.ɵɵtext(2);
50
+ i0.ɵɵelementEnd();
51
+ } if (rf & 2) {
52
+ const ctx_r1 = i0.ɵɵnextContext();
53
+ i0.ɵɵadvance(2);
54
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.record.Environment, " ");
55
+ } }
56
+ function TestSuiteRunFormComponentExtended_span_15_Template(rf, ctx) { if (rf & 1) {
57
+ i0.ɵɵelementStart(0, "span", 68);
58
+ i0.ɵɵelement(1, "i", 69);
59
+ i0.ɵɵtext(2);
60
+ i0.ɵɵelementEnd();
61
+ } if (rf & 2) {
62
+ const ctx_r1 = i0.ɵɵnextContext();
63
+ i0.ɵɵadvance(2);
64
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.record.TriggerType, " ");
65
+ } }
66
+ function TestSuiteRunFormComponentExtended_button_18_Template(rf, ctx) { if (rf & 1) {
67
+ const _r3 = i0.ɵɵgetCurrentView();
68
+ i0.ɵɵelementStart(0, "button", 70);
69
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_button_18_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.reRunSuite()); });
70
+ i0.ɵɵelement(1, "i", 71);
71
+ i0.ɵɵtext(2, " Re-run Suite ");
72
+ i0.ɵɵelementEnd();
73
+ } }
74
+ function TestSuiteRunFormComponentExtended_div_96_div_4_span_1_Template(rf, ctx) { if (rf & 1) {
75
+ i0.ɵɵelementStart(0, "span", 82);
39
76
  i0.ɵɵtext(1);
40
77
  i0.ɵɵelementEnd();
78
+ } if (rf & 2) {
79
+ const tag_r5 = ctx.$implicit;
80
+ i0.ɵɵadvance();
81
+ i0.ɵɵtextInterpolate(tag_r5);
82
+ } }
83
+ function TestSuiteRunFormComponentExtended_div_96_div_4_Template(rf, ctx) { if (rf & 1) {
84
+ i0.ɵɵelementStart(0, "div", 80);
85
+ i0.ɵɵtemplate(1, TestSuiteRunFormComponentExtended_div_96_div_4_span_1_Template, 2, 1, "span", 81);
86
+ i0.ɵɵelementEnd();
87
+ } if (rf & 2) {
88
+ const ctx_r1 = i0.ɵɵnextContext(2);
89
+ i0.ɵɵadvance();
90
+ i0.ɵɵproperty("ngForOf", ctx_r1.tags);
91
+ } }
92
+ function TestSuiteRunFormComponentExtended_div_96_span_5_Template(rf, ctx) { if (rf & 1) {
93
+ i0.ɵɵelementStart(0, "span", 83);
94
+ i0.ɵɵtext(1, "No tags");
95
+ i0.ɵɵelementEnd();
96
+ } }
97
+ function TestSuiteRunFormComponentExtended_div_96_Template(rf, ctx) { if (rf & 1) {
98
+ const _r4 = i0.ɵɵgetCurrentView();
99
+ i0.ɵɵelementStart(0, "div", 72)(1, "div", 73)(2, "span", 74);
100
+ i0.ɵɵelement(3, "i", 75);
101
+ i0.ɵɵelementEnd();
102
+ i0.ɵɵtemplate(4, TestSuiteRunFormComponentExtended_div_96_div_4_Template, 2, 1, "div", 76)(5, TestSuiteRunFormComponentExtended_div_96_span_5_Template, 2, 0, "span", 77);
103
+ i0.ɵɵelementStart(6, "button", 78);
104
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_96_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.startEditingTags()); });
105
+ i0.ɵɵelement(7, "i", 79);
106
+ i0.ɵɵtext(8, " Add ");
107
+ i0.ɵɵelementEnd()()();
41
108
  } if (rf & 2) {
42
109
  const ctx_r1 = i0.ɵɵnextContext();
110
+ i0.ɵɵadvance(4);
111
+ i0.ɵɵproperty("ngIf", ctx_r1.tags.length > 0);
43
112
  i0.ɵɵadvance();
44
- i0.ɵɵtextInterpolate(ctx_r1.record.Environment);
113
+ i0.ɵɵproperty("ngIf", ctx_r1.tags.length === 0);
45
114
  } }
46
- function TestSuiteRunFormComponentExtended_span_15_Template(rf, ctx) { if (rf & 1) {
47
- i0.ɵɵelementStart(0, "span", 47);
115
+ function TestSuiteRunFormComponentExtended_div_97_span_7_Template(rf, ctx) { if (rf & 1) {
116
+ const _r7 = i0.ɵɵgetCurrentView();
117
+ i0.ɵɵelementStart(0, "span", 98);
48
118
  i0.ɵɵtext(1);
119
+ i0.ɵɵelementStart(2, "button", 99);
120
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_97_span_7_Template_button_click_2_listener() { const tag_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.removeTag(tag_r8)); });
121
+ i0.ɵɵelement(3, "i", 100);
122
+ i0.ɵɵelementEnd()();
123
+ } if (rf & 2) {
124
+ const tag_r8 = ctx.$implicit;
125
+ i0.ɵɵadvance();
126
+ i0.ɵɵtextInterpolate1(" ", tag_r8, " ");
127
+ } }
128
+ function TestSuiteRunFormComponentExtended_div_97_span_8_Template(rf, ctx) { if (rf & 1) {
129
+ i0.ɵɵelementStart(0, "span", 101);
130
+ i0.ɵɵtext(1, "No tags yet");
131
+ i0.ɵɵelementEnd();
132
+ } }
133
+ function TestSuiteRunFormComponentExtended_div_97_i_15_Template(rf, ctx) { if (rf & 1) {
134
+ i0.ɵɵelement(0, "i", 102);
135
+ } }
136
+ function TestSuiteRunFormComponentExtended_div_97_Template(rf, ctx) { if (rf & 1) {
137
+ const _r6 = i0.ɵɵgetCurrentView();
138
+ i0.ɵɵelementStart(0, "div", 84)(1, "div", 85)(2, "span", 86);
139
+ i0.ɵɵelement(3, "i", 75);
140
+ i0.ɵɵtext(4, " Edit Tags");
141
+ i0.ɵɵelementEnd()();
142
+ i0.ɵɵelementStart(5, "div", 87)(6, "div", 88);
143
+ i0.ɵɵtemplate(7, TestSuiteRunFormComponentExtended_div_97_span_7_Template, 4, 1, "span", 89)(8, TestSuiteRunFormComponentExtended_div_97_span_8_Template, 2, 0, "span", 90);
144
+ i0.ɵɵelementEnd();
145
+ i0.ɵɵelementStart(9, "div", 91)(10, "input", 92);
146
+ i0.ɵɵtwoWayListener("ngModelChange", function TestSuiteRunFormComponentExtended_div_97_Template_input_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newTag, $event) || (ctx_r1.newTag = $event); return i0.ɵɵresetView($event); });
147
+ i0.ɵɵlistener("keyup.enter", function TestSuiteRunFormComponentExtended_div_97_Template_input_keyup_enter_10_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.addTag()); });
148
+ i0.ɵɵelementEnd();
149
+ i0.ɵɵelementStart(11, "button", 93);
150
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_97_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.addTag()); });
151
+ i0.ɵɵelement(12, "i", 79);
152
+ i0.ɵɵelementEnd()()();
153
+ i0.ɵɵelementStart(13, "div", 94)(14, "button", 95);
154
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_97_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.saveTags()); });
155
+ i0.ɵɵtemplate(15, TestSuiteRunFormComponentExtended_div_97_i_15_Template, 1, 0, "i", 96);
156
+ i0.ɵɵtext(16);
49
157
  i0.ɵɵelementEnd();
158
+ i0.ɵɵelementStart(17, "button", 97);
159
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_97_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelEditingTags()); });
160
+ i0.ɵɵtext(18, "Cancel");
161
+ i0.ɵɵelementEnd()()();
50
162
  } if (rf & 2) {
51
163
  const ctx_r1 = i0.ɵɵnextContext();
164
+ i0.ɵɵadvance(7);
165
+ i0.ɵɵproperty("ngForOf", ctx_r1.tags);
52
166
  i0.ɵɵadvance();
53
- i0.ɵɵtextInterpolate(ctx_r1.record.TriggerType);
167
+ i0.ɵɵproperty("ngIf", ctx_r1.tags.length === 0);
168
+ i0.ɵɵadvance(2);
169
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newTag);
170
+ i0.ɵɵadvance();
171
+ i0.ɵɵproperty("disabled", !ctx_r1.newTag.trim());
172
+ i0.ɵɵadvance(3);
173
+ i0.ɵɵproperty("disabled", ctx_r1.savingTags);
174
+ i0.ɵɵadvance();
175
+ i0.ɵɵproperty("ngIf", ctx_r1.savingTags);
176
+ i0.ɵɵadvance();
177
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.savingTags ? "Saving..." : "Save", " ");
54
178
  } }
55
- function TestSuiteRunFormComponentExtended_span_88_Template(rf, ctx) { if (rf & 1) {
56
- i0.ɵɵelementStart(0, "span", 48);
179
+ function TestSuiteRunFormComponentExtended_span_106_Template(rf, ctx) { if (rf & 1) {
180
+ i0.ɵɵelementStart(0, "span", 103);
57
181
  i0.ɵɵtext(1);
58
182
  i0.ɵɵelementEnd();
59
183
  } if (rf & 2) {
@@ -61,222 +185,1309 @@ function TestSuiteRunFormComponentExtended_span_88_Template(rf, ctx) { if (rf &
61
185
  i0.ɵɵadvance();
62
186
  i0.ɵɵtextInterpolate(ctx_r1.testRuns.length);
63
187
  } }
64
- function TestSuiteRunFormComponentExtended_div_94_Template(rf, ctx) { if (rf & 1) {
65
- i0.ɵɵelementStart(0, "div", 49)(1, "div", 50)(2, "div", 51);
66
- i0.ɵɵelement(3, "i", 10);
188
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_2_div_11_Template(rf, ctx) { if (rf & 1) {
189
+ i0.ɵɵelementStart(0, "div", 123)(1, "span", 124);
190
+ i0.ɵɵtext(2, "Avg Rating");
191
+ i0.ɵɵelementEnd();
192
+ i0.ɵɵelementStart(3, "span", 125);
193
+ i0.ɵɵtext(4);
194
+ i0.ɵɵelementEnd()();
195
+ } if (rf & 2) {
196
+ const ctx_r1 = i0.ɵɵnextContext(4);
197
+ i0.ɵɵadvance(4);
198
+ i0.ɵɵtextInterpolate1("", ctx_r1.evaluationMetrics.humanAvgRating.toFixed(1), "/10");
199
+ } }
200
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_2_div_12_span_5_Template(rf, ctx) { if (rf & 1) {
201
+ i0.ɵɵelementStart(0, "span", 130);
202
+ i0.ɵɵtext(1);
203
+ i0.ɵɵelementEnd();
204
+ } if (rf & 2) {
205
+ const ctx_r1 = i0.ɵɵnextContext(5);
206
+ i0.ɵɵadvance();
207
+ i0.ɵɵtextInterpolate1("", ctx_r1.evaluationMetrics.humanIncorrectCount, " incorrect");
208
+ } }
209
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_2_div_12_Template(rf, ctx) { if (rf & 1) {
210
+ i0.ɵɵelementStart(0, "div", 123)(1, "span", 124);
211
+ i0.ɵɵtext(2, "Correct");
212
+ i0.ɵɵelementEnd();
213
+ i0.ɵɵelementStart(3, "span", 128);
214
+ i0.ɵɵtext(4);
215
+ i0.ɵɵelementEnd();
216
+ i0.ɵɵtemplate(5, TestSuiteRunFormComponentExtended_div_118_div_19_div_2_div_12_span_5_Template, 2, 1, "span", 129);
217
+ i0.ɵɵelementEnd();
218
+ } if (rf & 2) {
219
+ const ctx_r1 = i0.ɵɵnextContext(4);
220
+ i0.ɵɵadvance(4);
221
+ i0.ɵɵtextInterpolate(ctx_r1.evaluationMetrics.humanCorrectCount);
222
+ i0.ɵɵadvance();
223
+ i0.ɵɵproperty("ngIf", ctx_r1.evaluationMetrics.humanIncorrectCount > 0);
224
+ } }
225
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_2_div_13_Template(rf, ctx) { if (rf & 1) {
226
+ i0.ɵɵelementStart(0, "div", 131)(1, "span", 132);
227
+ i0.ɵɵelement(2, "i", 133);
228
+ i0.ɵɵtext(3);
229
+ i0.ɵɵelementEnd()();
230
+ } if (rf & 2) {
231
+ const ctx_r1 = i0.ɵɵnextContext(4);
232
+ i0.ɵɵadvance(3);
233
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.evaluationMetrics.humanPendingCount, " need review ");
234
+ } }
235
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_2_Template(rf, ctx) { if (rf & 1) {
236
+ i0.ɵɵelementStart(0, "div", 119)(1, "div", 120);
237
+ i0.ɵɵelement(2, "i", 121);
238
+ i0.ɵɵelementStart(3, "span");
239
+ i0.ɵɵtext(4, "Human Feedback");
240
+ i0.ɵɵelementEnd()();
241
+ i0.ɵɵelementStart(5, "div", 122)(6, "div", 123)(7, "span", 124);
242
+ i0.ɵɵtext(8, "Reviewed");
243
+ i0.ɵɵelementEnd();
244
+ i0.ɵɵelementStart(9, "span", 125);
245
+ i0.ɵɵtext(10);
246
+ i0.ɵɵelementEnd()();
247
+ i0.ɵɵtemplate(11, TestSuiteRunFormComponentExtended_div_118_div_19_div_2_div_11_Template, 5, 1, "div", 126)(12, TestSuiteRunFormComponentExtended_div_118_div_19_div_2_div_12_Template, 6, 2, "div", 126);
248
+ i0.ɵɵelementEnd();
249
+ i0.ɵɵtemplate(13, TestSuiteRunFormComponentExtended_div_118_div_19_div_2_div_13_Template, 4, 1, "div", 127);
250
+ i0.ɵɵelementEnd();
251
+ } if (rf & 2) {
252
+ const ctx_r1 = i0.ɵɵnextContext(3);
253
+ i0.ɵɵadvance(10);
254
+ i0.ɵɵtextInterpolate2("", ctx_r1.evaluationMetrics.humanReviewedCount, " / ", ctx_r1.evaluationMetrics.totalRuns, "");
255
+ i0.ɵɵadvance();
256
+ i0.ɵɵproperty("ngIf", ctx_r1.evaluationMetrics.humanReviewedCount > 0);
257
+ i0.ɵɵadvance();
258
+ i0.ɵɵproperty("ngIf", ctx_r1.evaluationMetrics.humanReviewedCount > 0);
259
+ i0.ɵɵadvance();
260
+ i0.ɵɵproperty("ngIf", ctx_r1.evaluationMetrics.humanPendingCount > 0);
261
+ } }
262
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_3_div_11_Template(rf, ctx) { if (rf & 1) {
263
+ i0.ɵɵelementStart(0, "div", 123)(1, "span", 124);
264
+ i0.ɵɵtext(2, "Avg Score");
265
+ i0.ɵɵelementEnd();
266
+ i0.ɵɵelementStart(3, "span", 125);
267
+ i0.ɵɵtext(4);
268
+ i0.ɵɵelementEnd()();
269
+ } if (rf & 2) {
270
+ const ctx_r1 = i0.ɵɵnextContext(4);
271
+ i0.ɵɵadvance(4);
272
+ i0.ɵɵtextInterpolate1("", (ctx_r1.evaluationMetrics.autoAvgScore * 100).toFixed(0), "%");
273
+ } }
274
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_3_div_12_Template(rf, ctx) { if (rf & 1) {
275
+ i0.ɵɵelementStart(0, "div", 123)(1, "span", 124);
276
+ i0.ɵɵtext(2, "Pass Rate");
67
277
  i0.ɵɵelementEnd();
68
- i0.ɵɵelementStart(4, "div", 52)(5, "h2");
278
+ i0.ɵɵelementStart(3, "span", 125);
279
+ i0.ɵɵtext(4);
280
+ i0.ɵɵelementEnd()();
281
+ } if (rf & 2) {
282
+ const ctx_r1 = i0.ɵɵnextContext(4);
283
+ i0.ɵɵadvance(4);
284
+ i0.ɵɵtextInterpolate1("", ctx_r1.evaluationMetrics.autoPassRate.toFixed(0), "%");
285
+ } }
286
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_3_Template(rf, ctx) { if (rf & 1) {
287
+ i0.ɵɵelementStart(0, "div", 119)(1, "div", 120);
288
+ i0.ɵɵelement(2, "i", 134);
289
+ i0.ɵɵelementStart(3, "span");
290
+ i0.ɵɵtext(4, "Auto Evaluation");
291
+ i0.ɵɵelementEnd()();
292
+ i0.ɵɵelementStart(5, "div", 122)(6, "div", 123)(7, "span", 124);
293
+ i0.ɵɵtext(8, "Evaluated");
294
+ i0.ɵɵelementEnd();
295
+ i0.ɵɵelementStart(9, "span", 125);
296
+ i0.ɵɵtext(10);
297
+ i0.ɵɵelementEnd()();
298
+ i0.ɵɵtemplate(11, TestSuiteRunFormComponentExtended_div_118_div_19_div_3_div_11_Template, 5, 1, "div", 126)(12, TestSuiteRunFormComponentExtended_div_118_div_19_div_3_div_12_Template, 5, 1, "div", 126);
299
+ i0.ɵɵelementEnd()();
300
+ } if (rf & 2) {
301
+ const ctx_r1 = i0.ɵɵnextContext(3);
302
+ i0.ɵɵadvance(10);
303
+ i0.ɵɵtextInterpolate2("", ctx_r1.evaluationMetrics.autoEvaluatedCount, " / ", ctx_r1.evaluationMetrics.totalRuns, "");
304
+ i0.ɵɵadvance();
305
+ i0.ɵɵproperty("ngIf", ctx_r1.evaluationMetrics.autoEvaluatedCount > 0);
306
+ i0.ɵɵadvance();
307
+ i0.ɵɵproperty("ngIf", ctx_r1.evaluationMetrics.autoEvaluatedCount > 0);
308
+ } }
309
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_4_div_16_span_3_Template(rf, ctx) { if (rf & 1) {
310
+ i0.ɵɵelementStart(0, "span", 138);
311
+ i0.ɵɵtext(1);
312
+ i0.ɵɵelementEnd();
313
+ } if (rf & 2) {
314
+ const ctx_r1 = i0.ɵɵnextContext(5);
315
+ i0.ɵɵadvance();
316
+ i0.ɵɵtextInterpolate1("", ctx_r1.evaluationMetrics.execErrorCount, " errors");
317
+ } }
318
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_4_div_16_span_4_Template(rf, ctx) { if (rf & 1) {
319
+ i0.ɵɵelementStart(0, "span", 139);
320
+ i0.ɵɵtext(1);
321
+ i0.ɵɵelementEnd();
322
+ } if (rf & 2) {
323
+ const ctx_r1 = i0.ɵɵnextContext(5);
324
+ i0.ɵɵadvance();
325
+ i0.ɵɵtextInterpolate1("", ctx_r1.evaluationMetrics.execTimeoutCount, " timeouts");
326
+ } }
327
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_4_div_16_Template(rf, ctx) { if (rf & 1) {
328
+ i0.ɵɵelementStart(0, "div", 123)(1, "span", 124);
329
+ i0.ɵɵtext(2, "Issues");
330
+ i0.ɵɵelementEnd();
331
+ i0.ɵɵtemplate(3, TestSuiteRunFormComponentExtended_div_118_div_19_div_4_div_16_span_3_Template, 2, 1, "span", 136)(4, TestSuiteRunFormComponentExtended_div_118_div_19_div_4_div_16_span_4_Template, 2, 1, "span", 137);
332
+ i0.ɵɵelementEnd();
333
+ } if (rf & 2) {
334
+ const ctx_r1 = i0.ɵɵnextContext(4);
335
+ i0.ɵɵadvance(3);
336
+ i0.ɵɵproperty("ngIf", ctx_r1.evaluationMetrics.execErrorCount > 0);
337
+ i0.ɵɵadvance();
338
+ i0.ɵɵproperty("ngIf", ctx_r1.evaluationMetrics.execTimeoutCount > 0);
339
+ } }
340
+ function TestSuiteRunFormComponentExtended_div_118_div_19_div_4_Template(rf, ctx) { if (rf & 1) {
341
+ i0.ɵɵelementStart(0, "div", 119)(1, "div", 120);
342
+ i0.ɵɵelement(2, "i", 135);
343
+ i0.ɵɵelementStart(3, "span");
344
+ i0.ɵɵtext(4, "Execution");
345
+ i0.ɵɵelementEnd()();
346
+ i0.ɵɵelementStart(5, "div", 122)(6, "div", 123)(7, "span", 124);
347
+ i0.ɵɵtext(8, "Completed");
348
+ i0.ɵɵelementEnd();
349
+ i0.ɵɵelementStart(9, "span", 125);
350
+ i0.ɵɵtext(10);
351
+ i0.ɵɵelementEnd()();
352
+ i0.ɵɵelementStart(11, "div", 123)(12, "span", 124);
353
+ i0.ɵɵtext(13, "Success Rate");
354
+ i0.ɵɵelementEnd();
355
+ i0.ɵɵelementStart(14, "span", 125);
356
+ i0.ɵɵtext(15);
357
+ i0.ɵɵelementEnd()();
358
+ i0.ɵɵtemplate(16, TestSuiteRunFormComponentExtended_div_118_div_19_div_4_div_16_Template, 5, 2, "div", 126);
359
+ i0.ɵɵelementEnd()();
360
+ } if (rf & 2) {
361
+ const ctx_r1 = i0.ɵɵnextContext(3);
362
+ i0.ɵɵadvance(10);
363
+ i0.ɵɵtextInterpolate2("", ctx_r1.evaluationMetrics.execCompletedCount, " / ", ctx_r1.evaluationMetrics.totalRuns, "");
364
+ i0.ɵɵadvance(5);
365
+ i0.ɵɵtextInterpolate1("", ctx_r1.evaluationMetrics.execSuccessRate.toFixed(0), "%");
366
+ i0.ɵɵadvance();
367
+ i0.ɵɵproperty("ngIf", ctx_r1.evaluationMetrics.execErrorCount > 0 || ctx_r1.evaluationMetrics.execTimeoutCount > 0);
368
+ } }
369
+ function TestSuiteRunFormComponentExtended_div_118_div_19_Template(rf, ctx) { if (rf & 1) {
370
+ i0.ɵɵelementStart(0, "div", 116)(1, "div", 117);
371
+ i0.ɵɵtemplate(2, TestSuiteRunFormComponentExtended_div_118_div_19_div_2_Template, 14, 5, "div", 118)(3, TestSuiteRunFormComponentExtended_div_118_div_19_div_3_Template, 13, 4, "div", 118)(4, TestSuiteRunFormComponentExtended_div_118_div_19_div_4_Template, 17, 4, "div", 118);
372
+ i0.ɵɵelementEnd()();
373
+ } if (rf & 2) {
374
+ const ctx_r1 = i0.ɵɵnextContext(2);
375
+ i0.ɵɵadvance(2);
376
+ i0.ɵɵproperty("ngIf", ctx_r1.evalPreferences.showHuman);
377
+ i0.ɵɵadvance();
378
+ i0.ɵɵproperty("ngIf", ctx_r1.evalPreferences.showAuto);
379
+ i0.ɵɵadvance();
380
+ i0.ɵɵproperty("ngIf", ctx_r1.evalPreferences.showExecution);
381
+ } }
382
+ function TestSuiteRunFormComponentExtended_div_118_div_20_div_8_i_2_Template(rf, ctx) { if (rf & 1) {
383
+ i0.ɵɵelement(0, "i", 157);
384
+ } }
385
+ function TestSuiteRunFormComponentExtended_div_118_div_20_div_8_i_3_Template(rf, ctx) { if (rf & 1) {
386
+ i0.ɵɵelement(0, "i", 158);
387
+ } }
388
+ function TestSuiteRunFormComponentExtended_div_118_div_20_div_8_i_4_Template(rf, ctx) { if (rf & 1) {
389
+ i0.ɵɵelement(0, "i", 133);
390
+ } }
391
+ function TestSuiteRunFormComponentExtended_div_118_div_20_div_8_Template(rf, ctx) { if (rf & 1) {
392
+ const _r9 = i0.ɵɵgetCurrentView();
393
+ i0.ɵɵelementStart(0, "div", 147);
394
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_118_div_20_div_8_Template_div_click_0_listener() { const item_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleRunExpanded(item_r10.run.id)); });
395
+ i0.ɵɵelementStart(1, "div", 148);
396
+ i0.ɵɵtemplate(2, TestSuiteRunFormComponentExtended_div_118_div_20_div_8_i_2_Template, 1, 0, "i", 149)(3, TestSuiteRunFormComponentExtended_div_118_div_20_div_8_i_3_Template, 1, 0, "i", 150)(4, TestSuiteRunFormComponentExtended_div_118_div_20_div_8_i_4_Template, 1, 0, "i", 151);
397
+ i0.ɵɵelementEnd();
398
+ i0.ɵɵelementStart(5, "div", 152)(6, "span", 153);
399
+ i0.ɵɵtext(7);
400
+ i0.ɵɵelementEnd();
401
+ i0.ɵɵelementStart(8, "span", 154);
402
+ i0.ɵɵtext(9);
403
+ i0.ɵɵelementEnd()();
404
+ i0.ɵɵelementStart(10, "div", 155);
405
+ i0.ɵɵelement(11, "i", 156);
406
+ i0.ɵɵelementEnd()();
407
+ } if (rf & 2) {
408
+ const item_r10 = ctx.$implicit;
409
+ i0.ɵɵclassProp("high-priority", item_r10.priority === "high")("medium-priority", item_r10.priority === "medium");
410
+ i0.ɵɵadvance(2);
411
+ i0.ɵɵproperty("ngIf", item_r10.priority === "high");
412
+ i0.ɵɵadvance();
413
+ i0.ɵɵproperty("ngIf", item_r10.priority === "medium");
414
+ i0.ɵɵadvance();
415
+ i0.ɵɵproperty("ngIf", item_r10.priority === "low");
416
+ i0.ɵɵadvance(3);
417
+ i0.ɵɵtextInterpolate(item_r10.run.testName);
418
+ i0.ɵɵadvance(2);
419
+ i0.ɵɵtextInterpolate(item_r10.reason);
420
+ } }
421
+ function TestSuiteRunFormComponentExtended_div_118_div_20_div_9_Template(rf, ctx) { if (rf & 1) {
422
+ const _r11 = i0.ɵɵgetCurrentView();
423
+ i0.ɵɵelementStart(0, "div", 159)(1, "button", 97);
424
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_118_div_20_div_9_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.changeTab("runs")); });
425
+ i0.ɵɵtext(2);
426
+ i0.ɵɵelementEnd()();
427
+ } if (rf & 2) {
428
+ const ctx_r1 = i0.ɵɵnextContext(3);
429
+ i0.ɵɵadvance(2);
430
+ i0.ɵɵtextInterpolate1(" View all ", ctx_r1.needsReviewItems.length, " items ");
431
+ } }
432
+ function TestSuiteRunFormComponentExtended_div_118_div_20_Template(rf, ctx) { if (rf & 1) {
433
+ i0.ɵɵelementStart(0, "div", 140)(1, "div", 141)(2, "h3");
434
+ i0.ɵɵelement(3, "i", 142);
435
+ i0.ɵɵtext(4, " Needs Review");
436
+ i0.ɵɵelementEnd();
437
+ i0.ɵɵelementStart(5, "span", 143);
69
438
  i0.ɵɵtext(6);
439
+ i0.ɵɵelementEnd()();
440
+ i0.ɵɵelementStart(7, "div", 144);
441
+ i0.ɵɵtemplate(8, TestSuiteRunFormComponentExtended_div_118_div_20_div_8_Template, 12, 9, "div", 145)(9, TestSuiteRunFormComponentExtended_div_118_div_20_div_9_Template, 3, 1, "div", 146);
442
+ i0.ɵɵelementEnd()();
443
+ } if (rf & 2) {
444
+ const ctx_r1 = i0.ɵɵnextContext(2);
445
+ i0.ɵɵadvance(6);
446
+ i0.ɵɵtextInterpolate1("", ctx_r1.needsReviewItems.length, " items");
447
+ i0.ɵɵadvance(2);
448
+ i0.ɵɵproperty("ngForOf", ctx_r1.needsReviewItems.slice(0, 5));
449
+ i0.ɵɵadvance();
450
+ i0.ɵɵproperty("ngIf", ctx_r1.needsReviewItems.length > 5);
451
+ } }
452
+ function TestSuiteRunFormComponentExtended_div_118_div_21_Template(rf, ctx) { if (rf & 1) {
453
+ i0.ɵɵelementStart(0, "div", 160)(1, "div", 161);
454
+ i0.ɵɵelement(2, "i", 162);
455
+ i0.ɵɵelementStart(3, "span");
456
+ i0.ɵɵtext(4, "Suite execution in progress...");
457
+ i0.ɵɵelementEnd()();
458
+ i0.ɵɵelementStart(5, "div", 163);
459
+ i0.ɵɵelement(6, "i", 164);
460
+ i0.ɵɵtext(7, " Auto-refreshing every 5 seconds ");
461
+ i0.ɵɵelementEnd()();
462
+ } }
463
+ function TestSuiteRunFormComponentExtended_div_118_Template(rf, ctx) { if (rf & 1) {
464
+ i0.ɵɵelementStart(0, "div", 104)(1, "div", 105)(2, "div", 106);
465
+ i0.ɵɵelement(3, "i", 6);
70
466
  i0.ɵɵelementEnd();
71
- i0.ɵɵelementStart(7, "div", 53);
72
- i0.ɵɵtext(8);
467
+ i0.ɵɵelementStart(4, "div", 107)(5, "h2");
468
+ i0.ɵɵtext(6);
73
469
  i0.ɵɵelementEnd();
74
- i0.ɵɵelementStart(9, "div", 54);
470
+ i0.ɵɵelementStart(7, "div", 108)(8, "div", 109)(9, "span", 110);
75
471
  i0.ɵɵtext(10);
76
- i0.ɵɵelementEnd()()()();
472
+ i0.ɵɵelementEnd();
473
+ i0.ɵɵelementStart(11, "span", 111);
474
+ i0.ɵɵtext(12, "Pass Rate");
475
+ i0.ɵɵelementEnd()();
476
+ i0.ɵɵelement(13, "div", 112);
477
+ i0.ɵɵelementStart(14, "div", 109)(15, "span", 110);
478
+ i0.ɵɵtext(16);
479
+ i0.ɵɵelementEnd();
480
+ i0.ɵɵelementStart(17, "span", 111);
481
+ i0.ɵɵtext(18, "Tests Passed");
482
+ i0.ɵɵelementEnd()()()()();
483
+ i0.ɵɵtemplate(19, TestSuiteRunFormComponentExtended_div_118_div_19_Template, 5, 3, "div", 113)(20, TestSuiteRunFormComponentExtended_div_118_div_20_Template, 10, 3, "div", 114)(21, TestSuiteRunFormComponentExtended_div_118_div_21_Template, 8, 0, "div", 115);
484
+ i0.ɵɵelementEnd();
77
485
  } if (rf & 2) {
78
486
  const ctx_r1 = i0.ɵɵnextContext();
79
487
  i0.ɵɵadvance();
80
- i0.ɵɵclassProp("passed", ctx_r1.record.Status === "Completed" && ctx_r1.getPassRate() >= 90)("failed", ctx_r1.record.Status === "Failed");
488
+ i0.ɵɵclassProp("passed", ctx_r1.record.Status === "Completed" && ctx_r1.getPassRate() >= 90)("failed", ctx_r1.record.Status === "Failed" || ctx_r1.getPassRate() < 50)("running", ctx_r1.record.Status === "Running")("pending", ctx_r1.record.Status === "Pending");
81
489
  i0.ɵɵadvance(2);
82
490
  i0.ɵɵproperty("ngClass", ctx_r1.getStatusIcon());
83
491
  i0.ɵɵadvance(3);
84
- i0.ɵɵtextInterpolate1("SUITE ", ctx_r1.record.Status.toUpperCase(), "");
492
+ i0.ɵɵtextInterpolate1("SUITE ", ctx_r1.record.Status.toUpperCase() || "UNKNOWN", "");
493
+ i0.ɵɵadvance(4);
494
+ i0.ɵɵtextInterpolate1("", ctx_r1.getPassRate().toFixed(1), "%");
495
+ i0.ɵɵadvance(6);
496
+ i0.ɵɵtextInterpolate2("", ctx_r1.record.PassedTests || 0, " / ", ctx_r1.record.TotalTests || 0, "");
497
+ i0.ɵɵadvance(3);
498
+ i0.ɵɵproperty("ngIf", ctx_r1.evaluationMetrics && ctx_r1.feedbacksLoaded);
499
+ i0.ɵɵadvance();
500
+ i0.ɵɵproperty("ngIf", ctx_r1.evalPreferences.showHuman && ctx_r1.needsReviewItems.length > 0 && ctx_r1.feedbacksLoaded);
501
+ i0.ɵɵadvance();
502
+ i0.ɵɵproperty("ngIf", ctx_r1.record.Status === "Running" || ctx_r1.record.Status === "Pending");
503
+ } }
504
+ function TestSuiteRunFormComponentExtended_div_119_div_1_button_4_Template(rf, ctx) { if (rf & 1) {
505
+ const _r13 = i0.ɵɵgetCurrentView();
506
+ i0.ɵɵelementStart(0, "button", 179);
507
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_1_button_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.setRunStatusFilter("Passed")); });
508
+ i0.ɵɵelement(1, "i", 180);
509
+ i0.ɵɵtext(2);
510
+ i0.ɵɵelementEnd();
511
+ } if (rf & 2) {
512
+ const ctx_r1 = i0.ɵɵnextContext(3);
513
+ i0.ɵɵclassProp("active", ctx_r1.runStatusFilter === "Passed");
514
+ i0.ɵɵadvance(2);
515
+ i0.ɵɵtextInterpolate1(" Passed (", ctx_r1.getRunCountByStatus("Passed"), ") ");
516
+ } }
517
+ function TestSuiteRunFormComponentExtended_div_119_div_1_button_5_Template(rf, ctx) { if (rf & 1) {
518
+ const _r14 = i0.ɵɵgetCurrentView();
519
+ i0.ɵɵelementStart(0, "button", 181);
520
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_1_button_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.setRunStatusFilter("Failed")); });
521
+ i0.ɵɵelement(1, "i", 100);
522
+ i0.ɵɵtext(2);
523
+ i0.ɵɵelementEnd();
524
+ } if (rf & 2) {
525
+ const ctx_r1 = i0.ɵɵnextContext(3);
526
+ i0.ɵɵclassProp("active", ctx_r1.runStatusFilter === "Failed");
527
+ i0.ɵɵadvance(2);
528
+ i0.ɵɵtextInterpolate1(" Failed (", ctx_r1.getRunCountByStatus("Failed"), ") ");
529
+ } }
530
+ function TestSuiteRunFormComponentExtended_div_119_div_1_button_6_Template(rf, ctx) { if (rf & 1) {
531
+ const _r15 = i0.ɵɵgetCurrentView();
532
+ i0.ɵɵelementStart(0, "button", 182);
533
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_1_button_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.setRunStatusFilter("Error")); });
534
+ i0.ɵɵelement(1, "i", 183);
535
+ i0.ɵɵtext(2);
536
+ i0.ɵɵelementEnd();
537
+ } if (rf & 2) {
538
+ const ctx_r1 = i0.ɵɵnextContext(3);
539
+ i0.ɵɵclassProp("active", ctx_r1.runStatusFilter === "Error");
540
+ i0.ɵɵadvance(2);
541
+ i0.ɵɵtextInterpolate1(" Error (", ctx_r1.getRunCountByStatus("Error"), ") ");
542
+ } }
543
+ function TestSuiteRunFormComponentExtended_div_119_div_1_Template(rf, ctx) { if (rf & 1) {
544
+ const _r12 = i0.ɵɵgetCurrentView();
545
+ i0.ɵɵelementStart(0, "div", 170)(1, "div", 171)(2, "button", 172);
546
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_1_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.setRunStatusFilter(null)); });
547
+ i0.ɵɵtext(3);
548
+ i0.ɵɵelementEnd();
549
+ i0.ɵɵtemplate(4, TestSuiteRunFormComponentExtended_div_119_div_1_button_4_Template, 3, 3, "button", 173)(5, TestSuiteRunFormComponentExtended_div_119_div_1_button_5_Template, 3, 3, "button", 174)(6, TestSuiteRunFormComponentExtended_div_119_div_1_button_6_Template, 3, 3, "button", 175);
550
+ i0.ɵɵelementEnd();
551
+ i0.ɵɵelementStart(7, "div", 176)(8, "button", 177);
552
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_1_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.exportToCSV()); });
553
+ i0.ɵɵelement(9, "i", 178);
554
+ i0.ɵɵtext(10, " Export CSV ");
555
+ i0.ɵɵelementEnd()()();
556
+ } if (rf & 2) {
557
+ const ctx_r1 = i0.ɵɵnextContext(2);
558
+ i0.ɵɵadvance(2);
559
+ i0.ɵɵclassProp("active", ctx_r1.runStatusFilter === null);
560
+ i0.ɵɵadvance();
561
+ i0.ɵɵtextInterpolate1(" All (", ctx_r1.testRuns.length, ") ");
562
+ i0.ɵɵadvance();
563
+ i0.ɵɵproperty("ngIf", ctx_r1.getRunCountByStatus("Passed") > 0);
564
+ i0.ɵɵadvance();
565
+ i0.ɵɵproperty("ngIf", ctx_r1.getRunCountByStatus("Failed") > 0);
566
+ i0.ɵɵadvance();
567
+ i0.ɵɵproperty("ngIf", ctx_r1.getRunCountByStatus("Error") > 0);
568
+ } }
569
+ function TestSuiteRunFormComponentExtended_div_119_div_2_div_2_Template(rf, ctx) { if (rf & 1) {
570
+ i0.ɵɵelementStart(0, "div", 187);
571
+ i0.ɵɵelement(1, "div", 188)(2, "div", 189);
572
+ i0.ɵɵelementStart(3, "div", 190);
573
+ i0.ɵɵelement(4, "div", 191)(5, "div", 192);
574
+ i0.ɵɵelementEnd()();
575
+ } }
576
+ function TestSuiteRunFormComponentExtended_div_119_div_2_Template(rf, ctx) { if (rf & 1) {
577
+ i0.ɵɵelementStart(0, "div", 184)(1, "div", 185);
578
+ i0.ɵɵtemplate(2, TestSuiteRunFormComponentExtended_div_119_div_2_div_2_Template, 6, 0, "div", 186);
579
+ i0.ɵɵelementEnd()();
580
+ } if (rf & 2) {
581
+ i0.ɵɵadvance(2);
582
+ i0.ɵɵproperty("ngForOf", i0.ɵɵpureFunction0(1, _c0));
583
+ } }
584
+ function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_span_12_Template(rf, ctx) { if (rf & 1) {
585
+ i0.ɵɵelementStart(0, "span", 211);
586
+ i0.ɵɵelement(1, "i", 18);
587
+ i0.ɵɵtext(2);
588
+ i0.ɵɵelementEnd();
589
+ } if (rf & 2) {
590
+ const run_r17 = i0.ɵɵnextContext().$implicit;
591
+ i0.ɵɵadvance(2);
592
+ i0.ɵɵtextInterpolate1(" ", run_r17.DurationSeconds.toFixed(1), "s ");
593
+ } }
594
+ function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_span_13_Template(rf, ctx) { if (rf & 1) {
595
+ i0.ɵɵelementStart(0, "span", 212);
596
+ i0.ɵɵelement(1, "i", 23);
597
+ i0.ɵɵtext(2);
598
+ i0.ɵɵelementEnd();
599
+ } if (rf & 2) {
600
+ const run_r17 = i0.ɵɵnextContext().$implicit;
601
+ i0.ɵɵadvance(2);
602
+ i0.ɵɵtextInterpolate1(" ", run_r17.CostUSD.toFixed(6), " ");
603
+ } }
604
+ function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_mj_entity_link_pill_14_Template(rf, ctx) { if (rf & 1) {
605
+ i0.ɵɵelement(0, "mj-entity-link-pill", 213);
606
+ } if (rf & 2) {
607
+ const run_r17 = i0.ɵɵnextContext().$implicit;
608
+ i0.ɵɵproperty("entityName", run_r17.TargetLogEntity)("recordId", run_r17.TargetLogID);
609
+ } }
610
+ function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_15_span_1_Template(rf, ctx) { if (rf & 1) {
611
+ i0.ɵɵelementStart(0, "span", 216);
612
+ i0.ɵɵtext(1);
613
+ i0.ɵɵelementEnd();
614
+ } if (rf & 2) {
615
+ const tag_r18 = ctx.$implicit;
616
+ i0.ɵɵadvance();
617
+ i0.ɵɵtextInterpolate(tag_r18);
618
+ } }
619
+ function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_15_Template(rf, ctx) { if (rf & 1) {
620
+ i0.ɵɵelementStart(0, "div", 214);
621
+ i0.ɵɵtemplate(1, TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_15_span_1_Template, 2, 1, "span", 215);
622
+ i0.ɵɵelementEnd();
623
+ } if (rf & 2) {
624
+ const run_r17 = i0.ɵɵnextContext().$implicit;
625
+ const ctx_r1 = i0.ɵɵnextContext(3);
626
+ i0.ɵɵadvance();
627
+ i0.ɵɵproperty("ngForOf", ctx_r1.getRunTags(run_r17));
628
+ } }
629
+ function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_button_7_Template(rf, ctx) { if (rf & 1) {
630
+ const _r20 = i0.ɵɵgetCurrentView();
631
+ i0.ɵɵelementStart(0, "button", 234);
632
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_button_7_Template_button_click_0_listener($event) { const num_r21 = i0.ɵɵrestoreView(_r20).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); ctx_r1.setInlineRating(num_r21); return i0.ɵɵresetView($event.stopPropagation()); })("mouseenter", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_button_7_Template_button_mouseenter_0_listener() { const num_r21 = i0.ɵɵrestoreView(_r20).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.inlineHoverRating = num_r21); })("mouseleave", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_button_7_Template_button_mouseleave_0_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.inlineHoverRating = 0); });
633
+ i0.ɵɵtext(1);
634
+ i0.ɵɵelementEnd();
635
+ } if (rf & 2) {
636
+ const num_r21 = ctx.$implicit;
637
+ const ctx_r1 = i0.ɵɵnextContext(5);
638
+ i0.ɵɵclassProp("selected", num_r21 === ctx_r1.inlineRating)("hover", num_r21 === ctx_r1.inlineHoverRating)("low", num_r21 <= 3)("mid", num_r21 >= 4 && num_r21 <= 6)("high", num_r21 >= 7);
639
+ i0.ɵɵadvance();
640
+ i0.ɵɵtextInterpolate1(" ", num_r21, " ");
641
+ } }
642
+ function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_div_8_Template(rf, ctx) { if (rf & 1) {
643
+ i0.ɵɵelementStart(0, "div", 235)(1, "span", 236);
644
+ i0.ɵɵtext(2);
645
+ i0.ɵɵelementEnd();
646
+ i0.ɵɵelementStart(3, "span", 237);
647
+ i0.ɵɵtext(4);
648
+ i0.ɵɵelementEnd()();
649
+ } if (rf & 2) {
650
+ const ctx_r1 = i0.ɵɵnextContext(5);
651
+ i0.ɵɵadvance(2);
652
+ i0.ɵɵtextInterpolate1("", ctx_r1.inlineRating, "/10");
653
+ i0.ɵɵadvance(2);
654
+ i0.ɵɵtextInterpolate(ctx_r1.getInlineRatingLabel());
655
+ } }
656
+ function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template(rf, ctx) { if (rf & 1) {
657
+ const _r19 = i0.ɵɵgetCurrentView();
658
+ i0.ɵɵelementStart(0, "div", 217);
659
+ i0.ɵɵelement(1, "div", 218);
660
+ i0.ɵɵelementStart(2, "div", 219)(3, "div", 220);
661
+ i0.ɵɵtext(4, "Quick Feedback");
662
+ i0.ɵɵelementEnd();
663
+ i0.ɵɵelementStart(5, "div", 221)(6, "div", 222);
664
+ i0.ɵɵtemplate(7, TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_button_7_Template, 2, 11, "button", 223);
665
+ i0.ɵɵelementEnd();
666
+ i0.ɵɵtemplate(8, TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_div_8_Template, 5, 2, "div", 224);
667
+ i0.ɵɵelementEnd();
668
+ i0.ɵɵelementStart(9, "div", 225)(10, "span", 226);
669
+ i0.ɵɵtext(11, "Was it correct?");
670
+ i0.ɵɵelementEnd();
671
+ i0.ɵɵelementStart(12, "div", 227)(13, "label", 228);
672
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template_label_click_13_listener($event) { i0.ɵɵrestoreView(_r19); return i0.ɵɵresetView($event.stopPropagation()); });
673
+ i0.ɵɵelementStart(14, "input", 229);
674
+ i0.ɵɵtwoWayListener("ngModelChange", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template_input_ngModelChange_14_listener($event) { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.inlineIsCorrect, $event) || (ctx_r1.inlineIsCorrect = $event); return i0.ɵɵresetView($event); });
675
+ i0.ɵɵelementEnd();
676
+ i0.ɵɵelementStart(15, "span");
677
+ i0.ɵɵtext(16, "Yes");
678
+ i0.ɵɵelementEnd()();
679
+ i0.ɵɵelementStart(17, "label", 228);
680
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template_label_click_17_listener($event) { i0.ɵɵrestoreView(_r19); return i0.ɵɵresetView($event.stopPropagation()); });
681
+ i0.ɵɵelementStart(18, "input", 229);
682
+ i0.ɵɵtwoWayListener("ngModelChange", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template_input_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.inlineIsCorrect, $event) || (ctx_r1.inlineIsCorrect = $event); return i0.ɵɵresetView($event); });
683
+ i0.ɵɵelementEnd();
684
+ i0.ɵɵelementStart(19, "span");
685
+ i0.ɵɵtext(20, "No");
686
+ i0.ɵɵelementEnd()();
687
+ i0.ɵɵelementStart(21, "label", 228);
688
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template_label_click_21_listener($event) { i0.ɵɵrestoreView(_r19); return i0.ɵɵresetView($event.stopPropagation()); });
689
+ i0.ɵɵelementStart(22, "input", 229);
690
+ i0.ɵɵtwoWayListener("ngModelChange", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template_input_ngModelChange_22_listener($event) { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.inlineIsCorrect, $event) || (ctx_r1.inlineIsCorrect = $event); return i0.ɵɵresetView($event); });
691
+ i0.ɵɵelementEnd();
692
+ i0.ɵɵelementStart(23, "span");
693
+ i0.ɵɵtext(24, "Not Sure");
694
+ i0.ɵɵelementEnd()()()();
695
+ i0.ɵɵelementStart(25, "div", 230);
696
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template_div_click_25_listener($event) { i0.ɵɵrestoreView(_r19); return i0.ɵɵresetView($event.stopPropagation()); });
697
+ i0.ɵɵelementStart(26, "textarea", 231);
698
+ i0.ɵɵtwoWayListener("ngModelChange", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template_textarea_ngModelChange_26_listener($event) { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.inlineComments, $event) || (ctx_r1.inlineComments = $event); return i0.ɵɵresetView($event); });
699
+ i0.ɵɵelementEnd()();
700
+ i0.ɵɵelementStart(27, "div", 232);
701
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template_div_click_27_listener($event) { i0.ɵɵrestoreView(_r19); return i0.ɵɵresetView($event.stopPropagation()); });
702
+ i0.ɵɵelementStart(28, "button", 177);
703
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template_button_click_28_listener() { i0.ɵɵrestoreView(_r19); const run_r17 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openTestRun(run_r17.ID)); });
704
+ i0.ɵɵelement(29, "i", 233);
705
+ i0.ɵɵtext(30, " View Full Details ");
706
+ i0.ɵɵelementEnd();
707
+ i0.ɵɵelementStart(31, "button", 95);
708
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template_button_click_31_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.saveInlineFeedback()); });
709
+ i0.ɵɵelement(32, "i", 6);
710
+ i0.ɵɵtext(33);
711
+ i0.ɵɵelementEnd()()()();
712
+ } if (rf & 2) {
713
+ const run_r17 = i0.ɵɵnextContext().$implicit;
714
+ const ctx_r1 = i0.ɵɵnextContext(3);
715
+ i0.ɵɵadvance(7);
716
+ i0.ɵɵproperty("ngForOf", i0.ɵɵpureFunction0(18, _c1));
717
+ i0.ɵɵadvance();
718
+ i0.ɵɵproperty("ngIf", ctx_r1.inlineRating > 0);
719
+ i0.ɵɵadvance(6);
720
+ i0.ɵɵpropertyInterpolate1("name", "correct-", run_r17.ID, "");
721
+ i0.ɵɵproperty("value", true);
722
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.inlineIsCorrect);
723
+ i0.ɵɵadvance(4);
724
+ i0.ɵɵpropertyInterpolate1("name", "correct-", run_r17.ID, "");
725
+ i0.ɵɵproperty("value", false);
726
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.inlineIsCorrect);
727
+ i0.ɵɵadvance(4);
728
+ i0.ɵɵpropertyInterpolate1("name", "correct-", run_r17.ID, "");
729
+ i0.ɵɵproperty("value", null);
730
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.inlineIsCorrect);
731
+ i0.ɵɵadvance(4);
732
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.inlineComments);
733
+ i0.ɵɵadvance(5);
734
+ i0.ɵɵproperty("disabled", !ctx_r1.canSubmitInlineFeedback() || ctx_r1.savingInlineFeedback);
735
+ i0.ɵɵadvance();
736
+ i0.ɵɵproperty("ngClass", ctx_r1.savingInlineFeedback ? "fa-spinner fa-spin" : "fa-save");
737
+ i0.ɵɵadvance();
738
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.savingInlineFeedback ? "Saving..." : ctx_r1.hasFeedback(run_r17.ID) ? "Update" : "Save", " ");
739
+ } }
740
+ function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_Template(rf, ctx) { if (rf & 1) {
741
+ const _r16 = i0.ɵɵgetCurrentView();
742
+ i0.ɵɵelementStart(0, "div", 195)(1, "div", 196);
743
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_3_div_1_Template_div_click_1_listener() { const run_r17 = i0.ɵɵrestoreView(_r16).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleRunExpanded(run_r17.ID)); });
744
+ i0.ɵɵelementStart(2, "div", 197);
745
+ i0.ɵɵtext(3);
746
+ i0.ɵɵelementEnd();
747
+ i0.ɵɵelementStart(4, "div", 198);
748
+ i0.ɵɵelement(5, "i", 6);
749
+ i0.ɵɵelementEnd();
750
+ i0.ɵɵelementStart(6, "div", 199)(7, "div", 200)(8, "div", 201);
751
+ i0.ɵɵtext(9);
752
+ i0.ɵɵelementEnd();
753
+ i0.ɵɵelement(10, "app-evaluation-badge", 202);
754
+ i0.ɵɵelementEnd();
755
+ i0.ɵɵelementStart(11, "div", 203);
756
+ i0.ɵɵtemplate(12, TestSuiteRunFormComponentExtended_div_119_div_3_div_1_span_12_Template, 3, 1, "span", 204)(13, TestSuiteRunFormComponentExtended_div_119_div_3_div_1_span_13_Template, 3, 1, "span", 205)(14, TestSuiteRunFormComponentExtended_div_119_div_3_div_1_mj_entity_link_pill_14_Template, 1, 2, "mj-entity-link-pill", 206);
757
+ i0.ɵɵelementEnd();
758
+ i0.ɵɵtemplate(15, TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_15_Template, 2, 1, "div", 207);
759
+ i0.ɵɵelementEnd();
760
+ i0.ɵɵelementStart(16, "div", 208);
761
+ i0.ɵɵelement(17, "i", 209);
762
+ i0.ɵɵelementEnd()();
763
+ i0.ɵɵtemplate(18, TestSuiteRunFormComponentExtended_div_119_div_3_div_1_div_18_Template, 34, 19, "div", 210);
764
+ i0.ɵɵelementEnd();
765
+ } if (rf & 2) {
766
+ const run_r17 = ctx.$implicit;
767
+ const ctx_r1 = i0.ɵɵnextContext(3);
768
+ i0.ɵɵadvance(3);
769
+ i0.ɵɵtextInterpolate(run_r17.Sequence || "-");
770
+ i0.ɵɵadvance();
771
+ i0.ɵɵstyleProp("background-color", ctx_r1.getRunStatusColor(run_r17.Status));
772
+ i0.ɵɵadvance();
773
+ i0.ɵɵproperty("ngClass", ctx_r1.getRunStatusIcon(run_r17.Status));
774
+ i0.ɵɵadvance(4);
775
+ i0.ɵɵtextInterpolate(run_r17.Test);
776
+ i0.ɵɵadvance();
777
+ i0.ɵɵproperty("executionStatus", run_r17.Status)("originalStatus", run_r17.Status)("autoScore", run_r17.Score)("humanRating", ctx_r1.getFeedbackRating(run_r17.ID) || null)("humanIsCorrect", ctx_r1.getHumanIsCorrect(run_r17.ID))("hasHumanFeedback", ctx_r1.hasFeedback(run_r17.ID))("preferences", ctx_r1.evalPreferences)("mode", "compact");
85
778
  i0.ɵɵadvance(2);
86
- i0.ɵɵtextInterpolate1("Pass Rate: ", ctx_r1.getPassRate().toFixed(1), "%");
779
+ i0.ɵɵproperty("ngIf", run_r17.DurationSeconds);
780
+ i0.ɵɵadvance();
781
+ i0.ɵɵproperty("ngIf", run_r17.CostUSD);
782
+ i0.ɵɵadvance();
783
+ i0.ɵɵproperty("ngIf", run_r17.TargetLogEntityID && run_r17.TargetLogID);
784
+ i0.ɵɵadvance();
785
+ i0.ɵɵproperty("ngIf", ctx_r1.getRunTags(run_r17).length > 0);
87
786
  i0.ɵɵadvance(2);
88
- i0.ɵɵtextInterpolate2("", ctx_r1.record.PassedTests, " of ", ctx_r1.record.TotalTests, " tests passed");
787
+ i0.ɵɵclassProp("fa-chevron-down", ctx_r1.expandedRunId !== run_r17.ID)("fa-chevron-up", ctx_r1.expandedRunId === run_r17.ID);
788
+ i0.ɵɵadvance();
789
+ i0.ɵɵproperty("ngIf", ctx_r1.expandedRunId === run_r17.ID);
790
+ } }
791
+ function TestSuiteRunFormComponentExtended_div_119_div_3_Template(rf, ctx) { if (rf & 1) {
792
+ i0.ɵɵelementStart(0, "div", 193);
793
+ i0.ɵɵtemplate(1, TestSuiteRunFormComponentExtended_div_119_div_3_div_1_Template, 19, 22, "div", 194);
794
+ i0.ɵɵelementEnd();
795
+ } if (rf & 2) {
796
+ const ctx_r1 = i0.ɵɵnextContext(2);
797
+ i0.ɵɵadvance();
798
+ i0.ɵɵproperty("ngForOf", ctx_r1.getFilteredTestRuns());
799
+ } }
800
+ function TestSuiteRunFormComponentExtended_div_119_div_4_Template(rf, ctx) { if (rf & 1) {
801
+ i0.ɵɵelementStart(0, "div", 238)(1, "div", 239);
802
+ i0.ɵɵelement(2, "i", 240);
803
+ i0.ɵɵelementEnd();
804
+ i0.ɵɵelementStart(3, "h4");
805
+ i0.ɵɵtext(4, "No Test Runs Found");
806
+ i0.ɵɵelementEnd();
807
+ i0.ɵɵelementStart(5, "p");
808
+ i0.ɵɵtext(6, "No test runs have been recorded for this suite execution.");
809
+ i0.ɵɵelementEnd()();
810
+ } }
811
+ function TestSuiteRunFormComponentExtended_div_119_div_5_Template(rf, ctx) { if (rf & 1) {
812
+ const _r22 = i0.ɵɵgetCurrentView();
813
+ i0.ɵɵelementStart(0, "div", 238)(1, "div", 239);
814
+ i0.ɵɵelement(2, "i", 241);
815
+ i0.ɵɵelementEnd();
816
+ i0.ɵɵelementStart(3, "h4");
817
+ i0.ɵɵtext(4, "No Matching Runs");
818
+ i0.ɵɵelementEnd();
819
+ i0.ɵɵelementStart(5, "p");
820
+ i0.ɵɵtext(6, "No test runs match the current filter.");
821
+ i0.ɵɵelementEnd();
822
+ i0.ɵɵelementStart(7, "button", 177);
823
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_119_div_5_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r22); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.setRunStatusFilter(null)); });
824
+ i0.ɵɵtext(8, "Clear Filter");
825
+ i0.ɵɵelementEnd()();
826
+ } }
827
+ function TestSuiteRunFormComponentExtended_div_119_Template(rf, ctx) { if (rf & 1) {
828
+ i0.ɵɵelementStart(0, "div", 165);
829
+ i0.ɵɵtemplate(1, TestSuiteRunFormComponentExtended_div_119_div_1_Template, 11, 6, "div", 166)(2, TestSuiteRunFormComponentExtended_div_119_div_2_Template, 3, 2, "div", 167)(3, TestSuiteRunFormComponentExtended_div_119_div_3_Template, 2, 1, "div", 168)(4, TestSuiteRunFormComponentExtended_div_119_div_4_Template, 7, 0, "div", 169)(5, TestSuiteRunFormComponentExtended_div_119_div_5_Template, 9, 0, "div", 169);
830
+ i0.ɵɵelementEnd();
831
+ } if (rf & 2) {
832
+ const ctx_r1 = i0.ɵɵnextContext();
833
+ i0.ɵɵadvance();
834
+ i0.ɵɵproperty("ngIf", ctx_r1.testRunsLoaded && ctx_r1.testRuns.length > 0);
835
+ i0.ɵɵadvance();
836
+ i0.ɵɵproperty("ngIf", ctx_r1.loadingTestRuns);
837
+ i0.ɵɵadvance();
838
+ i0.ɵɵproperty("ngIf", !ctx_r1.loadingTestRuns && ctx_r1.testRuns.length > 0);
839
+ i0.ɵɵadvance();
840
+ i0.ɵɵproperty("ngIf", ctx_r1.testRunsLoaded && !ctx_r1.loadingTestRuns && ctx_r1.testRuns.length === 0);
841
+ i0.ɵɵadvance();
842
+ i0.ɵɵproperty("ngIf", ctx_r1.testRunsLoaded && !ctx_r1.loadingTestRuns && ctx_r1.testRuns.length > 0 && ctx_r1.getFilteredTestRuns().length === 0);
843
+ } }
844
+ function TestSuiteRunFormComponentExtended_div_120_a_15_Template(rf, ctx) { if (rf & 1) {
845
+ const _r23 = i0.ɵɵgetCurrentView();
846
+ i0.ɵɵelementStart(0, "a", 62);
847
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_120_a_15_Template_a_click_0_listener() { i0.ɵɵrestoreView(_r23); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.openTestSuite()); });
848
+ i0.ɵɵtext(1);
849
+ i0.ɵɵelementEnd();
850
+ } if (rf & 2) {
851
+ const ctx_r1 = i0.ɵɵnextContext(2);
852
+ i0.ɵɵadvance();
853
+ i0.ɵɵtextInterpolate(ctx_r1.testSuite.Name);
854
+ } }
855
+ function TestSuiteRunFormComponentExtended_div_120_span_16_Template(rf, ctx) { if (rf & 1) {
856
+ i0.ɵɵelementStart(0, "span");
857
+ i0.ɵɵtext(1, "Loading...");
858
+ i0.ɵɵelementEnd();
859
+ } }
860
+ function TestSuiteRunFormComponentExtended_div_120_Template(rf, ctx) { if (rf & 1) {
861
+ i0.ɵɵelementStart(0, "div", 242)(1, "div", 243)(2, "h3");
862
+ i0.ɵɵelement(3, "i", 47);
863
+ i0.ɵɵtext(4, " Run Information");
864
+ i0.ɵɵelementEnd();
865
+ i0.ɵɵelementStart(5, "div", 244)(6, "div", 245)(7, "div", 246);
866
+ i0.ɵɵtext(8, "Run ID");
867
+ i0.ɵɵelementEnd();
868
+ i0.ɵɵelementStart(9, "div", 247);
869
+ i0.ɵɵtext(10);
870
+ i0.ɵɵelementEnd()();
871
+ i0.ɵɵelementStart(11, "div", 245)(12, "div", 246);
872
+ i0.ɵɵtext(13, "Test Suite");
873
+ i0.ɵɵelementEnd();
874
+ i0.ɵɵelementStart(14, "div", 248);
875
+ i0.ɵɵtemplate(15, TestSuiteRunFormComponentExtended_div_120_a_15_Template, 2, 1, "a", 249)(16, TestSuiteRunFormComponentExtended_div_120_span_16_Template, 2, 0, "span", 250);
876
+ i0.ɵɵelementEnd()();
877
+ i0.ɵɵelementStart(17, "div", 245)(18, "div", 246);
878
+ i0.ɵɵtext(19, "Status");
879
+ i0.ɵɵelementEnd();
880
+ i0.ɵɵelementStart(20, "div", 248)(21, "span", 251);
881
+ i0.ɵɵtext(22);
882
+ i0.ɵɵelementEnd()()();
883
+ i0.ɵɵelementStart(23, "div", 245)(24, "div", 246);
884
+ i0.ɵɵtext(25, "Run By");
885
+ i0.ɵɵelementEnd();
886
+ i0.ɵɵelementStart(26, "div", 248);
887
+ i0.ɵɵtext(27);
888
+ i0.ɵɵelementEnd()();
889
+ i0.ɵɵelementStart(28, "div", 245)(29, "div", 246);
890
+ i0.ɵɵtext(30, "Started At");
891
+ i0.ɵɵelementEnd();
892
+ i0.ɵɵelementStart(31, "div", 248);
893
+ i0.ɵɵtext(32);
894
+ i0.ɵɵpipe(33, "date");
895
+ i0.ɵɵelementEnd()();
896
+ i0.ɵɵelementStart(34, "div", 245)(35, "div", 246);
897
+ i0.ɵɵtext(36, "Completed At");
898
+ i0.ɵɵelementEnd();
899
+ i0.ɵɵelementStart(37, "div", 248);
900
+ i0.ɵɵtext(38);
901
+ i0.ɵɵpipe(39, "date");
902
+ i0.ɵɵelementEnd()();
903
+ i0.ɵɵelementStart(40, "div", 245)(41, "div", 246);
904
+ i0.ɵɵtext(42, "Environment");
905
+ i0.ɵɵelementEnd();
906
+ i0.ɵɵelementStart(43, "div", 248);
907
+ i0.ɵɵtext(44);
908
+ i0.ɵɵelementEnd()();
909
+ i0.ɵɵelementStart(45, "div", 245)(46, "div", 246);
910
+ i0.ɵɵtext(47, "Trigger Type");
911
+ i0.ɵɵelementEnd();
912
+ i0.ɵɵelementStart(48, "div", 248);
913
+ i0.ɵɵtext(49);
914
+ i0.ɵɵelementEnd()();
915
+ i0.ɵɵelementStart(50, "div", 245)(51, "div", 246);
916
+ i0.ɵɵtext(52, "Git Commit");
917
+ i0.ɵɵelementEnd();
918
+ i0.ɵɵelementStart(53, "div", 247);
919
+ i0.ɵɵtext(54);
920
+ i0.ɵɵelementEnd()();
921
+ i0.ɵɵelementStart(55, "div", 245)(56, "div", 246);
922
+ i0.ɵɵtext(57, "Agent Version");
923
+ i0.ɵɵelementEnd();
924
+ i0.ɵɵelementStart(58, "div", 248);
925
+ i0.ɵɵtext(59);
926
+ i0.ɵɵelementEnd()()()()();
927
+ } if (rf & 2) {
928
+ const ctx_r1 = i0.ɵɵnextContext();
929
+ i0.ɵɵadvance(10);
930
+ i0.ɵɵtextInterpolate(ctx_r1.record.ID);
931
+ i0.ɵɵadvance(5);
932
+ i0.ɵɵproperty("ngIf", ctx_r1.testSuite);
933
+ i0.ɵɵadvance();
934
+ i0.ɵɵproperty("ngIf", !ctx_r1.testSuite);
935
+ i0.ɵɵadvance(5);
936
+ i0.ɵɵproperty("ngClass", ctx_r1.getStatusClass());
937
+ i0.ɵɵadvance();
938
+ i0.ɵɵtextInterpolate(ctx_r1.record.Status);
939
+ i0.ɵɵadvance(5);
940
+ i0.ɵɵtextInterpolate(ctx_r1.record.RunByUser || "N/A");
941
+ i0.ɵɵadvance(5);
942
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(33, 12, ctx_r1.record.StartedAt, "medium"));
943
+ i0.ɵɵadvance(6);
944
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(39, 15, ctx_r1.record.CompletedAt, "medium"));
945
+ i0.ɵɵadvance(6);
946
+ i0.ɵɵtextInterpolate(ctx_r1.record.Environment || "N/A");
947
+ i0.ɵɵadvance(5);
948
+ i0.ɵɵtextInterpolate(ctx_r1.record.TriggerType || "N/A");
949
+ i0.ɵɵadvance(5);
950
+ i0.ɵɵtextInterpolate(ctx_r1.record.GitCommit || "N/A");
951
+ i0.ɵɵadvance(5);
952
+ i0.ɵɵtextInterpolate(ctx_r1.record.AgentVersion || "N/A");
953
+ } }
954
+ function TestSuiteRunFormComponentExtended_div_121_div_1_Template(rf, ctx) { if (rf & 1) {
955
+ i0.ɵɵelementStart(0, "div", 255);
956
+ i0.ɵɵelement(1, "i", 102);
957
+ i0.ɵɵelementStart(2, "span");
958
+ i0.ɵɵtext(3, "Loading test results...");
959
+ i0.ɵɵelementEnd()();
960
+ } }
961
+ function TestSuiteRunFormComponentExtended_div_121_div_2_Template(rf, ctx) { if (rf & 1) {
962
+ i0.ɵɵelementStart(0, "div", 256)(1, "h3");
963
+ i0.ɵɵelement(2, "i", 257);
964
+ i0.ɵɵtext(3, " Summary Statistics");
965
+ i0.ɵɵelementEnd();
966
+ i0.ɵɵelementStart(4, "div", 258)(5, "div", 259)(6, "div", 260);
967
+ i0.ɵɵelement(7, "i", 28);
968
+ i0.ɵɵelementEnd();
969
+ i0.ɵɵelementStart(8, "div", 261)(9, "div", 110);
970
+ i0.ɵɵtext(10);
971
+ i0.ɵɵelementEnd();
972
+ i0.ɵɵelementStart(11, "div", 111);
973
+ i0.ɵɵtext(12, "Passed");
974
+ i0.ɵɵelementEnd();
975
+ i0.ɵɵelementStart(13, "div", 262);
976
+ i0.ɵɵtext(14);
977
+ i0.ɵɵelementEnd()()();
978
+ i0.ɵɵelementStart(15, "div", 259)(16, "div", 263);
979
+ i0.ɵɵelement(17, "i", 33);
980
+ i0.ɵɵelementEnd();
981
+ i0.ɵɵelementStart(18, "div", 261)(19, "div", 110);
982
+ i0.ɵɵtext(20);
983
+ i0.ɵɵelementEnd();
984
+ i0.ɵɵelementStart(21, "div", 111);
985
+ i0.ɵɵtext(22, "Failed");
986
+ i0.ɵɵelementEnd();
987
+ i0.ɵɵelementStart(23, "div", 262);
988
+ i0.ɵɵtext(24);
989
+ i0.ɵɵelementEnd()()();
990
+ i0.ɵɵelementStart(25, "div", 259)(26, "div", 264);
991
+ i0.ɵɵelement(27, "i", 265);
992
+ i0.ɵɵelementEnd();
993
+ i0.ɵɵelementStart(28, "div", 261)(29, "div", 110);
994
+ i0.ɵɵtext(30);
995
+ i0.ɵɵelementEnd();
996
+ i0.ɵɵelementStart(31, "div", 111);
997
+ i0.ɵɵtext(32, "Avg Score");
998
+ i0.ɵɵelementEnd()()();
999
+ i0.ɵɵelementStart(33, "div", 259)(34, "div", 266);
1000
+ i0.ɵɵelement(35, "i", 18);
1001
+ i0.ɵɵelementEnd();
1002
+ i0.ɵɵelementStart(36, "div", 261)(37, "div", 110);
1003
+ i0.ɵɵtext(38);
1004
+ i0.ɵɵelementEnd();
1005
+ i0.ɵɵelementStart(39, "div", 111);
1006
+ i0.ɵɵtext(40, "Avg Duration");
1007
+ i0.ɵɵelementEnd()()();
1008
+ i0.ɵɵelementStart(41, "div", 259)(42, "div", 267);
1009
+ i0.ɵɵelement(43, "i", 23);
1010
+ i0.ɵɵelementEnd();
1011
+ i0.ɵɵelementStart(44, "div", 261)(45, "div", 110);
1012
+ i0.ɵɵtext(46);
1013
+ i0.ɵɵelementEnd();
1014
+ i0.ɵɵelementStart(47, "div", 111);
1015
+ i0.ɵɵtext(48, "Total Cost");
1016
+ i0.ɵɵelementEnd()()()()();
1017
+ } if (rf & 2) {
1018
+ const ctx_r1 = i0.ɵɵnextContext(2);
1019
+ i0.ɵɵadvance(10);
1020
+ i0.ɵɵtextInterpolate(ctx_r1.getPassedCount());
1021
+ i0.ɵɵadvance(4);
1022
+ i0.ɵɵtextInterpolate1("", ctx_r1.getPassedPercent().toFixed(1), "%");
1023
+ i0.ɵɵadvance(6);
1024
+ i0.ɵɵtextInterpolate(ctx_r1.getFailedCount());
1025
+ i0.ɵɵadvance(4);
1026
+ i0.ɵɵtextInterpolate1("", ctx_r1.getFailedPercent().toFixed(1), "%");
1027
+ i0.ɵɵadvance(6);
1028
+ i0.ɵɵtextInterpolate1("", (ctx_r1.getAverageScore() * 100).toFixed(1), "%");
1029
+ i0.ɵɵadvance(8);
1030
+ i0.ɵɵtextInterpolate1("", ctx_r1.getAverageDuration().toFixed(1), "s");
1031
+ i0.ɵɵadvance(8);
1032
+ i0.ɵɵtextInterpolate1("$", ctx_r1.getTotalCost().toFixed(4), "");
1033
+ } }
1034
+ function TestSuiteRunFormComponentExtended_div_121_div_3_th_26_Template(rf, ctx) { if (rf & 1) {
1035
+ i0.ɵɵelementStart(0, "th", 285);
1036
+ i0.ɵɵtext(1, "Status");
1037
+ i0.ɵɵelementEnd();
1038
+ } }
1039
+ function TestSuiteRunFormComponentExtended_div_121_div_3_th_27_Template(rf, ctx) { if (rf & 1) {
1040
+ i0.ɵɵelementStart(0, "th", 286);
1041
+ i0.ɵɵtext(1, "Auto Score");
1042
+ i0.ɵɵelementEnd();
1043
+ } }
1044
+ function TestSuiteRunFormComponentExtended_div_121_div_3_th_28_Template(rf, ctx) { if (rf & 1) {
1045
+ i0.ɵɵelementStart(0, "th", 287);
1046
+ i0.ɵɵtext(1, "Human Score");
1047
+ i0.ɵɵelementEnd();
1048
+ } }
1049
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_div_7_span_1_Template(rf, ctx) { if (rf & 1) {
1050
+ i0.ɵɵelementStart(0, "span", 295);
1051
+ i0.ɵɵtext(1);
1052
+ i0.ɵɵelementEnd();
1053
+ } if (rf & 2) {
1054
+ const tag_r26 = ctx.$implicit;
1055
+ i0.ɵɵadvance();
1056
+ i0.ɵɵtextInterpolate(tag_r26);
1057
+ } }
1058
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_div_7_Template(rf, ctx) { if (rf & 1) {
1059
+ i0.ɵɵelementStart(0, "div", 293);
1060
+ i0.ɵɵtemplate(1, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_div_7_span_1_Template, 2, 1, "span", 294);
1061
+ i0.ɵɵelementEnd();
1062
+ } if (rf & 2) {
1063
+ const run_r25 = i0.ɵɵnextContext().$implicit;
1064
+ const ctx_r1 = i0.ɵɵnextContext(3);
1065
+ i0.ɵɵadvance();
1066
+ i0.ɵɵproperty("ngForOf", ctx_r1.getRunTags(run_r25).slice(0, 2));
1067
+ } }
1068
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_8_Template(rf, ctx) { if (rf & 1) {
1069
+ i0.ɵɵelementStart(0, "td", 285)(1, "span", 9);
1070
+ i0.ɵɵelement(2, "i", 209);
1071
+ i0.ɵɵtext(3);
1072
+ i0.ɵɵelementEnd()();
1073
+ } if (rf & 2) {
1074
+ const run_r25 = i0.ɵɵnextContext().$implicit;
1075
+ i0.ɵɵadvance();
1076
+ i0.ɵɵproperty("ngClass", "status-" + run_r25.Status.toLowerCase());
1077
+ i0.ɵɵadvance();
1078
+ i0.ɵɵclassProp("fa-check-circle", run_r25.Status === "Passed")("fa-times-circle", run_r25.Status === "Failed")("fa-exclamation-circle", run_r25.Status === "Error")("fa-forward", run_r25.Status === "Skipped")("fa-clock", run_r25.Status === "Pending")("fa-spinner", run_r25.Status === "Running")("fa-spin", run_r25.Status === "Running");
1079
+ i0.ɵɵadvance();
1080
+ i0.ɵɵtextInterpolate1(" ", run_r25.Status, " ");
1081
+ } }
1082
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_9_div_1_Template(rf, ctx) { if (rf & 1) {
1083
+ i0.ɵɵelementStart(0, "div", 297)(1, "div", 298);
1084
+ i0.ɵɵelement(2, "div", 299);
1085
+ i0.ɵɵelementEnd();
1086
+ i0.ɵɵelementStart(3, "span", 300);
1087
+ i0.ɵɵtext(4);
1088
+ i0.ɵɵelementEnd()();
1089
+ } if (rf & 2) {
1090
+ const run_r25 = i0.ɵɵnextContext(2).$implicit;
1091
+ i0.ɵɵadvance(2);
1092
+ i0.ɵɵstyleProp("width", run_r25.Score * 100, "%");
1093
+ i0.ɵɵclassProp("high", run_r25.Score >= 0.8)("medium", run_r25.Score >= 0.5 && run_r25.Score < 0.8)("low", run_r25.Score < 0.5);
1094
+ i0.ɵɵadvance(2);
1095
+ i0.ɵɵtextInterpolate1("", (run_r25.Score * 100).toFixed(0), "%");
1096
+ } }
1097
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_9_span_2_Template(rf, ctx) { if (rf & 1) {
1098
+ i0.ɵɵelementStart(0, "span", 301);
1099
+ i0.ɵɵtext(1, "\u2014");
1100
+ i0.ɵɵelementEnd();
1101
+ } }
1102
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_9_Template(rf, ctx) { if (rf & 1) {
1103
+ i0.ɵɵelementStart(0, "td", 286);
1104
+ i0.ɵɵtemplate(1, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_9_div_1_Template, 5, 9, "div", 296)(2, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_9_span_2_Template, 2, 0, "span", 292);
1105
+ i0.ɵɵelementEnd();
1106
+ } if (rf & 2) {
1107
+ const run_r25 = i0.ɵɵnextContext().$implicit;
1108
+ i0.ɵɵadvance();
1109
+ i0.ɵɵproperty("ngIf", run_r25.Score != null);
1110
+ i0.ɵɵadvance();
1111
+ i0.ɵɵproperty("ngIf", run_r25.Score == null);
1112
+ } }
1113
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_10_div_1_span_3_Template(rf, ctx) { if (rf & 1) {
1114
+ i0.ɵɵelementStart(0, "span", 307);
1115
+ i0.ɵɵelement(1, "i", 209);
1116
+ i0.ɵɵelementEnd();
1117
+ } if (rf & 2) {
1118
+ const run_r25 = i0.ɵɵnextContext(3).$implicit;
1119
+ const ctx_r1 = i0.ɵɵnextContext(3);
1120
+ i0.ɵɵadvance();
1121
+ i0.ɵɵclassProp("fa-check", ctx_r1.getHumanIsCorrect(run_r25.ID) === true)("fa-times", ctx_r1.getHumanIsCorrect(run_r25.ID) === false)("correct", ctx_r1.getHumanIsCorrect(run_r25.ID) === true)("incorrect", ctx_r1.getHumanIsCorrect(run_r25.ID) === false);
1122
+ } }
1123
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_10_div_1_Template(rf, ctx) { if (rf & 1) {
1124
+ i0.ɵɵelementStart(0, "div", 304)(1, "span", 305);
1125
+ i0.ɵɵtext(2);
1126
+ i0.ɵɵelementEnd();
1127
+ i0.ɵɵtemplate(3, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_10_div_1_span_3_Template, 2, 8, "span", 306);
1128
+ i0.ɵɵelementEnd();
1129
+ } if (rf & 2) {
1130
+ const run_r25 = i0.ɵɵnextContext(2).$implicit;
1131
+ const ctx_r1 = i0.ɵɵnextContext(3);
1132
+ i0.ɵɵadvance();
1133
+ i0.ɵɵclassProp("low", ctx_r1.getFeedbackRating(run_r25.ID) <= 3)("mid", ctx_r1.getFeedbackRating(run_r25.ID) >= 4 && ctx_r1.getFeedbackRating(run_r25.ID) <= 6)("high", ctx_r1.getFeedbackRating(run_r25.ID) >= 7);
1134
+ i0.ɵɵadvance();
1135
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.getFeedbackRating(run_r25.ID), "/10 ");
1136
+ i0.ɵɵadvance();
1137
+ i0.ɵɵproperty("ngIf", ctx_r1.getHumanIsCorrect(run_r25.ID) !== null);
1138
+ } }
1139
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_10_span_2_Template(rf, ctx) { if (rf & 1) {
1140
+ i0.ɵɵelementStart(0, "span", 308);
1141
+ i0.ɵɵelement(1, "i", 309);
1142
+ i0.ɵɵelementEnd();
1143
+ } }
1144
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_10_Template(rf, ctx) { if (rf & 1) {
1145
+ i0.ɵɵelementStart(0, "td", 287);
1146
+ i0.ɵɵtemplate(1, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_10_div_1_Template, 4, 8, "div", 302)(2, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_10_span_2_Template, 2, 0, "span", 303);
1147
+ i0.ɵɵelementEnd();
1148
+ } if (rf & 2) {
1149
+ const run_r25 = i0.ɵɵnextContext().$implicit;
1150
+ const ctx_r1 = i0.ɵɵnextContext(3);
1151
+ i0.ɵɵadvance();
1152
+ i0.ɵɵproperty("ngIf", ctx_r1.hasFeedback(run_r25.ID));
1153
+ i0.ɵɵadvance();
1154
+ i0.ɵɵproperty("ngIf", !ctx_r1.hasFeedback(run_r25.ID));
89
1155
  } }
90
- function TestSuiteRunFormComponentExtended_div_95_div_1_div_1_span_11_Template(rf, ctx) { if (rf & 1) {
1156
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_span_12_Template(rf, ctx) { if (rf & 1) {
91
1157
  i0.ɵɵelementStart(0, "span");
92
1158
  i0.ɵɵtext(1);
93
1159
  i0.ɵɵelementEnd();
94
1160
  } if (rf & 2) {
95
- const run_r4 = i0.ɵɵnextContext().$implicit;
1161
+ const run_r25 = i0.ɵɵnextContext().$implicit;
96
1162
  i0.ɵɵadvance();
97
- i0.ɵɵtextInterpolate1("Score: ", run_r4.Score.toFixed(4), "");
1163
+ i0.ɵɵtextInterpolate1("", run_r25.DurationSeconds.toFixed(1), "s");
98
1164
  } }
99
- function TestSuiteRunFormComponentExtended_div_95_div_1_div_1_span_12_Template(rf, ctx) { if (rf & 1) {
1165
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_span_13_Template(rf, ctx) { if (rf & 1) {
1166
+ i0.ɵɵelementStart(0, "span", 301);
1167
+ i0.ɵɵtext(1, "\u2014");
1168
+ i0.ɵɵelementEnd();
1169
+ } }
1170
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_span_15_Template(rf, ctx) { if (rf & 1) {
100
1171
  i0.ɵɵelementStart(0, "span");
101
1172
  i0.ɵɵtext(1);
102
1173
  i0.ɵɵelementEnd();
103
1174
  } if (rf & 2) {
104
- const run_r4 = i0.ɵɵnextContext().$implicit;
1175
+ const run_r25 = i0.ɵɵnextContext().$implicit;
105
1176
  i0.ɵɵadvance();
106
- i0.ɵɵtextInterpolate1("", run_r4.DurationSeconds.toFixed(1), "s");
1177
+ i0.ɵɵtextInterpolate1("$", run_r25.CostUSD.toFixed(4), "");
107
1178
  } }
108
- function TestSuiteRunFormComponentExtended_div_95_div_1_div_1_Template(rf, ctx) { if (rf & 1) {
109
- const _r3 = i0.ɵɵgetCurrentView();
110
- i0.ɵɵelementStart(0, "div", 60);
111
- i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_95_div_1_div_1_Template_div_click_0_listener() { const run_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openTestRun(run_r4.ID)); });
112
- i0.ɵɵelementStart(1, "div", 61);
113
- i0.ɵɵtext(2);
1179
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_span_16_Template(rf, ctx) { if (rf & 1) {
1180
+ i0.ɵɵelementStart(0, "span", 301);
1181
+ i0.ɵɵtext(1, "\u2014");
114
1182
  i0.ɵɵelementEnd();
115
- i0.ɵɵelementStart(3, "div", 62);
116
- i0.ɵɵelement(4, "i", 63);
117
- i0.ɵɵelementEnd();
118
- i0.ɵɵelementStart(5, "div", 64)(6, "div", 65);
119
- i0.ɵɵtext(7);
1183
+ } }
1184
+ function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_Template(rf, ctx) { if (rf & 1) {
1185
+ const _r24 = i0.ɵɵgetCurrentView();
1186
+ i0.ɵɵelementStart(0, "tr", 288);
1187
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_Template_tr_click_0_listener() { const run_r25 = i0.ɵɵrestoreView(_r24).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openTestRun(run_r25.ID)); });
1188
+ i0.ɵɵelementStart(1, "td", 277);
1189
+ i0.ɵɵtext(2);
120
1190
  i0.ɵɵelementEnd();
121
- i0.ɵɵelementStart(8, "div", 66)(9, "span", 67);
122
- i0.ɵɵtext(10);
1191
+ i0.ɵɵelementStart(3, "td", 278)(4, "div", 289)(5, "span", 290);
1192
+ i0.ɵɵtext(6);
123
1193
  i0.ɵɵelementEnd();
124
- i0.ɵɵtemplate(11, TestSuiteRunFormComponentExtended_div_95_div_1_div_1_span_11_Template, 2, 1, "span", 68)(12, TestSuiteRunFormComponentExtended_div_95_div_1_div_1_span_12_Template, 2, 1, "span", 68);
1194
+ i0.ɵɵtemplate(7, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_div_7_Template, 2, 1, "div", 291);
125
1195
  i0.ɵɵelementEnd()();
126
- i0.ɵɵelement(13, "i", 45);
1196
+ i0.ɵɵtemplate(8, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_8_Template, 4, 16, "td", 279)(9, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_9_Template, 3, 2, "td", 280)(10, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_td_10_Template, 3, 2, "td", 281);
1197
+ i0.ɵɵelementStart(11, "td", 282);
1198
+ i0.ɵɵtemplate(12, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_span_12_Template, 2, 1, "span", 250)(13, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_span_13_Template, 2, 0, "span", 292);
127
1199
  i0.ɵɵelementEnd();
1200
+ i0.ɵɵelementStart(14, "td", 283);
1201
+ i0.ɵɵtemplate(15, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_span_15_Template, 2, 1, "span", 250)(16, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_span_16_Template, 2, 0, "span", 292);
1202
+ i0.ɵɵelementEnd()();
128
1203
  } if (rf & 2) {
129
- const run_r4 = ctx.$implicit;
1204
+ const run_r25 = ctx.$implicit;
1205
+ const i_r27 = ctx.index;
1206
+ const ctx_r1 = i0.ɵɵnextContext(3);
1207
+ i0.ɵɵclassProp("row-passed", run_r25.Status === "Passed")("row-failed", run_r25.Status === "Failed")("row-error", run_r25.Status === "Error")("row-skipped", run_r25.Status === "Skipped");
130
1208
  i0.ɵɵadvance(2);
131
- i0.ɵɵtextInterpolate(run_r4.Sequence);
1209
+ i0.ɵɵtextInterpolate(i_r27 + 1);
1210
+ i0.ɵɵadvance(4);
1211
+ i0.ɵɵtextInterpolate(run_r25.Test || "Unknown Test");
132
1212
  i0.ɵɵadvance();
133
- i0.ɵɵstyleProp("background-color", run_r4.Status === "Passed" ? "#4caf50" : run_r4.Status === "Failed" ? "#f44336" : "#ff9800");
1213
+ i0.ɵɵproperty("ngIf", ctx_r1.getRunTags(run_r25).length > 0);
134
1214
  i0.ɵɵadvance();
135
- i0.ɵɵclassProp("fa-check", run_r4.Status === "Passed")("fa-times", run_r4.Status === "Failed")("fa-exclamation", run_r4.Status === "Error");
136
- i0.ɵɵadvance(3);
137
- i0.ɵɵtextInterpolate(run_r4.Test);
138
- i0.ɵɵadvance(2);
139
- i0.ɵɵstyleProp("color", run_r4.Status === "Passed" ? "#4caf50" : run_r4.Status === "Failed" ? "#f44336" : "#ff9800");
1215
+ i0.ɵɵproperty("ngIf", ctx_r1.evalPreferences.showExecution);
1216
+ i0.ɵɵadvance();
1217
+ i0.ɵɵproperty("ngIf", ctx_r1.evalPreferences.showAuto);
140
1218
  i0.ɵɵadvance();
141
- i0.ɵɵtextInterpolate(run_r4.Status);
1219
+ i0.ɵɵproperty("ngIf", ctx_r1.evalPreferences.showHuman);
1220
+ i0.ɵɵadvance(2);
1221
+ i0.ɵɵproperty("ngIf", run_r25.DurationSeconds);
142
1222
  i0.ɵɵadvance();
143
- i0.ɵɵproperty("ngIf", run_r4.Score != null);
1223
+ i0.ɵɵproperty("ngIf", !run_r25.DurationSeconds);
1224
+ i0.ɵɵadvance(2);
1225
+ i0.ɵɵproperty("ngIf", run_r25.CostUSD);
144
1226
  i0.ɵɵadvance();
145
- i0.ɵɵproperty("ngIf", run_r4.DurationSeconds);
1227
+ i0.ɵɵproperty("ngIf", !run_r25.CostUSD);
146
1228
  } }
147
- function TestSuiteRunFormComponentExtended_div_95_div_1_Template(rf, ctx) { if (rf & 1) {
148
- i0.ɵɵelementStart(0, "div", 58);
149
- i0.ɵɵtemplate(1, TestSuiteRunFormComponentExtended_div_95_div_1_div_1_Template, 14, 15, "div", 59);
1229
+ function TestSuiteRunFormComponentExtended_div_121_div_3_Template(rf, ctx) { if (rf & 1) {
1230
+ i0.ɵɵelementStart(0, "div", 256)(1, "div", 268)(2, "h3");
1231
+ i0.ɵɵelement(3, "i", 269);
1232
+ i0.ɵɵtext(4, " Test Results");
150
1233
  i0.ɵɵelementEnd();
1234
+ i0.ɵɵelementStart(5, "div", 270)(6, "span", 271);
1235
+ i0.ɵɵelement(7, "i", 28);
1236
+ i0.ɵɵtext(8, " Passed");
1237
+ i0.ɵɵelementEnd();
1238
+ i0.ɵɵelementStart(9, "span", 272);
1239
+ i0.ɵɵelement(10, "i", 33);
1240
+ i0.ɵɵtext(11, " Failed");
1241
+ i0.ɵɵelementEnd();
1242
+ i0.ɵɵelementStart(12, "span", 273);
1243
+ i0.ɵɵelement(13, "i", 35);
1244
+ i0.ɵɵtext(14, " Error");
1245
+ i0.ɵɵelementEnd();
1246
+ i0.ɵɵelementStart(15, "span", 274);
1247
+ i0.ɵɵelement(16, "i", 37);
1248
+ i0.ɵɵtext(17, " Skipped");
1249
+ i0.ɵɵelementEnd()()();
1250
+ i0.ɵɵelementStart(18, "div", 275)(19, "table", 276)(20, "thead")(21, "tr")(22, "th", 277);
1251
+ i0.ɵɵtext(23, "#");
1252
+ i0.ɵɵelementEnd();
1253
+ i0.ɵɵelementStart(24, "th", 278);
1254
+ i0.ɵɵtext(25, "Test Name");
1255
+ i0.ɵɵelementEnd();
1256
+ i0.ɵɵtemplate(26, TestSuiteRunFormComponentExtended_div_121_div_3_th_26_Template, 2, 0, "th", 279)(27, TestSuiteRunFormComponentExtended_div_121_div_3_th_27_Template, 2, 0, "th", 280)(28, TestSuiteRunFormComponentExtended_div_121_div_3_th_28_Template, 2, 0, "th", 281);
1257
+ i0.ɵɵelementStart(29, "th", 282);
1258
+ i0.ɵɵtext(30, "Duration");
1259
+ i0.ɵɵelementEnd();
1260
+ i0.ɵɵelementStart(31, "th", 283);
1261
+ i0.ɵɵtext(32, "Cost");
1262
+ i0.ɵɵelementEnd()()();
1263
+ i0.ɵɵelementStart(33, "tbody");
1264
+ i0.ɵɵtemplate(34, TestSuiteRunFormComponentExtended_div_121_div_3_tr_34_Template, 17, 18, "tr", 284);
1265
+ i0.ɵɵelementEnd()()()();
151
1266
  } if (rf & 2) {
152
1267
  const ctx_r1 = i0.ɵɵnextContext(2);
1268
+ i0.ɵɵadvance(26);
1269
+ i0.ɵɵproperty("ngIf", ctx_r1.evalPreferences.showExecution);
1270
+ i0.ɵɵadvance();
1271
+ i0.ɵɵproperty("ngIf", ctx_r1.evalPreferences.showAuto);
153
1272
  i0.ɵɵadvance();
1273
+ i0.ɵɵproperty("ngIf", ctx_r1.evalPreferences.showHuman);
1274
+ i0.ɵɵadvance(6);
154
1275
  i0.ɵɵproperty("ngForOf", ctx_r1.testRuns);
155
1276
  } }
156
- function TestSuiteRunFormComponentExtended_div_95_div_2_Template(rf, ctx) { if (rf & 1) {
157
- i0.ɵɵelementStart(0, "div", 69);
158
- i0.ɵɵelement(1, "i", 70);
159
- i0.ɵɵelementStart(2, "p");
160
- i0.ɵɵtext(3, "No test runs found for this suite execution");
1277
+ function TestSuiteRunFormComponentExtended_div_121_div_4_Template(rf, ctx) { if (rf & 1) {
1278
+ i0.ɵɵelementStart(0, "div", 238)(1, "div", 239);
1279
+ i0.ɵɵelement(2, "i", 49);
1280
+ i0.ɵɵelementEnd();
1281
+ i0.ɵɵelementStart(3, "h4");
1282
+ i0.ɵɵtext(4, "No Test Results Yet");
1283
+ i0.ɵɵelementEnd();
1284
+ i0.ɵɵelementStart(5, "p");
1285
+ i0.ɵɵtext(6, "Test runs will appear here once the suite execution completes.");
161
1286
  i0.ɵɵelementEnd()();
162
1287
  } }
163
- function TestSuiteRunFormComponentExtended_div_95_Template(rf, ctx) { if (rf & 1) {
164
- i0.ɵɵelementStart(0, "div", 55);
165
- i0.ɵɵtemplate(1, TestSuiteRunFormComponentExtended_div_95_div_1_Template, 2, 1, "div", 56)(2, TestSuiteRunFormComponentExtended_div_95_div_2_Template, 4, 0, "div", 57);
1288
+ function TestSuiteRunFormComponentExtended_div_121_Template(rf, ctx) { if (rf & 1) {
1289
+ i0.ɵɵelementStart(0, "div", 252);
1290
+ i0.ɵɵtemplate(1, TestSuiteRunFormComponentExtended_div_121_div_1_Template, 4, 0, "div", 253)(2, TestSuiteRunFormComponentExtended_div_121_div_2_Template, 49, 7, "div", 254)(3, TestSuiteRunFormComponentExtended_div_121_div_3_Template, 35, 4, "div", 254)(4, TestSuiteRunFormComponentExtended_div_121_div_4_Template, 7, 0, "div", 169);
166
1291
  i0.ɵɵelementEnd();
167
1292
  } if (rf & 2) {
168
1293
  const ctx_r1 = i0.ɵɵnextContext();
169
1294
  i0.ɵɵadvance();
170
- i0.ɵɵproperty("ngIf", ctx_r1.testRuns.length > 0);
1295
+ i0.ɵɵproperty("ngIf", ctx_r1.loadingTestRuns);
1296
+ i0.ɵɵadvance();
1297
+ i0.ɵɵproperty("ngIf", !ctx_r1.loadingTestRuns && ctx_r1.testRuns.length > 0);
171
1298
  i0.ɵɵadvance();
172
- i0.ɵɵproperty("ngIf", ctx_r1.testRunsLoaded && ctx_r1.testRuns.length === 0);
1299
+ i0.ɵɵproperty("ngIf", !ctx_r1.loadingTestRuns && ctx_r1.testRuns.length > 0);
1300
+ i0.ɵɵadvance();
1301
+ i0.ɵɵproperty("ngIf", !ctx_r1.loadingTestRuns && ctx_r1.testRunsLoaded && ctx_r1.testRuns.length === 0);
173
1302
  } }
174
- function TestSuiteRunFormComponentExtended_div_96_a_11_Template(rf, ctx) { if (rf & 1) {
175
- const _r5 = i0.ɵɵgetCurrentView();
176
- i0.ɵɵelementStart(0, "a", 43);
177
- i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_96_a_11_Template_a_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.openTestSuite()); });
178
- i0.ɵɵtext(1);
1303
+ function TestSuiteRunFormComponentExtended_div_122_Template(rf, ctx) { if (rf & 1) {
1304
+ i0.ɵɵelementStart(0, "div", 310);
1305
+ i0.ɵɵelement(1, "mj-execution-context", 311);
179
1306
  i0.ɵɵelementEnd();
180
1307
  } if (rf & 2) {
181
- const ctx_r1 = i0.ɵɵnextContext(2);
1308
+ const ctx_r1 = i0.ɵɵnextContext();
182
1309
  i0.ɵɵadvance();
183
- i0.ɵɵtextInterpolate(ctx_r1.testSuite.Name);
1310
+ 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);
184
1311
  } }
185
- function TestSuiteRunFormComponentExtended_div_96_Template(rf, ctx) { if (rf & 1) {
186
- i0.ɵɵelementStart(0, "div", 71)(1, "div", 72)(2, "div", 73)(3, "div", 74);
187
- i0.ɵɵtext(4, "Run ID");
188
- i0.ɵɵelementEnd();
189
- i0.ɵɵelementStart(5, "div", 75);
190
- i0.ɵɵtext(6);
1312
+ function TestSuiteRunFormComponentExtended_div_125_Template(rf, ctx) { if (rf & 1) {
1313
+ const _r28 = i0.ɵɵgetCurrentView();
1314
+ i0.ɵɵelementStart(0, "div", 312)(1, "div", 313);
1315
+ i0.ɵɵelement(2, "i", 59);
1316
+ i0.ɵɵtext(3, " Shortcuts ");
1317
+ i0.ɵɵelementStart(4, "button", 314);
1318
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_div_125_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r28); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleShortcuts()); });
1319
+ i0.ɵɵelement(5, "i", 100);
191
1320
  i0.ɵɵelementEnd()();
192
- i0.ɵɵelementStart(7, "div", 73)(8, "div", 74);
193
- i0.ɵɵtext(9, "Test Suite");
1321
+ i0.ɵɵelementStart(6, "div", 315)(7, "div", 316)(8, "span");
1322
+ i0.ɵɵtext(9, "Refresh");
194
1323
  i0.ɵɵelementEnd();
195
- i0.ɵɵelementStart(10, "div", 75);
196
- i0.ɵɵtemplate(11, TestSuiteRunFormComponentExtended_div_96_a_11_Template, 2, 1, "a", 76);
197
- i0.ɵɵelementEnd()();
198
- i0.ɵɵelementStart(12, "div", 73)(13, "div", 74);
199
- i0.ɵɵtext(14, "Status");
1324
+ i0.ɵɵelementStart(10, "span", 317)(11, "kbd");
1325
+ i0.ɵɵtext(12, "Cmd");
200
1326
  i0.ɵɵelementEnd();
201
- i0.ɵɵelementStart(15, "div", 75);
202
- i0.ɵɵtext(16);
203
- i0.ɵɵelementEnd()();
204
- i0.ɵɵelementStart(17, "div", 73)(18, "div", 74);
205
- i0.ɵɵtext(19, "Run By");
1327
+ i0.ɵɵelementStart(13, "kbd");
1328
+ i0.ɵɵtext(14, "R");
1329
+ i0.ɵɵelementEnd()()();
1330
+ i0.ɵɵelementStart(15, "div", 316)(16, "span");
1331
+ i0.ɵɵtext(17, "Re-run Suite");
206
1332
  i0.ɵɵelementEnd();
207
- i0.ɵɵelementStart(20, "div", 75);
208
- i0.ɵɵtext(21);
209
- i0.ɵɵelementEnd()();
210
- i0.ɵɵelementStart(22, "div", 73)(23, "div", 74);
211
- i0.ɵɵtext(24, "Environment");
1333
+ i0.ɵɵelementStart(18, "span", 317)(19, "kbd");
1334
+ i0.ɵɵtext(20, "Cmd");
212
1335
  i0.ɵɵelementEnd();
213
- i0.ɵɵelementStart(25, "div", 75);
214
- i0.ɵɵtext(26);
215
- i0.ɵɵelementEnd()();
216
- i0.ɵɵelementStart(27, "div", 73)(28, "div", 74);
217
- i0.ɵɵtext(29, "Trigger Type");
1336
+ i0.ɵɵelementStart(21, "kbd");
1337
+ i0.ɵɵtext(22, "Shift");
218
1338
  i0.ɵɵelementEnd();
219
- i0.ɵɵelementStart(30, "div", 75);
220
- i0.ɵɵtext(31);
221
- i0.ɵɵelementEnd()();
222
- i0.ɵɵelementStart(32, "div", 73)(33, "div", 74);
223
- i0.ɵɵtext(34, "Git Commit");
1339
+ i0.ɵɵelementStart(23, "kbd");
1340
+ i0.ɵɵtext(24, "R");
1341
+ i0.ɵɵelementEnd()()();
1342
+ i0.ɵɵelementStart(25, "div", 316)(26, "span");
1343
+ i0.ɵɵtext(27, "Switch Tabs");
224
1344
  i0.ɵɵelementEnd();
225
- i0.ɵɵelementStart(35, "div", 75);
226
- i0.ɵɵtext(36);
227
- i0.ɵɵelementEnd()();
228
- i0.ɵɵelementStart(37, "div", 73)(38, "div", 74);
229
- i0.ɵɵtext(39, "Agent Version");
1345
+ i0.ɵɵelementStart(28, "span", 317)(29, "kbd");
1346
+ i0.ɵɵtext(30, "1");
230
1347
  i0.ɵɵelementEnd();
231
- i0.ɵɵelementStart(40, "div", 75);
232
- i0.ɵɵtext(41);
233
- i0.ɵɵelementEnd()()()();
234
- } if (rf & 2) {
235
- const ctx_r1 = i0.ɵɵnextContext();
236
- i0.ɵɵadvance(6);
237
- i0.ɵɵtextInterpolate(ctx_r1.record.ID);
238
- i0.ɵɵadvance(5);
239
- i0.ɵɵproperty("ngIf", ctx_r1.testSuite);
240
- i0.ɵɵadvance(5);
241
- i0.ɵɵtextInterpolate(ctx_r1.record.Status);
242
- i0.ɵɵadvance(5);
243
- i0.ɵɵtextInterpolate(ctx_r1.record.RunByUser);
244
- i0.ɵɵadvance(5);
245
- i0.ɵɵtextInterpolate(ctx_r1.record.Environment || "N/A");
246
- i0.ɵɵadvance(5);
247
- i0.ɵɵtextInterpolate(ctx_r1.record.TriggerType || "N/A");
248
- i0.ɵɵadvance(5);
249
- i0.ɵɵtextInterpolate(ctx_r1.record.GitCommit || "N/A");
250
- i0.ɵɵadvance(5);
251
- i0.ɵɵtextInterpolate(ctx_r1.record.AgentVersion || "N/A");
1348
+ i0.ɵɵtext(31, "-");
1349
+ i0.ɵɵelementStart(32, "kbd");
1350
+ i0.ɵɵtext(33, "5");
1351
+ i0.ɵɵelementEnd()()()()();
252
1352
  } }
1353
+ /** Settings key for keyboard shortcuts visibility */
1354
+ const SHORTCUTS_SETTINGS_KEY = '__mj.Testing.ShowKeyboardShortcuts';
253
1355
  let TestSuiteRunFormComponentExtended = class TestSuiteRunFormComponentExtended extends TestSuiteRunFormComponent {
254
- constructor(elementRef, sharedService, router, route, cdr) {
1356
+ constructor(elementRef, sharedService, router, route, cdr, testingDialogService, evalPrefsService) {
255
1357
  super(elementRef, sharedService, router, route, cdr);
256
1358
  this.router = router;
257
1359
  this.cdr = cdr;
1360
+ this.testingDialogService = testingDialogService;
1361
+ this.evalPrefsService = evalPrefsService;
258
1362
  this.destroy$ = new Subject();
259
1363
  // UI state
260
1364
  this.activeTab = 'overview';
261
1365
  this.loading = false;
1366
+ this.loadingTestRuns = false;
1367
+ this.loadingFeedbacks = false;
262
1368
  this.error = null;
263
1369
  this.testRunsLoaded = false;
1370
+ this.feedbacksLoaded = false;
1371
+ this.isRefreshing = false;
1372
+ this.autoRefreshEnabled = false;
264
1373
  // Related entities
265
1374
  this.testSuite = null;
266
1375
  this.testRuns = [];
1376
+ this.feedbacks = new Map();
1377
+ // Tags
1378
+ this.tags = [];
1379
+ this.newTag = '';
1380
+ this.editingTags = false;
1381
+ this.savingTags = false;
1382
+ // Inline feedback
1383
+ this.expandedRunId = null;
1384
+ this.inlineRating = 0;
1385
+ this.inlineHoverRating = 0;
1386
+ this.inlineIsCorrect = null;
1387
+ this.inlineComments = '';
1388
+ this.savingInlineFeedback = false;
1389
+ // Filter for test runs
1390
+ this.runStatusFilter = null;
1391
+ // Keyboard shortcuts
1392
+ this.keyboardShortcutsEnabled = true;
1393
+ this.showShortcuts = false; // Hidden by default
1394
+ this.shortcutsSettingEntity = null;
1395
+ this.metadata = new Metadata();
1396
+ // Evaluation system
1397
+ this.evalPreferences = {
1398
+ showExecution: true,
1399
+ showHuman: true,
1400
+ showAuto: false
1401
+ };
1402
+ this.testRunsWithFeedback = [];
1403
+ this.evaluationMetrics = null;
1404
+ this.needsReviewItems = [];
267
1405
  }
268
1406
  async ngOnInit() {
269
1407
  await super.ngOnInit();
1408
+ this.loadShortcutsSetting();
1409
+ // Subscribe to evaluation preferences
1410
+ this.evalPrefsService.preferences$
1411
+ .pipe(takeUntil(this.destroy$))
1412
+ .subscribe(prefs => {
1413
+ this.evalPreferences = prefs;
1414
+ this.cdr.markForCheck();
1415
+ });
270
1416
  if (this.record && this.record.ID) {
271
1417
  await this.loadRelatedData();
1418
+ this.parseTags();
1419
+ // Auto-refresh for running suite executions
1420
+ if (this.record.Status === 'Running' || this.record.Status === 'Pending') {
1421
+ this.startAutoRefresh();
1422
+ }
272
1423
  }
273
1424
  }
1425
+ parseTags() {
1426
+ this.tags = TagsHelper.parseTags(this.record.Tags);
1427
+ }
274
1428
  ngOnDestroy() {
275
1429
  this.destroy$.next();
276
1430
  this.destroy$.complete();
277
1431
  }
1432
+ // Keyboard shortcuts
1433
+ handleKeyboardShortcut(event) {
1434
+ if (!this.keyboardShortcutsEnabled)
1435
+ return;
1436
+ // Cmd/Ctrl + R: Refresh
1437
+ if ((event.metaKey || event.ctrlKey) && event.key === 'r' && !event.shiftKey) {
1438
+ event.preventDefault();
1439
+ this.refresh();
1440
+ return;
1441
+ }
1442
+ // Cmd/Ctrl + Shift + R: Re-run suite
1443
+ if ((event.metaKey || event.ctrlKey) && event.shiftKey && event.key === 'r') {
1444
+ event.preventDefault();
1445
+ this.reRunSuite();
1446
+ return;
1447
+ }
1448
+ // Number keys for tabs (1-4)
1449
+ if (!event.metaKey && !event.ctrlKey && !event.altKey) {
1450
+ switch (event.key) {
1451
+ case '1':
1452
+ this.changeTab('overview');
1453
+ break;
1454
+ case '2':
1455
+ this.changeTab('runs');
1456
+ break;
1457
+ case '3':
1458
+ this.changeTab('details');
1459
+ break;
1460
+ case '4':
1461
+ this.changeTab('analytics');
1462
+ break;
1463
+ }
1464
+ }
1465
+ }
1466
+ startAutoRefresh() {
1467
+ this.autoRefreshEnabled = true;
1468
+ interval(5000)
1469
+ .pipe(takeUntil(this.destroy$))
1470
+ .subscribe(() => {
1471
+ if (this.autoRefreshEnabled && (this.record.Status === 'Running' || this.record.Status === 'Pending')) {
1472
+ this.silentRefresh();
1473
+ }
1474
+ else {
1475
+ this.autoRefreshEnabled = false;
1476
+ }
1477
+ });
1478
+ }
1479
+ async silentRefresh() {
1480
+ try {
1481
+ await this.record.Load(this.record.ID);
1482
+ this.cdr.markForCheck();
1483
+ }
1484
+ catch {
1485
+ // Silently fail on auto-refresh
1486
+ }
1487
+ }
278
1488
  async loadRelatedData() {
279
1489
  this.loading = true;
1490
+ this.error = null;
280
1491
  try {
281
1492
  // Load test suite
282
1493
  if (this.record.SuiteID) {
@@ -290,16 +1501,22 @@ let TestSuiteRunFormComponentExtended = class TestSuiteRunFormComponentExtended
290
1501
  }
291
1502
  catch (error) {
292
1503
  console.error('Error loading related data:', error);
293
- this.error = 'Failed to load related data';
1504
+ this.error = 'Failed to load related data. Click to retry.';
294
1505
  }
295
1506
  finally {
296
1507
  this.loading = false;
297
1508
  this.cdr.markForCheck();
298
1509
  }
299
1510
  }
1511
+ async retryLoad() {
1512
+ this.error = null;
1513
+ await this.loadRelatedData();
1514
+ }
300
1515
  async loadTestRuns() {
301
1516
  if (this.testRunsLoaded)
302
1517
  return;
1518
+ this.loadingTestRuns = true;
1519
+ this.cdr.markForCheck();
303
1520
  try {
304
1521
  const rv = new RunView();
305
1522
  const result = await rv.RunView({
@@ -312,40 +1529,51 @@ let TestSuiteRunFormComponentExtended = class TestSuiteRunFormComponentExtended
312
1529
  this.testRuns = result.Results || [];
313
1530
  }
314
1531
  this.testRunsLoaded = true;
315
- this.cdr.markForCheck();
1532
+ // Also load feedbacks for these runs
1533
+ if (this.testRuns.length > 0) {
1534
+ await this.loadFeedbacks();
1535
+ }
316
1536
  }
317
1537
  catch (error) {
318
1538
  console.error('Error loading test runs:', error);
1539
+ SharedService.Instance.CreateSimpleNotification('Failed to load test runs', 'error', 3000);
1540
+ }
1541
+ finally {
1542
+ this.loadingTestRuns = false;
1543
+ this.cdr.markForCheck();
319
1544
  }
320
1545
  }
321
1546
  changeTab(tab) {
322
1547
  this.activeTab = tab;
323
1548
  // Lazy load tabs
324
- if (tab === 'runs' && !this.testRunsLoaded) {
1549
+ if ((tab === 'runs' || tab === 'analytics') && !this.testRunsLoaded) {
325
1550
  this.loadTestRuns();
326
1551
  }
327
1552
  this.cdr.markForCheck();
328
1553
  }
329
1554
  getStatusColor() {
330
1555
  switch (this.record.Status) {
331
- case 'Completed': return '#4caf50';
332
- case 'Failed': return '#f44336';
333
- case 'Running': return '#2196f3';
334
- case 'Pending': return '#ffc107';
335
- case 'Cancelled': return '#9e9e9e';
336
- default: return '#999';
1556
+ case 'Completed': return '#10b981';
1557
+ case 'Failed': return '#ef4444';
1558
+ case 'Running': return '#3b82f6';
1559
+ case 'Pending': return '#8b5cf6';
1560
+ case 'Cancelled': return '#6b7280';
1561
+ default: return '#9ca3af';
337
1562
  }
338
1563
  }
339
1564
  getStatusIcon() {
340
1565
  switch (this.record.Status) {
341
1566
  case 'Completed': return 'fa-check-circle';
342
1567
  case 'Failed': return 'fa-times-circle';
343
- case 'Running': return 'fa-spinner fa-spin';
344
- case 'Pending': return 'fa-clock';
1568
+ case 'Running': return 'fa-circle-notch fa-spin';
1569
+ case 'Pending': return 'fa-hourglass-half';
345
1570
  case 'Cancelled': return 'fa-ban';
346
1571
  default: return 'fa-question-circle';
347
1572
  }
348
1573
  }
1574
+ getStatusClass() {
1575
+ return `status-${this.record.Status?.toLowerCase() || 'unknown'}`;
1576
+ }
349
1577
  calculateDuration() {
350
1578
  if (!this.record.TotalDurationSeconds)
351
1579
  return 'N/A';
@@ -373,6 +1601,25 @@ let TestSuiteRunFormComponentExtended = class TestSuiteRunFormComponentExtended
373
1601
  return 0;
374
1602
  return (passed / total) * 100;
375
1603
  }
1604
+ getRelativeTime(date) {
1605
+ if (!date)
1606
+ return 'N/A';
1607
+ const d = new Date(date);
1608
+ const now = new Date();
1609
+ const diffMs = now.getTime() - d.getTime();
1610
+ const diffMins = Math.floor(diffMs / 60000);
1611
+ const diffHours = Math.floor(diffMs / 3600000);
1612
+ const diffDays = Math.floor(diffMs / 86400000);
1613
+ if (diffMins < 1)
1614
+ return 'Just now';
1615
+ if (diffMins < 60)
1616
+ return `${diffMins}m ago`;
1617
+ if (diffHours < 24)
1618
+ return `${diffHours}h ago`;
1619
+ if (diffDays < 7)
1620
+ return `${diffDays}d ago`;
1621
+ return d.toLocaleDateString();
1622
+ }
376
1623
  openTestSuite() {
377
1624
  if (this.testSuite) {
378
1625
  SharedService.Instance.OpenEntityRecord('MJ: Test Suites', CompositeKey.FromID(this.testSuite.ID));
@@ -381,136 +1628,572 @@ let TestSuiteRunFormComponentExtended = class TestSuiteRunFormComponentExtended
381
1628
  openTestRun(runId) {
382
1629
  SharedService.Instance.OpenEntityRecord('MJ: Test Runs', CompositeKey.FromID(runId));
383
1630
  }
1631
+ async reRunSuite() {
1632
+ if (!this.record.SuiteID) {
1633
+ SharedService.Instance.CreateSimpleNotification('Cannot re-run: Suite ID not available', 'error', 3000);
1634
+ return;
1635
+ }
1636
+ this.testingDialogService.OpenSuiteDialog(this.record.SuiteID);
1637
+ }
384
1638
  async refresh() {
385
- await this.loadRelatedData();
386
- if (this.testRunsLoaded) {
387
- this.testRunsLoaded = false;
388
- await this.loadTestRuns();
1639
+ this.isRefreshing = true;
1640
+ this.cdr.markForCheck();
1641
+ try {
1642
+ await this.record.Load(this.record.ID);
1643
+ await this.loadRelatedData();
1644
+ // Reset lazy-loaded data
1645
+ if (this.testRunsLoaded) {
1646
+ this.testRunsLoaded = false;
1647
+ this.testRuns = [];
1648
+ await this.loadTestRuns();
1649
+ }
1650
+ SharedService.Instance.CreateSimpleNotification('Refreshed successfully', 'success', 2000);
1651
+ }
1652
+ catch {
1653
+ SharedService.Instance.CreateSimpleNotification('Failed to refresh', 'error', 3000);
1654
+ }
1655
+ finally {
1656
+ this.isRefreshing = false;
1657
+ this.cdr.markForCheck();
1658
+ }
1659
+ }
1660
+ getRunStatusColor(status) {
1661
+ switch (status) {
1662
+ case 'Passed': return '#10b981';
1663
+ case 'Failed': return '#ef4444';
1664
+ case 'Error': return '#f59e0b';
1665
+ case 'Timeout': return '#f97316';
1666
+ case 'Running': return '#3b82f6';
1667
+ case 'Pending': return '#8b5cf6';
1668
+ case 'Skipped': return '#6b7280';
1669
+ default: return '#9ca3af';
1670
+ }
1671
+ }
1672
+ getRunStatusIcon(status) {
1673
+ switch (status) {
1674
+ case 'Passed': return 'fa-check';
1675
+ case 'Failed': return 'fa-times';
1676
+ case 'Error': return 'fa-exclamation';
1677
+ case 'Timeout': return 'fa-clock';
1678
+ case 'Running': return 'fa-circle-notch fa-spin';
1679
+ case 'Pending': return 'fa-hourglass-half';
1680
+ case 'Skipped': return 'fa-forward';
1681
+ default: return 'fa-question';
1682
+ }
1683
+ }
1684
+ // ===========================
1685
+ // Tag Management
1686
+ // ===========================
1687
+ startEditingTags() {
1688
+ this.editingTags = true;
1689
+ this.cdr.markForCheck();
1690
+ }
1691
+ cancelEditingTags() {
1692
+ this.editingTags = false;
1693
+ this.newTag = '';
1694
+ this.parseTags(); // Reset to original
1695
+ this.cdr.markForCheck();
1696
+ }
1697
+ addTag() {
1698
+ const tag = this.newTag.trim();
1699
+ if (tag && !this.tags.includes(tag)) {
1700
+ this.tags = [...this.tags, tag];
1701
+ this.newTag = '';
1702
+ this.cdr.markForCheck();
1703
+ }
1704
+ }
1705
+ removeTag(tag) {
1706
+ this.tags = this.tags.filter(t => t !== tag);
1707
+ this.cdr.markForCheck();
1708
+ }
1709
+ async saveTags() {
1710
+ // Auto-add any pending tag in the input before saving
1711
+ const pendingTag = this.newTag.trim();
1712
+ if (pendingTag && !this.tags.includes(pendingTag)) {
1713
+ this.tags = [...this.tags, pendingTag];
1714
+ this.newTag = '';
1715
+ }
1716
+ this.savingTags = true;
1717
+ this.cdr.markForCheck();
1718
+ try {
1719
+ this.record.Tags = TagsHelper.toJson(this.tags);
1720
+ const result = await this.record.Save();
1721
+ if (result) {
1722
+ this.editingTags = false;
1723
+ SharedService.Instance.CreateSimpleNotification('Tags saved successfully', 'success', 2000);
1724
+ }
1725
+ else {
1726
+ SharedService.Instance.CreateSimpleNotification(this.record.LatestResult?.Message || 'Failed to save tags', 'error', 3000);
1727
+ }
1728
+ }
1729
+ catch (error) {
1730
+ SharedService.Instance.CreateSimpleNotification('Failed to save tags', 'error', 3000);
1731
+ }
1732
+ finally {
1733
+ this.savingTags = false;
1734
+ this.cdr.markForCheck();
1735
+ }
1736
+ }
1737
+ // ===========================
1738
+ // Test Run Filtering
1739
+ // ===========================
1740
+ setRunStatusFilter(status) {
1741
+ this.runStatusFilter = status;
1742
+ this.cdr.markForCheck();
1743
+ }
1744
+ getFilteredTestRuns() {
1745
+ if (!this.runStatusFilter)
1746
+ return this.testRuns;
1747
+ return this.testRuns.filter(run => run.Status === this.runStatusFilter);
1748
+ }
1749
+ getRunCountByStatus(status) {
1750
+ return this.testRuns.filter(run => run.Status === status).length;
1751
+ }
1752
+ // ===========================
1753
+ // Inline Feedback
1754
+ // ===========================
1755
+ async loadFeedbacks() {
1756
+ if (this.feedbacksLoaded)
1757
+ return;
1758
+ this.loadingFeedbacks = true;
1759
+ this.cdr.markForCheck();
1760
+ try {
1761
+ const testRunIds = this.testRuns.map(r => `'${r.ID}'`).join(',');
1762
+ if (!testRunIds)
1763
+ return;
1764
+ const rv = new RunView();
1765
+ const result = await rv.RunView({
1766
+ EntityName: 'MJ: Test Run Feedbacks',
1767
+ ExtraFilter: `TestRunID IN (${testRunIds})`,
1768
+ ResultType: 'entity_object'
1769
+ });
1770
+ if (result.Success && result.Results) {
1771
+ this.feedbacks.clear();
1772
+ for (const feedback of result.Results) {
1773
+ this.feedbacks.set(feedback.TestRunID, feedback);
1774
+ }
1775
+ }
1776
+ // Build TestRunWithFeedback array and calculate metrics
1777
+ this.buildTestRunsWithFeedback();
1778
+ this.feedbacksLoaded = true;
1779
+ }
1780
+ catch (error) {
1781
+ console.error('Error loading feedbacks:', error);
1782
+ }
1783
+ finally {
1784
+ this.loadingFeedbacks = false;
1785
+ this.cdr.markForCheck();
1786
+ }
1787
+ }
1788
+ /**
1789
+ * Build TestRunWithFeedback array from testRuns and feedbacks
1790
+ */
1791
+ buildTestRunsWithFeedback() {
1792
+ this.testRunsWithFeedback = this.testRuns.map(run => {
1793
+ const feedback = this.feedbacks.get(run.ID);
1794
+ return {
1795
+ id: run.ID,
1796
+ testId: run.TestID,
1797
+ testName: run.Test || 'Unknown Test',
1798
+ executionStatus: normalizeExecutionStatus(run.Status || 'Completed'),
1799
+ originalStatus: run.Status || 'Completed',
1800
+ duration: (run.DurationSeconds || 0) * 1000, // Convert to ms
1801
+ cost: run.CostUSD || 0,
1802
+ runDateTime: run.StartedAt ? new Date(run.StartedAt) : new Date(),
1803
+ autoScore: run.Score,
1804
+ passedChecks: null,
1805
+ failedChecks: null,
1806
+ totalChecks: null,
1807
+ humanRating: feedback?.Rating || null,
1808
+ humanIsCorrect: feedback?.IsCorrect ?? null,
1809
+ humanComments: feedback?.CorrectionSummary || null,
1810
+ hasHumanFeedback: !!feedback,
1811
+ feedbackId: feedback?.ID || null,
1812
+ tags: TagsHelper.parseTags(run.Tags),
1813
+ targetType: null,
1814
+ targetLogID: null
1815
+ };
1816
+ });
1817
+ // Calculate metrics
1818
+ this.evaluationMetrics = calculateEvaluationMetrics(this.testRunsWithFeedback);
1819
+ // Get items needing review
1820
+ this.needsReviewItems = getNeedsReviewItems(this.testRunsWithFeedback);
1821
+ }
1822
+ toggleRunExpanded(runId) {
1823
+ if (this.expandedRunId === runId) {
1824
+ this.expandedRunId = null;
1825
+ }
1826
+ else {
1827
+ this.expandedRunId = runId;
1828
+ this.initializeInlineFeedback(runId);
1829
+ }
1830
+ this.cdr.markForCheck();
1831
+ }
1832
+ initializeInlineFeedback(runId) {
1833
+ const existingFeedback = this.feedbacks.get(runId);
1834
+ if (existingFeedback) {
1835
+ this.inlineRating = existingFeedback.Rating || 0;
1836
+ this.inlineIsCorrect = existingFeedback.IsCorrect;
1837
+ this.inlineComments = existingFeedback.CorrectionSummary || '';
1838
+ }
1839
+ else {
1840
+ this.inlineRating = 0;
1841
+ this.inlineIsCorrect = null;
1842
+ this.inlineComments = '';
1843
+ }
1844
+ this.inlineHoverRating = 0;
1845
+ }
1846
+ setInlineRating(value) {
1847
+ this.inlineRating = value;
1848
+ this.cdr.markForCheck();
1849
+ }
1850
+ getInlineRatingLabel() {
1851
+ if (this.inlineRating <= 3)
1852
+ return 'Poor';
1853
+ if (this.inlineRating <= 5)
1854
+ return 'Below Average';
1855
+ if (this.inlineRating <= 6)
1856
+ return 'Average';
1857
+ if (this.inlineRating <= 7)
1858
+ return 'Good';
1859
+ if (this.inlineRating <= 8)
1860
+ return 'Very Good';
1861
+ if (this.inlineRating <= 9)
1862
+ return 'Excellent';
1863
+ return 'Outstanding';
1864
+ }
1865
+ canSubmitInlineFeedback() {
1866
+ return this.inlineRating > 0 && this.inlineComments.trim().length > 0;
1867
+ }
1868
+ async saveInlineFeedback() {
1869
+ if (!this.expandedRunId || !this.canSubmitInlineFeedback())
1870
+ return;
1871
+ this.savingInlineFeedback = true;
1872
+ this.cdr.markForCheck();
1873
+ try {
1874
+ const md = new Metadata();
1875
+ const currentUser = md.CurrentUser;
1876
+ let feedback = this.feedbacks.get(this.expandedRunId);
1877
+ if (!feedback) {
1878
+ feedback = await md.GetEntityObject('MJ: Test Run Feedbacks', currentUser);
1879
+ feedback.TestRunID = this.expandedRunId;
1880
+ feedback.ReviewerUserID = currentUser.ID;
1881
+ }
1882
+ feedback.Rating = this.inlineRating;
1883
+ feedback.IsCorrect = this.inlineIsCorrect;
1884
+ feedback.CorrectionSummary = this.inlineComments.trim() || null;
1885
+ const result = await feedback.Save();
1886
+ if (result) {
1887
+ this.feedbacks.set(this.expandedRunId, feedback);
1888
+ // Rebuild the metrics after feedback update
1889
+ this.buildTestRunsWithFeedback();
1890
+ SharedService.Instance.CreateSimpleNotification('Feedback saved', 'success', 2000);
1891
+ this.expandedRunId = null;
1892
+ }
1893
+ else {
1894
+ SharedService.Instance.CreateSimpleNotification(feedback.LatestResult?.Message || 'Failed to save feedback', 'error', 3000);
1895
+ }
1896
+ }
1897
+ catch (error) {
1898
+ SharedService.Instance.CreateSimpleNotification('Failed to save feedback', 'error', 3000);
1899
+ }
1900
+ finally {
1901
+ this.savingInlineFeedback = false;
1902
+ this.cdr.markForCheck();
1903
+ }
1904
+ }
1905
+ hasFeedback(runId) {
1906
+ return this.feedbacks.has(runId);
1907
+ }
1908
+ getFeedbackRating(runId) {
1909
+ return this.feedbacks.get(runId)?.Rating || 0;
1910
+ }
1911
+ /**
1912
+ * Get TestRunWithFeedback by run ID for template binding
1913
+ */
1914
+ getRunWithFeedback(runId) {
1915
+ return this.testRunsWithFeedback.find(r => r.id === runId);
1916
+ }
1917
+ /**
1918
+ * Get the human correctness status for a run
1919
+ */
1920
+ getHumanIsCorrect(runId) {
1921
+ return this.feedbacks.get(runId)?.IsCorrect ?? null;
1922
+ }
1923
+ // ===========================
1924
+ // Run Tags
1925
+ // ===========================
1926
+ getRunTags(run) {
1927
+ return TagsHelper.parseTags(run.Tags);
1928
+ }
1929
+ // ===========================
1930
+ // Keyboard Shortcuts Settings
1931
+ // ===========================
1932
+ /**
1933
+ * Load keyboard shortcuts visibility setting from user settings
1934
+ */
1935
+ loadShortcutsSetting() {
1936
+ try {
1937
+ const engine = UserInfoEngine.Instance;
1938
+ const setting = engine.UserSettings.find(s => s.Setting === SHORTCUTS_SETTINGS_KEY);
1939
+ if (setting) {
1940
+ this.shortcutsSettingEntity = setting;
1941
+ this.showShortcuts = setting.Value === 'true';
1942
+ }
1943
+ else {
1944
+ // Default to hidden
1945
+ this.showShortcuts = false;
1946
+ }
1947
+ this.cdr.markForCheck();
1948
+ }
1949
+ catch (error) {
1950
+ console.warn('Failed to load shortcuts setting:', error);
389
1951
  }
1952
+ }
1953
+ /**
1954
+ * Toggle keyboard shortcuts visibility and save preference
1955
+ */
1956
+ async toggleShortcuts() {
1957
+ this.showShortcuts = !this.showShortcuts;
390
1958
  this.cdr.markForCheck();
1959
+ try {
1960
+ const userId = this.metadata.CurrentUser?.ID;
1961
+ if (!userId)
1962
+ return;
1963
+ if (!this.shortcutsSettingEntity) {
1964
+ const engine = UserInfoEngine.Instance;
1965
+ const setting = engine.UserSettings.find(s => s.Setting === SHORTCUTS_SETTINGS_KEY);
1966
+ if (setting) {
1967
+ this.shortcutsSettingEntity = setting;
1968
+ }
1969
+ else {
1970
+ this.shortcutsSettingEntity = await this.metadata.GetEntityObject('MJ: User Settings');
1971
+ this.shortcutsSettingEntity.UserID = userId;
1972
+ this.shortcutsSettingEntity.Setting = SHORTCUTS_SETTINGS_KEY;
1973
+ }
1974
+ }
1975
+ this.shortcutsSettingEntity.Value = this.showShortcuts ? 'true' : 'false';
1976
+ await this.shortcutsSettingEntity.Save();
1977
+ }
1978
+ catch (error) {
1979
+ console.warn('Failed to save shortcuts setting:', error);
1980
+ }
1981
+ }
1982
+ // ===========================
1983
+ // Analytics Calculations
1984
+ // ===========================
1985
+ getPassedCount() {
1986
+ return this.testRuns.filter(r => r.Status === 'Passed').length;
1987
+ }
1988
+ getFailedCount() {
1989
+ return this.testRuns.filter(r => r.Status === 'Failed' || r.Status === 'Error').length;
1990
+ }
1991
+ getPassedPercent() {
1992
+ if (this.testRuns.length === 0)
1993
+ return 0;
1994
+ return (this.getPassedCount() / this.testRuns.length) * 100;
1995
+ }
1996
+ getFailedPercent() {
1997
+ if (this.testRuns.length === 0)
1998
+ return 0;
1999
+ return (this.getFailedCount() / this.testRuns.length) * 100;
2000
+ }
2001
+ getAverageScore() {
2002
+ const runsWithScore = this.testRuns.filter(r => r.Score != null);
2003
+ if (runsWithScore.length === 0)
2004
+ return 0;
2005
+ const sum = runsWithScore.reduce((acc, r) => acc + (r.Score || 0), 0);
2006
+ return sum / runsWithScore.length;
2007
+ }
2008
+ getAverageDuration() {
2009
+ const runsWithDuration = this.testRuns.filter(r => r.DurationSeconds != null);
2010
+ if (runsWithDuration.length === 0)
2011
+ return 0;
2012
+ const sum = runsWithDuration.reduce((acc, r) => acc + (r.DurationSeconds || 0), 0);
2013
+ return sum / runsWithDuration.length;
2014
+ }
2015
+ getTotalCost() {
2016
+ return this.testRuns.reduce((acc, r) => acc + (r.CostUSD || 0), 0);
2017
+ }
2018
+ // ===========================
2019
+ // Export
2020
+ // ===========================
2021
+ exportToCSV() {
2022
+ const headers = ['Test Name', 'Status', 'Score', 'Duration (s)', 'Cost (USD)', 'Started At', 'Tags'];
2023
+ const rows = this.testRuns.map(run => [
2024
+ run.Test || '',
2025
+ run.Status || '',
2026
+ run.Score?.toFixed(4) || '',
2027
+ run.DurationSeconds?.toFixed(2) || '',
2028
+ run.CostUSD?.toFixed(6) || '',
2029
+ run.StartedAt ? new Date(run.StartedAt).toISOString() : '',
2030
+ this.getRunTags(run).join('; ')
2031
+ ]);
2032
+ const csvContent = [headers, ...rows]
2033
+ .map(row => row.map(cell => `"${cell}"`).join(','))
2034
+ .join('\n');
2035
+ const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
2036
+ const link = document.createElement('a');
2037
+ link.href = URL.createObjectURL(blob);
2038
+ link.download = `test-suite-run-${this.record.ID.substring(0, 8)}-results.csv`;
2039
+ link.click();
2040
+ URL.revokeObjectURL(link.href);
2041
+ SharedService.Instance.CreateSimpleNotification('Export complete', 'success', 2000);
391
2042
  }
392
- static { this.ɵfac = function TestSuiteRunFormComponentExtended_Factory(t) { return new (t || TestSuiteRunFormComponentExtended)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i1.SharedService), i0.ɵɵdirectiveInject(i2.Router), i0.ɵɵdirectiveInject(i2.ActivatedRoute), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); }; }
393
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestSuiteRunFormComponentExtended, selectors: [["mj-test-suite-run-form"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 97, vars: 35, consts: [[1, "test-suite-run-form"], [1, "suite-run-header"], ["class", "breadcrumb", 4, "ngIf"], [1, "header-content"], [1, "header-left"], [1, "suite-run-icon"], [1, "fas", "fa-layer-group"], [1, "suite-run-info"], [1, "suite-run-meta"], [1, "status-badge"], [1, "fas", 3, "ngClass"], ["class", "environment", 4, "ngIf"], ["class", "trigger", 4, "ngIf"], [1, "header-actions"], ["kendoButton", "", "icon", "sync", 3, "click"], [1, "metrics-bar"], [1, "metric-card"], [1, "metric-label"], [1, "metric-value"], [1, "results-summary"], [1, "result-item", "passed"], [1, "fas", "fa-check-circle"], [1, "count"], [1, "label"], [1, "result-item", "failed"], [1, "fas", "fa-times-circle"], [1, "result-item", "skipped"], [1, "fas", "fa-forward"], [1, "result-item", "error"], [1, "fas", "fa-exclamation-circle"], [1, "result-item", "total"], [1, "fas", "fa-list"], [1, "tabs-container"], [1, "tabs"], [1, "tab", 3, "click"], [1, "fas", "fa-th-large"], ["class", "tab-badge", 4, "ngIf"], [1, "fas", "fa-info-circle"], [1, "tab-content"], ["class", "overview-tab", 4, "ngIf"], ["class", "runs-tab", 4, "ngIf"], ["class", "details-tab", 4, "ngIf"], [1, "breadcrumb"], ["href", "javascript:void(0)", 3, "click"], [1, "fas", "fa-folder"], [1, "fas", "fa-chevron-right"], [1, "environment"], [1, "trigger"], [1, "tab-badge"], [1, "overview-tab"], [1, "result-hero"], [1, "result-icon"], [1, "result-text"], [1, "result-stats"], [1, "result-counts"], [1, "runs-tab"], ["class", "test-runs-list", 4, "ngIf"], ["class", "no-data", 4, "ngIf"], [1, "test-runs-list"], ["class", "test-run-item", 3, "click", 4, "ngFor", "ngForOf"], [1, "test-run-item", 3, "click"], [1, "run-sequence"], [1, "run-icon"], [1, "fas"], [1, "run-content"], [1, "run-name"], [1, "run-meta"], [1, "status"], [4, "ngIf"], [1, "no-data"], [1, "fas", "fa-inbox"], [1, "details-tab"], [1, "details-grid"], [1, "detail-item"], [1, "detail-label"], [1, "detail-value"], ["href", "javascript:void(0)", 3, "click", 4, "ngIf"]], template: function TestSuiteRunFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
2043
+ static { this.ɵfac = function TestSuiteRunFormComponentExtended_Factory(t) { return new (t || TestSuiteRunFormComponentExtended)(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(i3.EvaluationPreferencesService)); }; }
2044
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestSuiteRunFormComponentExtended, selectors: [["mj-test-suite-run-form"]], hostBindings: function TestSuiteRunFormComponentExtended_HostBindings(rf, ctx) { if (rf & 1) {
2045
+ i0.ɵɵlistener("keydown", function TestSuiteRunFormComponentExtended_keydown_HostBindingHandler($event) { return ctx.handleKeyboardShortcut($event); }, false, i0.ɵɵresolveDocument);
2046
+ } }, features: [i0.ɵɵInheritDefinitionFeature], decls: 126, vars: 47, consts: [["kendoDialogContainer", "", 1, "test-suite-run-form"], [1, "suite-run-header"], ["class", "breadcrumb", 4, "ngIf"], [1, "header-content"], [1, "header-left"], [1, "suite-run-icon"], [1, "fas", 3, "ngClass"], [1, "suite-run-info"], [1, "suite-run-meta"], [1, "status-badge", 3, "ngClass"], ["class", "meta-tag environment", 4, "ngIf"], ["class", "meta-tag trigger", 4, "ngIf"], [1, "header-actions"], ["kendoButton", "", "themeColor", "primary", 3, "click", 4, "ngIf"], ["kendoButton", "", 3, "click", "disabled"], [1, "metrics-bar"], [1, "metric-card"], [1, "metric-icon"], [1, "fas", "fa-clock"], [1, "metric-content"], [1, "metric-value"], [1, "metric-label"], [1, "fas", "fa-percentage"], [1, "fas", "fa-dollar-sign"], [1, "fas", "fa-calendar"], [1, "results-summary"], [1, "result-item", "passed"], [1, "result-icon"], [1, "fas", "fa-check-circle"], [1, "result-content"], [1, "result-count"], [1, "result-label"], [1, "result-item", "failed"], [1, "fas", "fa-times-circle"], [1, "result-item", "error"], [1, "fas", "fa-exclamation-circle"], [1, "result-item", "skipped"], [1, "fas", "fa-forward"], [1, "result-item", "total"], [1, "fas", "fa-list"], ["class", "tags-bar", 4, "ngIf"], ["class", "tags-editor-panel", 4, "ngIf"], [1, "tabs-container"], ["role", "tablist", 1, "tabs"], ["role", "tab", 1, "tab", 3, "click"], [1, "fas", "fa-th-large"], ["class", "tab-badge", 4, "ngIf"], [1, "fas", "fa-info-circle"], ["role", "tab", "title", "Press 4", 1, "tab", 3, "click"], [1, "fas", "fa-chart-bar"], ["role", "tab", "title", "Press 5", 1, "tab", 3, "click"], [1, "fas", "fa-microchip"], [1, "tab-content"], ["class", "overview-tab", 4, "ngIf"], ["class", "runs-tab", 4, "ngIf"], ["class", "details-tab", 4, "ngIf"], ["class", "analytics-tab", 4, "ngIf"], ["class", "execution-tab", 4, "ngIf"], [1, "shortcuts-toggle", 3, "click", "title"], [1, "fas", "fa-keyboard"], ["class", "keyboard-shortcuts", 4, "ngIf"], [1, "breadcrumb"], ["href", "javascript:void(0)", 3, "click"], [1, "fas", "fa-layer-group"], [1, "fas", "fa-chevron-right", "separator"], [1, "current"], [1, "meta-tag", "environment"], [1, "fas", "fa-server"], [1, "meta-tag", "trigger"], [1, "fas", "fa-bolt"], ["kendoButton", "", "themeColor", "primary", 3, "click"], [1, "fas", "fa-play"], [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"], [1, "overview-tab"], [1, "result-hero"], [1, "result-hero-icon"], [1, "result-hero-text"], [1, "result-hero-stats"], [1, "stat-item"], [1, "stat-value"], [1, "stat-label"], [1, "stat-divider"], ["class", "evaluation-summary", 4, "ngIf"], ["class", "needs-review-section", 4, "ngIf"], ["class", "progress-section", 4, "ngIf"], [1, "evaluation-summary"], [1, "eval-summary-grid"], ["class", "eval-summary-card", 4, "ngIf"], [1, "eval-summary-card"], [1, "eval-card-header"], [1, "fa-solid", "fa-user"], [1, "eval-card-body"], [1, "eval-stat-row"], [1, "eval-stat-label"], [1, "eval-stat-value"], ["class", "eval-stat-row", 4, "ngIf"], ["class", "eval-card-footer", 4, "ngIf"], [1, "eval-stat-value", "correct"], ["class", "eval-stat-value incorrect", 4, "ngIf"], [1, "eval-stat-value", "incorrect"], [1, "eval-card-footer"], [1, "pending-badge"], [1, "fa-solid", "fa-clock"], [1, "fa-solid", "fa-robot"], [1, "fa-solid", "fa-circle-check"], ["class", "eval-stat-value error", 4, "ngIf"], ["class", "eval-stat-value timeout", 4, "ngIf"], [1, "eval-stat-value", "error"], [1, "eval-stat-value", "timeout"], [1, "needs-review-section"], [1, "needs-review-header"], [1, "fa-solid", "fa-user-clock"], [1, "review-count"], [1, "needs-review-list"], ["class", "review-item", 3, "high-priority", "medium-priority", "click", 4, "ngFor", "ngForOf"], ["class", "review-more", 4, "ngIf"], [1, "review-item", 3, "click"], [1, "review-item-icon"], ["class", "fa-solid fa-exclamation-triangle", 4, "ngIf"], ["class", "fa-solid fa-circle-dot", 4, "ngIf"], ["class", "fa-solid fa-clock", 4, "ngIf"], [1, "review-item-content"], [1, "review-item-name"], [1, "review-item-reason"], [1, "review-item-action"], [1, "fa-solid", "fa-chevron-right"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "fa-solid", "fa-circle-dot"], [1, "review-more"], [1, "progress-section"], [1, "progress-info"], [1, "fas", "fa-circle-notch", "fa-spin"], [1, "auto-refresh-notice"], [1, "fas", "fa-sync"], [1, "runs-tab"], ["class", "runs-toolbar", 4, "ngIf"], ["class", "loading-state", 4, "ngIf"], ["class", "test-runs-list", 4, "ngIf"], ["class", "empty-state", 4, "ngIf"], [1, "runs-toolbar"], [1, "run-filters"], [1, "filter-btn", 3, "click"], ["class", "filter-btn passed", 3, "active", "click", 4, "ngIf"], ["class", "filter-btn failed", 3, "active", "click", 4, "ngIf"], ["class", "filter-btn error", 3, "active", "click", 4, "ngIf"], [1, "runs-actions"], ["kendoButton", "", 3, "click"], [1, "fas", "fa-download"], [1, "filter-btn", "passed", 3, "click"], [1, "fas", "fa-check"], [1, "filter-btn", "failed", 3, "click"], [1, "filter-btn", "error", 3, "click"], [1, "fas", "fa-exclamation"], [1, "loading-state"], [1, "skeleton-list"], ["class", "skeleton-card", 4, "ngFor", "ngForOf"], [1, "skeleton-card"], [1, "skeleton-sequence"], [1, "skeleton-icon"], [1, "skeleton-content"], [1, "skeleton-line", "wide"], [1, "skeleton-line", "narrow"], [1, "test-runs-list"], ["class", "test-run-card", 4, "ngFor", "ngForOf"], [1, "test-run-card"], [1, "test-run-item", 3, "click"], [1, "run-sequence"], [1, "run-icon"], [1, "run-content"], [1, "run-header-row"], [1, "run-name"], [3, "executionStatus", "originalStatus", "autoScore", "humanRating", "humanIsCorrect", "hasHumanFeedback", "preferences", "mode"], [1, "run-meta"], ["class", "run-duration", 4, "ngIf"], ["class", "run-cost", 4, "ngIf"], [3, "entityName", "recordId", 4, "ngIf"], ["class", "run-tags", 4, "ngIf"], [1, "run-expand"], [1, "fas"], ["class", "inline-feedback", 4, "ngIf"], [1, "run-duration"], [1, "run-cost"], [3, "entityName", "recordId"], [1, "run-tags"], ["class", "tag-chip", 4, "ngFor", "ngForOf"], [1, "tag-chip"], [1, "inline-feedback"], [1, "feedback-divider"], [1, "feedback-section"], [1, "feedback-label"], [1, "inline-rating"], [1, "rating-numbers"], ["type", "button", "class", "rating-btn", 3, "selected", "hover", "low", "mid", "high", "click", "mouseenter", "mouseleave", 4, "ngFor", "ngForOf"], ["class", "rating-info", 4, "ngIf"], [1, "correctness-row"], [1, "correctness-label"], [1, "correctness-options"], [1, "radio-opt", 3, "click"], ["type", "radio", 3, "ngModelChange", "name", "value", "ngModel"], [1, "comments-row", 3, "click"], ["placeholder", "Add comments or corrections...", "rows", "3", 1, "feedback-textarea", 3, "ngModelChange", "ngModel"], [1, "feedback-actions", 3, "click"], [1, "fas", "fa-external-link-alt"], ["type", "button", 1, "rating-btn", 3, "click", "mouseenter", "mouseleave"], [1, "rating-info"], [1, "rating-value"], [1, "rating-label-text"], [1, "empty-state"], [1, "empty-icon"], [1, "fas", "fa-inbox"], [1, "fas", "fa-filter"], [1, "details-tab"], [1, "details-card"], [1, "details-grid"], [1, "detail-item"], [1, "detail-label"], [1, "detail-value", "monospace"], [1, "detail-value"], ["href", "javascript:void(0)", 3, "click", 4, "ngIf"], [4, "ngIf"], [1, "status-inline", 3, "ngClass"], [1, "analytics-tab"], ["class", "analytics-loading", 4, "ngIf"], ["class", "analytics-section", 4, "ngIf"], [1, "analytics-loading"], [1, "analytics-section"], [1, "fas", "fa-chart-pie"], [1, "stats-grid"], [1, "stat-card"], [1, "stat-icon", "passed"], [1, "stat-content"], [1, "stat-percent"], [1, "stat-icon", "failed"], [1, "stat-icon", "score"], [1, "fas", "fa-star"], [1, "stat-icon", "duration"], [1, "stat-icon", "cost"], [1, "analytics-header"], [1, "fas", "fa-table"], [1, "analytics-legend"], [1, "legend-item", "passed"], [1, "legend-item", "failed"], [1, "legend-item", "error"], [1, "legend-item", "skipped"], [1, "results-table-wrapper"], [1, "results-table"], [1, "seq-col"], [1, "name-col"], ["class", "status-col", 4, "ngIf"], ["class", "score-col", 4, "ngIf"], ["class", "feedback-col", 4, "ngIf"], [1, "duration-col"], [1, "cost-col"], ["class", "result-row", 3, "row-passed", "row-failed", "row-error", "row-skipped", "click", 4, "ngFor", "ngForOf"], [1, "status-col"], [1, "score-col"], [1, "feedback-col"], [1, "result-row", 3, "click"], [1, "test-name-wrapper"], [1, "test-name"], ["class", "test-tags", 4, "ngIf"], ["class", "na-value", 4, "ngIf"], [1, "test-tags"], ["class", "tag-mini", 4, "ngFor", "ngForOf"], [1, "tag-mini"], ["class", "score-display", 4, "ngIf"], [1, "score-display"], [1, "score-bar-mini"], [1, "score-fill"], [1, "score-text"], [1, "na-value"], ["class", "feedback-display", 4, "ngIf"], ["class", "na-value needs-review", 4, "ngIf"], [1, "feedback-display"], [1, "feedback-rating"], ["class", "feedback-correctness", 4, "ngIf"], [1, "feedback-correctness"], [1, "na-value", "needs-review"], [1, "fas", "fa-user-clock"], [1, "execution-tab"], [3, "machineName", "machineId", "runByUserName", "runByUserEmail", "runContextDetailsJson"], [1, "keyboard-shortcuts"], [1, "shortcuts-header"], ["title", "Hide shortcuts", 1, "shortcuts-close", 3, "click"], [1, "shortcut-list"], [1, "shortcut-item"], [1, "shortcut-keys"]], template: function TestSuiteRunFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
394
2047
  i0.ɵɵelementStart(0, "div", 0)(1, "div", 1);
395
2048
  i0.ɵɵtemplate(2, TestSuiteRunFormComponentExtended_div_2_Template, 7, 2, "div", 2);
396
2049
  i0.ɵɵelementStart(3, "div", 3)(4, "div", 4)(5, "div", 5);
397
2050
  i0.ɵɵelement(6, "i", 6);
398
2051
  i0.ɵɵelementEnd();
399
2052
  i0.ɵɵelementStart(7, "div", 7)(8, "h1");
400
- i0.ɵɵtext(9, "Test Suite Run");
2053
+ i0.ɵɵtext(9, "Suite Run");
401
2054
  i0.ɵɵelementEnd();
402
2055
  i0.ɵɵelementStart(10, "div", 8)(11, "span", 9);
403
- i0.ɵɵelement(12, "i", 10);
2056
+ i0.ɵɵelement(12, "i", 6);
404
2057
  i0.ɵɵtext(13);
405
2058
  i0.ɵɵelementEnd();
406
- i0.ɵɵtemplate(14, TestSuiteRunFormComponentExtended_span_14_Template, 2, 1, "span", 11)(15, TestSuiteRunFormComponentExtended_span_15_Template, 2, 1, "span", 12);
2059
+ i0.ɵɵtemplate(14, TestSuiteRunFormComponentExtended_span_14_Template, 3, 1, "span", 10)(15, TestSuiteRunFormComponentExtended_span_15_Template, 3, 1, "span", 11);
407
2060
  i0.ɵɵelementEnd()()();
408
- i0.ɵɵelementStart(16, "div", 13)(17, "button", 14);
409
- i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_Template_button_click_17_listener() { return ctx.refresh(); });
410
- i0.ɵɵtext(18, " Refresh ");
2061
+ i0.ɵɵelementStart(16, "div", 12);
2062
+ i0.ɵɵelement(17, "app-evaluation-mode-toggle");
2063
+ i0.ɵɵtemplate(18, TestSuiteRunFormComponentExtended_button_18_Template, 3, 0, "button", 13);
2064
+ i0.ɵɵelementStart(19, "button", 14);
2065
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_Template_button_click_19_listener() { return ctx.refresh(); });
2066
+ i0.ɵɵelement(20, "i", 6);
2067
+ i0.ɵɵtext(21);
411
2068
  i0.ɵɵelementEnd()()();
412
- i0.ɵɵelementStart(19, "div", 15)(20, "div", 16)(21, "div", 17);
413
- i0.ɵɵtext(22, "Started");
2069
+ i0.ɵɵelementStart(22, "div", 15)(23, "div", 16)(24, "div", 17);
2070
+ i0.ɵɵelement(25, "i", 18);
414
2071
  i0.ɵɵelementEnd();
415
- i0.ɵɵelementStart(23, "div", 18);
416
- i0.ɵɵtext(24);
417
- i0.ɵɵpipe(25, "date");
418
- i0.ɵɵelementEnd()();
419
- i0.ɵɵelementStart(26, "div", 16)(27, "div", 17);
420
- i0.ɵɵtext(28, "Completed");
2072
+ i0.ɵɵelementStart(26, "div", 19)(27, "div", 20);
2073
+ i0.ɵɵtext(28);
421
2074
  i0.ɵɵelementEnd();
422
- i0.ɵɵelementStart(29, "div", 18);
423
- i0.ɵɵtext(30);
424
- i0.ɵɵpipe(31, "date");
425
- i0.ɵɵelementEnd()();
426
- i0.ɵɵelementStart(32, "div", 16)(33, "div", 17);
427
- i0.ɵɵtext(34, "Duration");
2075
+ i0.ɵɵelementStart(29, "div", 21);
2076
+ i0.ɵɵtext(30, "Duration");
2077
+ i0.ɵɵelementEnd()()();
2078
+ i0.ɵɵelementStart(31, "div", 16)(32, "div", 17);
2079
+ i0.ɵɵelement(33, "i", 22);
428
2080
  i0.ɵɵelementEnd();
429
- i0.ɵɵelementStart(35, "div", 18);
2081
+ i0.ɵɵelementStart(34, "div", 19)(35, "div", 20);
430
2082
  i0.ɵɵtext(36);
431
- i0.ɵɵelementEnd()();
432
- i0.ɵɵelementStart(37, "div", 16)(38, "div", 17);
433
- i0.ɵɵtext(39, "Pass Rate");
434
2083
  i0.ɵɵelementEnd();
435
- i0.ɵɵelementStart(40, "div", 18);
436
- i0.ɵɵtext(41);
437
- i0.ɵɵelementEnd()();
438
- i0.ɵɵelementStart(42, "div", 16)(43, "div", 17);
439
- i0.ɵɵtext(44, "Cost");
2084
+ i0.ɵɵelementStart(37, "div", 21);
2085
+ i0.ɵɵtext(38, "Pass Rate");
2086
+ i0.ɵɵelementEnd()()();
2087
+ i0.ɵɵelementStart(39, "div", 16)(40, "div", 17);
2088
+ i0.ɵɵelement(41, "i", 23);
2089
+ i0.ɵɵelementEnd();
2090
+ i0.ɵɵelementStart(42, "div", 19)(43, "div", 20);
2091
+ i0.ɵɵtext(44);
440
2092
  i0.ɵɵelementEnd();
441
- i0.ɵɵelementStart(45, "div", 18);
442
- i0.ɵɵtext(46);
2093
+ i0.ɵɵelementStart(45, "div", 21);
2094
+ i0.ɵɵtext(46, "Total Cost");
443
2095
  i0.ɵɵelementEnd()()();
444
- i0.ɵɵelementStart(47, "div", 19)(48, "div", 20);
445
- i0.ɵɵelement(49, "i", 21);
446
- i0.ɵɵelementStart(50, "span", 22);
447
- i0.ɵɵtext(51);
2096
+ i0.ɵɵelementStart(47, "div", 16)(48, "div", 17);
2097
+ i0.ɵɵelement(49, "i", 24);
2098
+ i0.ɵɵelementEnd();
2099
+ i0.ɵɵelementStart(50, "div", 19)(51, "div", 20);
2100
+ i0.ɵɵtext(52);
448
2101
  i0.ɵɵelementEnd();
449
- i0.ɵɵelementStart(52, "span", 23);
450
- i0.ɵɵtext(53, "Passed");
451
- i0.ɵɵelementEnd()();
452
- i0.ɵɵelementStart(54, "div", 24);
453
- i0.ɵɵelement(55, "i", 25);
454
- i0.ɵɵelementStart(56, "span", 22);
455
- i0.ɵɵtext(57);
2102
+ i0.ɵɵelementStart(53, "div", 21);
2103
+ i0.ɵɵtext(54, "Started");
2104
+ i0.ɵɵelementEnd()()()();
2105
+ i0.ɵɵelementStart(55, "div", 25)(56, "div", 26)(57, "div", 27);
2106
+ i0.ɵɵelement(58, "i", 28);
2107
+ i0.ɵɵelementEnd();
2108
+ i0.ɵɵelementStart(59, "div", 29)(60, "span", 30);
2109
+ i0.ɵɵtext(61);
456
2110
  i0.ɵɵelementEnd();
457
- i0.ɵɵelementStart(58, "span", 23);
458
- i0.ɵɵtext(59, "Failed");
459
- i0.ɵɵelementEnd()();
460
- i0.ɵɵelementStart(60, "div", 26);
461
- i0.ɵɵelement(61, "i", 27);
462
- i0.ɵɵelementStart(62, "span", 22);
463
- i0.ɵɵtext(63);
2111
+ i0.ɵɵelementStart(62, "span", 31);
2112
+ i0.ɵɵtext(63, "Passed");
2113
+ i0.ɵɵelementEnd()()();
2114
+ i0.ɵɵelementStart(64, "div", 32)(65, "div", 27);
2115
+ i0.ɵɵelement(66, "i", 33);
464
2116
  i0.ɵɵelementEnd();
465
- i0.ɵɵelementStart(64, "span", 23);
466
- i0.ɵɵtext(65, "Skipped");
467
- i0.ɵɵelementEnd()();
468
- i0.ɵɵelementStart(66, "div", 28);
469
- i0.ɵɵelement(67, "i", 29);
470
- i0.ɵɵelementStart(68, "span", 22);
2117
+ i0.ɵɵelementStart(67, "div", 29)(68, "span", 30);
471
2118
  i0.ɵɵtext(69);
472
2119
  i0.ɵɵelementEnd();
473
- i0.ɵɵelementStart(70, "span", 23);
474
- i0.ɵɵtext(71, "Errors");
475
- i0.ɵɵelementEnd()();
476
- i0.ɵɵelementStart(72, "div", 30);
477
- i0.ɵɵelement(73, "i", 31);
478
- i0.ɵɵelementStart(74, "span", 22);
479
- i0.ɵɵtext(75);
2120
+ i0.ɵɵelementStart(70, "span", 31);
2121
+ i0.ɵɵtext(71, "Failed");
2122
+ i0.ɵɵelementEnd()()();
2123
+ i0.ɵɵelementStart(72, "div", 34)(73, "div", 27);
2124
+ i0.ɵɵelement(74, "i", 35);
2125
+ i0.ɵɵelementEnd();
2126
+ i0.ɵɵelementStart(75, "div", 29)(76, "span", 30);
2127
+ i0.ɵɵtext(77);
2128
+ i0.ɵɵelementEnd();
2129
+ i0.ɵɵelementStart(78, "span", 31);
2130
+ i0.ɵɵtext(79, "Errors");
2131
+ i0.ɵɵelementEnd()()();
2132
+ i0.ɵɵelementStart(80, "div", 36)(81, "div", 27);
2133
+ i0.ɵɵelement(82, "i", 37);
2134
+ i0.ɵɵelementEnd();
2135
+ i0.ɵɵelementStart(83, "div", 29)(84, "span", 30);
2136
+ i0.ɵɵtext(85);
480
2137
  i0.ɵɵelementEnd();
481
- i0.ɵɵelementStart(76, "span", 23);
482
- i0.ɵɵtext(77, "Total");
2138
+ i0.ɵɵelementStart(86, "span", 31);
2139
+ i0.ɵɵtext(87, "Skipped");
2140
+ i0.ɵɵelementEnd()()();
2141
+ i0.ɵɵelementStart(88, "div", 38)(89, "div", 27);
2142
+ i0.ɵɵelement(90, "i", 39);
2143
+ i0.ɵɵelementEnd();
2144
+ i0.ɵɵelementStart(91, "div", 29)(92, "span", 30);
2145
+ i0.ɵɵtext(93);
2146
+ i0.ɵɵelementEnd();
2147
+ i0.ɵɵelementStart(94, "span", 31);
2148
+ i0.ɵɵtext(95, "Total");
483
2149
  i0.ɵɵelementEnd()()()();
484
- i0.ɵɵelementStart(78, "div", 32)(79, "div", 33)(80, "button", 34);
485
- i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_Template_button_click_80_listener() { return ctx.changeTab("overview"); });
486
- i0.ɵɵelement(81, "i", 35);
487
- i0.ɵɵelementStart(82, "span");
488
- i0.ɵɵtext(83, "Overview");
489
- i0.ɵɵelementEnd()();
490
- i0.ɵɵelementStart(84, "button", 34);
491
- i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_Template_button_click_84_listener() { return ctx.changeTab("runs"); });
492
- i0.ɵɵelement(85, "i", 31);
493
- i0.ɵɵelementStart(86, "span");
494
- i0.ɵɵtext(87, "Test Runs");
2150
+ i0.ɵɵtemplate(96, TestSuiteRunFormComponentExtended_div_96_Template, 9, 2, "div", 40)(97, TestSuiteRunFormComponentExtended_div_97_Template, 19, 7, "div", 41);
2151
+ i0.ɵɵelementEnd();
2152
+ i0.ɵɵelementStart(98, "div", 42)(99, "div", 43)(100, "button", 44);
2153
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_Template_button_click_100_listener() { return ctx.changeTab("overview"); });
2154
+ i0.ɵɵelement(101, "i", 45);
2155
+ i0.ɵɵtext(102, " Overview ");
495
2156
  i0.ɵɵelementEnd();
496
- i0.ɵɵtemplate(88, TestSuiteRunFormComponentExtended_span_88_Template, 2, 1, "span", 36);
2157
+ i0.ɵɵelementStart(103, "button", 44);
2158
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_Template_button_click_103_listener() { return ctx.changeTab("runs"); });
2159
+ i0.ɵɵelement(104, "i", 39);
2160
+ i0.ɵɵtext(105, " Test Runs ");
2161
+ i0.ɵɵtemplate(106, TestSuiteRunFormComponentExtended_span_106_Template, 2, 1, "span", 46);
497
2162
  i0.ɵɵelementEnd();
498
- i0.ɵɵelementStart(89, "button", 34);
499
- i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_Template_button_click_89_listener() { return ctx.changeTab("details"); });
500
- i0.ɵɵelement(90, "i", 37);
501
- i0.ɵɵelementStart(91, "span");
502
- i0.ɵɵtext(92, "Details");
2163
+ i0.ɵɵelementStart(107, "button", 44);
2164
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_Template_button_click_107_listener() { return ctx.changeTab("details"); });
2165
+ i0.ɵɵelement(108, "i", 47);
2166
+ i0.ɵɵtext(109, " Details ");
2167
+ i0.ɵɵelementEnd();
2168
+ i0.ɵɵelementStart(110, "button", 48);
2169
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_Template_button_click_110_listener() { return ctx.changeTab("analytics"); });
2170
+ i0.ɵɵelement(111, "i", 49);
2171
+ i0.ɵɵtext(112, " Analytics ");
2172
+ i0.ɵɵelementEnd();
2173
+ i0.ɵɵelementStart(113, "button", 50);
2174
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_Template_button_click_113_listener() { return ctx.changeTab("execution"); });
2175
+ i0.ɵɵelement(114, "i", 51);
2176
+ i0.ɵɵelementStart(115, "span");
2177
+ i0.ɵɵtext(116, "Execution");
503
2178
  i0.ɵɵelementEnd()()()();
504
- i0.ɵɵelementStart(93, "div", 38);
505
- i0.ɵɵtemplate(94, TestSuiteRunFormComponentExtended_div_94_Template, 11, 9, "div", 39)(95, TestSuiteRunFormComponentExtended_div_95_Template, 3, 2, "div", 40)(96, TestSuiteRunFormComponentExtended_div_96_Template, 42, 8, "div", 41);
506
- i0.ɵɵelementEnd()();
2179
+ i0.ɵɵelementStart(117, "div", 52);
2180
+ i0.ɵɵtemplate(118, TestSuiteRunFormComponentExtended_div_118_Template, 22, 16, "div", 53)(119, TestSuiteRunFormComponentExtended_div_119_Template, 6, 5, "div", 54)(120, TestSuiteRunFormComponentExtended_div_120_Template, 60, 18, "div", 55)(121, TestSuiteRunFormComponentExtended_div_121_Template, 5, 4, "div", 56)(122, TestSuiteRunFormComponentExtended_div_122_Template, 2, 5, "div", 57);
2181
+ i0.ɵɵelementEnd();
2182
+ i0.ɵɵelementStart(123, "button", 58);
2183
+ i0.ɵɵlistener("click", function TestSuiteRunFormComponentExtended_Template_button_click_123_listener() { return ctx.toggleShortcuts(); });
2184
+ i0.ɵɵelement(124, "i", 59);
2185
+ i0.ɵɵelementEnd();
2186
+ i0.ɵɵtemplate(125, TestSuiteRunFormComponentExtended_div_125_Template, 34, 0, "div", 60);
2187
+ i0.ɵɵelementEnd();
507
2188
  } if (rf & 2) {
508
2189
  i0.ɵɵadvance(2);
509
2190
  i0.ɵɵproperty("ngIf", ctx.testSuite);
510
2191
  i0.ɵɵadvance(3);
511
2192
  i0.ɵɵstyleProp("background-color", ctx.getStatusColor());
512
- i0.ɵɵadvance(6);
513
- i0.ɵɵstyleProp("background-color", ctx.getStatusColor());
2193
+ i0.ɵɵadvance();
2194
+ i0.ɵɵproperty("ngClass", ctx.getStatusIcon());
2195
+ i0.ɵɵadvance(5);
2196
+ i0.ɵɵproperty("ngClass", ctx.getStatusClass());
514
2197
  i0.ɵɵadvance();
515
2198
  i0.ɵɵproperty("ngClass", ctx.getStatusIcon());
516
2199
  i0.ɵɵadvance();
@@ -519,41 +2202,68 @@ let TestSuiteRunFormComponentExtended = class TestSuiteRunFormComponentExtended
519
2202
  i0.ɵɵproperty("ngIf", ctx.record.Environment);
520
2203
  i0.ɵɵadvance();
521
2204
  i0.ɵɵproperty("ngIf", ctx.record.TriggerType);
522
- i0.ɵɵadvance(9);
523
- i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(25, 29, ctx.record.StartedAt, "short"));
524
- i0.ɵɵadvance(6);
525
- i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(31, 32, ctx.record.CompletedAt, "short"));
526
- i0.ɵɵadvance(6);
2205
+ i0.ɵɵadvance(3);
2206
+ i0.ɵɵproperty("ngIf", ctx.record.SuiteID);
2207
+ i0.ɵɵadvance();
2208
+ i0.ɵɵproperty("disabled", ctx.isRefreshing);
2209
+ i0.ɵɵadvance();
2210
+ i0.ɵɵproperty("ngClass", ctx.isRefreshing ? "fa-sync fa-spin" : "fa-sync");
2211
+ i0.ɵɵadvance();
2212
+ i0.ɵɵtextInterpolate1(" ", ctx.isRefreshing ? "Refreshing..." : "Refresh", " ");
2213
+ i0.ɵɵadvance(7);
527
2214
  i0.ɵɵtextInterpolate(ctx.calculateDuration());
528
- i0.ɵɵadvance(5);
2215
+ i0.ɵɵadvance(8);
529
2216
  i0.ɵɵtextInterpolate1("", ctx.getPassRate().toFixed(1), "%");
530
- i0.ɵɵadvance(5);
2217
+ i0.ɵɵadvance(8);
531
2218
  i0.ɵɵtextInterpolate(ctx.formatCost(ctx.record.TotalCostUSD));
532
- i0.ɵɵadvance(5);
2219
+ i0.ɵɵadvance(8);
2220
+ i0.ɵɵtextInterpolate(ctx.getRelativeTime(ctx.record.StartedAt));
2221
+ i0.ɵɵadvance(9);
533
2222
  i0.ɵɵtextInterpolate(ctx.record.PassedTests || 0);
534
- i0.ɵɵadvance(6);
2223
+ i0.ɵɵadvance(8);
535
2224
  i0.ɵɵtextInterpolate(ctx.record.FailedTests || 0);
536
- i0.ɵɵadvance(6);
537
- i0.ɵɵtextInterpolate(ctx.record.SkippedTests || 0);
538
- i0.ɵɵadvance(6);
2225
+ i0.ɵɵadvance(8);
539
2226
  i0.ɵɵtextInterpolate(ctx.record.ErrorTests || 0);
540
- i0.ɵɵadvance(6);
2227
+ i0.ɵɵadvance(8);
2228
+ i0.ɵɵtextInterpolate(ctx.record.SkippedTests || 0);
2229
+ i0.ɵɵadvance(8);
541
2230
  i0.ɵɵtextInterpolate(ctx.record.TotalTests || 0);
542
- i0.ɵɵadvance(5);
2231
+ i0.ɵɵadvance(3);
2232
+ i0.ɵɵproperty("ngIf", !ctx.editingTags);
2233
+ i0.ɵɵadvance();
2234
+ i0.ɵɵproperty("ngIf", ctx.editingTags);
2235
+ i0.ɵɵadvance(3);
543
2236
  i0.ɵɵclassProp("active", ctx.activeTab === "overview");
544
- i0.ɵɵadvance(4);
2237
+ i0.ɵɵattribute("aria-selected", ctx.activeTab === "overview");
2238
+ i0.ɵɵadvance(3);
545
2239
  i0.ɵɵclassProp("active", ctx.activeTab === "runs");
546
- i0.ɵɵadvance(4);
2240
+ i0.ɵɵattribute("aria-selected", ctx.activeTab === "runs");
2241
+ i0.ɵɵadvance(3);
547
2242
  i0.ɵɵproperty("ngIf", ctx.testRunsLoaded);
548
2243
  i0.ɵɵadvance();
549
2244
  i0.ɵɵclassProp("active", ctx.activeTab === "details");
2245
+ i0.ɵɵattribute("aria-selected", ctx.activeTab === "details");
2246
+ i0.ɵɵadvance(3);
2247
+ i0.ɵɵclassProp("active", ctx.activeTab === "analytics");
2248
+ i0.ɵɵattribute("aria-selected", ctx.activeTab === "analytics");
2249
+ i0.ɵɵadvance(3);
2250
+ i0.ɵɵclassProp("active", ctx.activeTab === "execution");
2251
+ i0.ɵɵattribute("aria-selected", ctx.activeTab === "execution");
550
2252
  i0.ɵɵadvance(5);
551
2253
  i0.ɵɵproperty("ngIf", ctx.activeTab === "overview");
552
2254
  i0.ɵɵadvance();
553
2255
  i0.ɵɵproperty("ngIf", ctx.activeTab === "runs");
554
2256
  i0.ɵɵadvance();
555
2257
  i0.ɵɵproperty("ngIf", ctx.activeTab === "details");
556
- } }, dependencies: [i3.NgClass, i3.NgForOf, i3.NgIf, i4.ButtonComponent, i3.DatePipe], styles: [".test-suite-run-form[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f8f9fa;\n}\n\n\n\n.suite-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.suite-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.suite-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.suite-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.environment[_ngcontent-%COMP%], \n.trigger[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #666;\n padding: 4px 8px;\n background: #f0f0f0;\n border-radius: 6px;\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.results-summary[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n padding-top: 16px;\n border-top: 1px solid #e0e0e0;\n}\n\n.result-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 8px;\n background: #f8f9fa;\n}\n\n.result-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n}\n\n.result-item[_ngcontent-%COMP%] .count[_ngcontent-%COMP%] {\n font-size: 20px;\n font-weight: 700;\n}\n\n.result-item[_ngcontent-%COMP%] .label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: #666;\n}\n\n.result-item.passed[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.result-item.passed[_ngcontent-%COMP%] .count[_ngcontent-%COMP%] {\n color: #4caf50;\n}\n\n.result-item.failed[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.result-item.failed[_ngcontent-%COMP%] .count[_ngcontent-%COMP%] {\n color: #f44336;\n}\n\n.result-item.skipped[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.result-item.skipped[_ngcontent-%COMP%] .count[_ngcontent-%COMP%] {\n color: #9e9e9e;\n}\n\n.result-item.error[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.result-item.error[_ngcontent-%COMP%] .count[_ngcontent-%COMP%] {\n color: #ff9800;\n}\n\n.result-item.total[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.result-item.total[_ngcontent-%COMP%] .count[_ngcontent-%COMP%] {\n color: #2196f3;\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-stats[_ngcontent-%COMP%] {\n font-size: 20px;\n font-weight: 600;\n color: #666;\n margin-bottom: 8px;\n}\n\n.result-counts[_ngcontent-%COMP%] {\n font-size: 16px;\n color: #999;\n}\n\n\n\n.test-runs-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.test-run-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: white;\n border: 2px solid transparent;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.test-run-item[_ngcontent-%COMP%]:hover {\n background: #e3f2fd;\n border-color: #90caf9;\n}\n\n.run-sequence[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #f0f0f0;\n border-radius: 50%;\n font-size: 14px;\n font-weight: 700;\n color: #666;\n flex-shrink: 0;\n}\n\n.run-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n color: white;\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.run-content[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.run-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: #333;\n margin-bottom: 4px;\n}\n\n.run-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: #666;\n}\n\n.run-meta[_ngcontent-%COMP%] .status[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.test-run-item[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: #999;\n font-size: 14px;\n}\n\n\n\n.details-tab[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.details-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\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\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 background: white;\n border-radius: 12px;\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 .results-summary[_ngcontent-%COMP%] {\n flex-wrap: wrap;\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 }); }
2258
+ i0.ɵɵadvance();
2259
+ i0.ɵɵproperty("ngIf", ctx.activeTab === "analytics");
2260
+ i0.ɵɵadvance();
2261
+ i0.ɵɵproperty("ngIf", ctx.activeTab === "execution");
2262
+ i0.ɵɵadvance();
2263
+ i0.ɵɵproperty("title", ctx.showShortcuts ? "Hide keyboard shortcuts" : "Show keyboard shortcuts");
2264
+ i0.ɵɵadvance(2);
2265
+ i0.ɵɵproperty("ngIf", ctx.showShortcuts);
2266
+ } }, dependencies: [i4.NgClass, i4.NgForOf, i4.NgIf, i5.DefaultValueAccessor, i5.RadioControlValueAccessor, i5.NgControlStatus, i5.NgModel, i6.DialogContainerDirective, i7.ButtonComponent, i3.EvaluationBadgeComponent, i3.EvaluationModeToggleComponent, i3.ExecutionContextComponent, i8.EntityLinkPillComponent, i4.DatePipe], styles: ["\n\n\n\n\n\n\n\n[_nghost-%COMP%] {\n --suite-run-primary: #3b82f6;\n --suite-run-primary-light: #eff6ff;\n --suite-run-success: #10b981;\n --suite-run-success-light: #ecfdf5;\n --suite-run-danger: #ef4444;\n --suite-run-danger-light: #fef2f2;\n --suite-run-warning: #f59e0b;\n --suite-run-warning-light: #fffbeb;\n --suite-run-info: #8b5cf6;\n --suite-run-info-light: #f5f3ff;\n --suite-run-neutral: #6b7280;\n --suite-run-neutral-light: #f9fafb;\n --suite-run-bg: #f8fafc;\n --suite-run-card: #ffffff;\n --suite-run-border: #e2e8f0;\n --suite-run-text: #1e293b;\n --suite-run-text-secondary: #64748b;\n --suite-run-radius: 12px;\n --suite-run-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);\n --suite-run-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n --suite-run-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n\n\n.test-suite-run-form[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--suite-run-bg);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n}\n\n\n\n\n\n.suite-run-header[_ngcontent-%COMP%] {\n background: var(--suite-run-card);\n border-bottom: 1px solid var(--suite-run-border);\n padding: 20px 24px;\n}\n\n\n\n.breadcrumb[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: var(--suite-run-text-secondary);\n margin-bottom: 16px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: var(--suite-run-transition);\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover {\n color: #2563eb;\n}\n\n.breadcrumb[_ngcontent-%COMP%] .separator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #cbd5e1;\n}\n\n.breadcrumb[_ngcontent-%COMP%] .current[_ngcontent-%COMP%] {\n color: var(--suite-run-text);\n font-weight: 500;\n}\n\n\n\n.header-content[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n align-items: flex-start;\n}\n\n.suite-run-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n border-radius: var(--suite-run-radius);\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(--suite-run-shadow);\n}\n\n.suite-run-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 24px;\n font-weight: 700;\n color: var(--suite-run-text);\n letter-spacing: -0.025em;\n}\n\n.suite-run-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.025em;\n}\n\n.status-badge.status-completed[_ngcontent-%COMP%] {\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.status-badge.status-failed[_ngcontent-%COMP%] {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.status-badge.status-running[_ngcontent-%COMP%] {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n}\n\n.status-badge.status-pending[_ngcontent-%COMP%] {\n background: var(--suite-run-info-light);\n color: var(--suite-run-info);\n}\n\n.status-badge.status-cancelled[_ngcontent-%COMP%] {\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-neutral);\n}\n\n.meta-tag[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--suite-run-neutral-light);\n border-radius: 6px;\n font-size: 12px;\n color: var(--suite-run-text-secondary);\n}\n\n.meta-tag[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.7;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n\n\n\n\n.metrics-bar[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 12px;\n margin-bottom: 20px;\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(--suite-run-border);\n border-radius: 10px;\n padding: 14px;\n transition: var(--suite-run-transition);\n}\n\n.metric-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--suite-run-shadow);\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(--suite-run-card);\n border-radius: 10px;\n color: var(--suite-run-primary);\n font-size: 16px;\n box-shadow: var(--suite-run-shadow);\n}\n\n.metric-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.metric-value[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 700;\n color: var(--suite-run-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\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: var(--suite-run-text-secondary);\n margin-top: 2px;\n}\n\n\n\n\n\n.results-summary[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding-top: 20px;\n border-top: 1px solid var(--suite-run-border);\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.result-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: 10px;\n flex-shrink: 0;\n transition: var(--suite-run-transition);\n}\n\n.result-item[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--suite-run-shadow);\n}\n\n.result-icon[_ngcontent-%COMP%] {\n font-size: 24px;\n}\n\n.result-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n}\n\n.result-count[_ngcontent-%COMP%] {\n font-size: 20px;\n font-weight: 700;\n line-height: 1.2;\n}\n\n.result-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 500;\n color: var(--suite-run-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.result-item.passed[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%], \n.result-item.passed[_ngcontent-%COMP%] .result-count[_ngcontent-%COMP%] {\n color: var(--suite-run-success);\n}\n\n.result-item.failed[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%], \n.result-item.failed[_ngcontent-%COMP%] .result-count[_ngcontent-%COMP%] {\n color: var(--suite-run-danger);\n}\n\n.result-item.error[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%], \n.result-item.error[_ngcontent-%COMP%] .result-count[_ngcontent-%COMP%] {\n color: var(--suite-run-warning);\n}\n\n.result-item.skipped[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%], \n.result-item.skipped[_ngcontent-%COMP%] .result-count[_ngcontent-%COMP%] {\n color: var(--suite-run-neutral);\n}\n\n.result-item.total[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%], \n.result-item.total[_ngcontent-%COMP%] .result-count[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n}\n\n\n\n\n\n.tabs-container[_ngcontent-%COMP%] {\n background: var(--suite-run-card);\n border-bottom: 1px solid var(--suite-run-border);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n\n.tabs[_ngcontent-%COMP%] {\n display: flex;\n padding: 0 24px;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: 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: 16px 20px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: var(--suite-run-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--suite-run-transition);\n white-space: nowrap;\n position: relative;\n}\n\n.tab[_ngcontent-%COMP%]:hover {\n color: var(--suite-run-primary);\n background: var(--suite-run-primary-light);\n}\n\n.tab.active[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n border-bottom-color: var(--suite-run-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(--suite-run-border);\n color: var(--suite-run-text-secondary);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active[_ngcontent-%COMP%] .tab-badge[_ngcontent-%COMP%] {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n}\n\n.tab-shortcut[_ngcontent-%COMP%] {\n display: none;\n width: 18px;\n height: 18px;\n background: var(--suite-run-neutral-light);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n color: var(--suite-run-text-secondary);\n align-items: center;\n justify-content: center;\n margin-left: 4px;\n}\n\n\n\n\n\n.tab-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 24px;\n}\n\n\n\n\n\n.overview-tab[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n max-width: 800px;\n margin: 0 auto;\n width: 100%;\n}\n\n.result-hero[_ngcontent-%COMP%] {\n background: var(--suite-run-card);\n border-radius: var(--suite-run-radius);\n padding: 48px 32px;\n text-align: center;\n border: 2px solid var(--suite-run-border);\n transition: var(--suite-run-transition);\n}\n\n.result-hero.passed[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%);\n border-color: var(--suite-run-success);\n}\n\n.result-hero.failed[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fef2f2 0%, #fecaca 100%);\n border-color: var(--suite-run-danger);\n}\n\n.result-hero.running[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);\n border-color: var(--suite-run-primary);\n}\n\n.result-hero.pending[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f5f3ff 0%, #ede9fe 100%);\n border-color: var(--suite-run-info);\n}\n\n.result-hero-icon[_ngcontent-%COMP%] {\n font-size: 72px;\n margin-bottom: 20px;\n}\n\n.result-hero.passed[_ngcontent-%COMP%] .result-hero-icon[_ngcontent-%COMP%] {\n color: var(--suite-run-success);\n}\n\n.result-hero.failed[_ngcontent-%COMP%] .result-hero-icon[_ngcontent-%COMP%] {\n color: var(--suite-run-danger);\n}\n\n.result-hero.running[_ngcontent-%COMP%] .result-hero-icon[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n}\n\n.result-hero.pending[_ngcontent-%COMP%] .result-hero-icon[_ngcontent-%COMP%] {\n color: var(--suite-run-info);\n}\n\n.result-hero-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 32px;\n font-weight: 800;\n color: var(--suite-run-text);\n letter-spacing: -0.025em;\n}\n\n.result-hero-stats[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 32px;\n}\n\n.stat-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--suite-run-text);\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--suite-run-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.stat-divider[_ngcontent-%COMP%] {\n width: 1px;\n height: 40px;\n background: var(--suite-run-border);\n}\n\n\n\n.progress-section[_ngcontent-%COMP%] {\n background: var(--suite-run-primary-light);\n border: 1px solid rgba(59, 130, 246, 0.2);\n border-radius: var(--suite-run-radius);\n padding: 20px;\n text-align: center;\n}\n\n.progress-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 500;\n color: var(--suite-run-primary);\n margin-bottom: 8px;\n}\n\n.progress-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n}\n\n.auto-refresh-notice[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n font-size: 12px;\n color: var(--suite-run-text-secondary);\n}\n\n\n\n\n\n.runs-tab[_ngcontent-%COMP%] {\n max-width: 900px;\n margin: 0 auto;\n width: 100%;\n}\n\n\n\n.loading-state[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\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: 12px;\n padding: 16px;\n background: var(--suite-run-card);\n border-radius: var(--suite-run-radius);\n border: 1px solid var(--suite-run-border);\n}\n\n.skeleton-sequence[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n border-radius: 50%;\n}\n\n.skeleton-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n border-radius: 8px;\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 background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n border-radius: 4px;\n}\n\n.skeleton-line.wide[_ngcontent-%COMP%] {\n width: 70%;\n}\n\n.skeleton-line.narrow[_ngcontent-%COMP%] {\n width: 40%;\n}\n\n@keyframes _ngcontent-%COMP%_shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n\n\n.test-runs-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.test-run-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.test-run-item[_ngcontent-%COMP%]:hover {\n background: var(--suite-run-primary-light);\n border-color: #93c5fd;\n transform: translateX(4px);\n}\n\n.test-run-item[_ngcontent-%COMP%]:active {\n transform: translateX(2px);\n}\n\n.run-sequence[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--suite-run-neutral-light);\n border-radius: 50%;\n font-size: 13px;\n font-weight: 700;\n color: var(--suite-run-text-secondary);\n flex-shrink: 0;\n}\n\n.run-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n color: white;\n font-size: 16px;\n flex-shrink: 0;\n box-shadow: var(--suite-run-shadow);\n}\n\n.run-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.run-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--suite-run-text);\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.run-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: var(--suite-run-text-secondary);\n flex-wrap: wrap;\n}\n\n.run-status[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.run-score[_ngcontent-%COMP%], \n.run-duration[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.run-score[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.run-duration[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.7;\n}\n\n.test-run-item[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: #cbd5e1;\n font-size: 14px;\n transition: var(--suite-run-transition);\n}\n\n.test-run-item[_ngcontent-%COMP%]:hover > i[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n transform: translateX(4px);\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 20px;\n text-align: center;\n background: var(--suite-run-card);\n border-radius: var(--suite-run-radius);\n border: 2px dashed var(--suite-run-border);\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(--suite-run-neutral-light);\n border-radius: 50%;\n margin-bottom: 20px;\n}\n\n.empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n color: #cbd5e1;\n}\n\n.empty-state[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--suite-run-text);\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: var(--suite-run-text-secondary);\n max-width: 300px;\n}\n\n\n\n\n\n.details-tab[_ngcontent-%COMP%] {\n max-width: 900px;\n margin: 0 auto;\n width: 100%;\n}\n\n.details-card[_ngcontent-%COMP%] {\n background: var(--suite-run-card);\n border-radius: var(--suite-run-radius);\n padding: 24px;\n box-shadow: var(--suite-run-shadow);\n}\n\n.details-card[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0 0 20px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--suite-run-text);\n padding-bottom: 12px;\n border-bottom: 1px solid var(--suite-run-border);\n}\n\n.details-card[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n}\n\n.details-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 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: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--suite-run-text-secondary);\n}\n\n.detail-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--suite-run-text);\n word-wrap: break-word;\n}\n\n.detail-value.monospace[_ngcontent-%COMP%] {\n font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;\n font-size: 12px;\n background: var(--suite-run-neutral-light);\n padding: 6px 10px;\n border-radius: 6px;\n}\n\n.detail-value[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n text-decoration: none;\n font-weight: 500;\n transition: var(--suite-run-transition);\n}\n\n.detail-value[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover {\n color: #2563eb;\n text-decoration: underline;\n}\n\n.status-inline[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.status-inline.status-completed[_ngcontent-%COMP%] {\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.status-inline.status-failed[_ngcontent-%COMP%] {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.status-inline.status-running[_ngcontent-%COMP%] {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n}\n\n.status-inline.status-pending[_ngcontent-%COMP%] {\n background: var(--suite-run-info-light);\n color: var(--suite-run-info);\n}\n\n.status-inline.status-cancelled[_ngcontent-%COMP%] {\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-neutral);\n}\n\n\n\n\n\n\n\n.shortcuts-toggle[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n box-shadow: var(--suite-run-shadow);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--suite-run-text-secondary);\n font-size: 14px;\n z-index: 99;\n transition: var(--suite-run-transition);\n opacity: 0.7;\n}\n\n.shortcuts-toggle[_ngcontent-%COMP%]:hover {\n opacity: 1;\n transform: scale(1.1);\n color: var(--suite-run-primary);\n border-color: var(--suite-run-primary);\n}\n\n.keyboard-shortcuts[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n padding: 12px 16px;\n box-shadow: var(--suite-run-shadow-lg);\n font-size: 12px;\n z-index: 100;\n opacity: 0.9;\n transition: var(--suite-run-transition);\n}\n\n.keyboard-shortcuts[_ngcontent-%COMP%]:hover {\n opacity: 1;\n}\n\n.shortcuts-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-weight: 600;\n color: var(--suite-run-text);\n margin-bottom: 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--suite-run-border);\n}\n\n.shortcuts-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n}\n\n.shortcuts-close[_ngcontent-%COMP%] {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--suite-run-text-muted);\n font-size: 12px;\n padding: 2px 4px;\n border-radius: 4px;\n transition: var(--suite-run-transition);\n}\n\n.shortcuts-close[_ngcontent-%COMP%]:hover {\n color: var(--suite-run-text);\n background: var(--suite-run-border);\n}\n\n.shortcut-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.shortcut-item[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n}\n\n.shortcut-item[_ngcontent-%COMP%] span[_ngcontent-%COMP%]:first-child {\n color: var(--suite-run-text-secondary);\n}\n\n.shortcut-keys[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\nkbd[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n background: linear-gradient(180deg, #f8fafc 0%, #e2e8f0 100%);\n border: 1px solid #cbd5e1;\n border-radius: 4px;\n font-family: inherit;\n font-size: 10px;\n font-weight: 600;\n color: var(--suite-run-text);\n box-shadow: 0 1px 0 #94a3b8;\n}\n\n\n\n\n\n@media (max-width: 1024px) {\n .suite-run-header[_ngcontent-%COMP%] {\n padding: 16px 20px;\n }\n\n .metrics-bar[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .result-hero-stats[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .stat-divider[_ngcontent-%COMP%] {\n display: none;\n }\n\n .details-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .tab-shortcut[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n\n\n\n\n@media (max-width: 768px) {\n .suite-run-header[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .header-content[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-left[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .suite-run-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n font-size: 20px;\n }\n\n .suite-run-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: 20px;\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: 8px;\n }\n\n .metric-card[_ngcontent-%COMP%] {\n padding: 12px;\n flex-direction: column;\n text-align: center;\n gap: 8px;\n }\n\n .metric-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n }\n\n .metric-value[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .results-summary[_ngcontent-%COMP%] {\n gap: 8px;\n padding-top: 16px;\n flex-wrap: nowrap;\n overflow-x: auto;\n padding-bottom: 8px;\n margin-bottom: -8px;\n }\n\n .result-item[_ngcontent-%COMP%] {\n padding: 10px 12px;\n min-width: 90px;\n }\n\n .result-icon[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .result-count[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n\n .tabs[_ngcontent-%COMP%] {\n padding: 0 16px;\n }\n\n .tab[_ngcontent-%COMP%] {\n padding: 14px 16px;\n font-size: 13px;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .result-hero[_ngcontent-%COMP%] {\n padding: 32px 20px;\n }\n\n .result-hero-icon[_ngcontent-%COMP%] {\n font-size: 56px;\n }\n\n .result-hero-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n font-size: 24px;\n }\n\n .stat-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .test-run-item[_ngcontent-%COMP%] {\n padding: 14px;\n }\n\n .run-sequence[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n font-size: 12px;\n }\n\n .run-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n font-size: 14px;\n }\n\n .run-name[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n\n .run-meta[_ngcontent-%COMP%] {\n gap: 10px;\n font-size: 11px;\n }\n\n .empty-state[_ngcontent-%COMP%] {\n padding: 40px 16px;\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 .details-card[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .details-grid[_ngcontent-%COMP%] {\n gap: 16px;\n }\n\n .keyboard-shortcuts[_ngcontent-%COMP%], .shortcuts-toggle[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n\n\n\n\n@media (max-width: 480px) {\n .suite-run-header[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .breadcrumb[_ngcontent-%COMP%] {\n font-size: 12px;\n margin-bottom: 12px;\n }\n\n .suite-run-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n font-size: 18px;\n }\n\n .suite-run-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n\n .suite-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 .meta-tag[_ngcontent-%COMP%] {\n font-size: 11px;\n padding: 3px 8px;\n }\n\n .metrics-bar[_ngcontent-%COMP%] {\n grid-template-columns: 1fr 1fr;\n }\n\n .metric-card[_ngcontent-%COMP%] {\n padding: 10px;\n gap: 6px;\n }\n\n .metric-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n font-size: 14px;\n }\n\n .metric-value[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n\n .metric-label[_ngcontent-%COMP%] {\n font-size: 9px;\n }\n\n .result-item[_ngcontent-%COMP%] {\n padding: 8px 10px;\n min-width: 80px;\n gap: 8px;\n }\n\n .result-icon[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n\n .result-count[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .result-label[_ngcontent-%COMP%] {\n font-size: 9px;\n }\n\n .tabs[_ngcontent-%COMP%] {\n padding: 0 12px;\n }\n\n .tab[_ngcontent-%COMP%] {\n padding: 12px 14px;\n gap: 6px;\n }\n\n .tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .result-hero[_ngcontent-%COMP%] {\n padding: 24px 16px;\n }\n\n .result-hero-icon[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n }\n\n .result-hero-text[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n font-size: 20px;\n margin-bottom: 12px;\n }\n\n .stat-value[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n\n .stat-label[_ngcontent-%COMP%] {\n font-size: 10px;\n }\n\n .progress-section[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .progress-info[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n\n .test-run-item[_ngcontent-%COMP%] {\n padding: 12px;\n gap: 10px;\n }\n\n .run-sequence[_ngcontent-%COMP%] {\n width: 24px;\n height: 24px;\n font-size: 11px;\n }\n\n .run-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n font-size: 12px;\n border-radius: 8px;\n }\n\n .run-name[_ngcontent-%COMP%] {\n font-size: 12px;\n margin-bottom: 3px;\n }\n\n .run-meta[_ngcontent-%COMP%] {\n gap: 8px;\n font-size: 10px;\n }\n\n .empty-state[_ngcontent-%COMP%] {\n padding: 32px 12px;\n }\n\n .empty-state[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n\n .details-card[_ngcontent-%COMP%] {\n padding: 14px;\n }\n\n .details-card[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 14px;\n margin-bottom: 16px;\n }\n\n .detail-label[_ngcontent-%COMP%] {\n font-size: 10px;\n }\n\n .detail-value[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n}\n\n\n\n\n\n@media (hover: none) and (pointer: coarse) {\n .test-run-item[_ngcontent-%COMP%] {\n min-height: 64px;\n }\n\n .test-run-item[_ngcontent-%COMP%]:hover {\n transform: none;\n background: var(--suite-run-card);\n border-color: var(--suite-run-border);\n }\n\n .test-run-item[_ngcontent-%COMP%]:active {\n background: var(--suite-run-primary-light);\n border-color: #93c5fd;\n }\n\n .tab[_ngcontent-%COMP%]:hover {\n background: transparent;\n color: var(--suite-run-text-secondary);\n }\n\n .tab[_ngcontent-%COMP%]:active {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n }\n\n .metric-card[_ngcontent-%COMP%]:hover {\n transform: none;\n box-shadow: none;\n }\n\n .result-item[_ngcontent-%COMP%]:hover {\n transform: none;\n box-shadow: none;\n }\n\n .keyboard-shortcuts[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n\n\n\n\n@media print {\n .suite-run-header[_ngcontent-%COMP%] {\n background: white;\n box-shadow: none;\n border-bottom: 2px solid #000;\n }\n\n .tabs-container[_ngcontent-%COMP%], \n .header-actions[_ngcontent-%COMP%], \n .keyboard-shortcuts[_ngcontent-%COMP%] {\n display: none;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n padding: 20px 0;\n }\n\n .result-hero[_ngcontent-%COMP%], \n .test-run-item[_ngcontent-%COMP%], \n .details-card[_ngcontent-%COMP%] {\n box-shadow: none;\n border: 1px solid #ccc;\n }\n}\n\n\n\n\n\n@media (prefers-color-scheme: dark) {\n \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(59, 130, 246, 0.04) 0%, rgba(59, 130, 246, 0.08) 100%);\n border: 1px solid rgba(59, 130, 246, 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(--suite-run-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: var(--suite-run-primary-light);\n color: var(--suite-run-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(--suite-run-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(--suite-run-border);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--suite-run-text-secondary);\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.tags-bar-edit[_ngcontent-%COMP%]:hover {\n border-color: var(--suite-run-primary);\n color: var(--suite-run-primary);\n background: var(--suite-run-primary-light);\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(--suite-run-card);\n border: 1px solid var(--suite-run-primary);\n border-radius: 10px;\n overflow: hidden;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 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: var(--suite-run-primary-light);\n border-bottom: 1px solid rgba(59, 130, 246, 0.2);\n}\n\n.tags-editor-title[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--suite-run-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(--suite-run-card);\n border: 1px solid var(--suite-run-primary);\n color: var(--suite-run-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(--suite-run-primary);\n cursor: pointer;\n border-radius: 50%;\n font-size: 9px;\n opacity: 0.6;\n transition: var(--suite-run-transition);\n}\n\n.tag-remove-btn[_ngcontent-%COMP%]:hover {\n opacity: 1;\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.tags-empty-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--suite-run-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(--suite-run-border);\n border-radius: 8px;\n font-size: 13px;\n background: var(--suite-run-neutral-light);\n}\n\n.tag-text-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--suite-run-primary);\n background: var(--suite-run-card);\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.tag-text-input[_ngcontent-%COMP%]::placeholder {\n color: var(--suite-run-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(--suite-run-neutral-light);\n border-top: 1px solid var(--suite-run-border);\n}\n\n\n\n\n\n.runs-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding: 12px 16px;\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.run-filters[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.filter-btn[_ngcontent-%COMP%] {\n padding: 6px 14px;\n border: 1px solid var(--suite-run-border);\n background: var(--suite-run-card);\n border-radius: 20px;\n font-size: 12px;\n font-weight: 500;\n color: var(--suite-run-text-secondary);\n cursor: pointer;\n transition: var(--suite-run-transition);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.filter-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--suite-run-primary);\n color: var(--suite-run-primary);\n}\n\n.filter-btn.active[_ngcontent-%COMP%] {\n background: var(--suite-run-primary);\n border-color: var(--suite-run-primary);\n color: white;\n}\n\n.filter-btn.passed[_ngcontent-%COMP%]:hover, \n.filter-btn.passed.active[_ngcontent-%COMP%] {\n background: var(--suite-run-success);\n border-color: var(--suite-run-success);\n color: white;\n}\n\n.filter-btn.failed[_ngcontent-%COMP%]:hover, \n.filter-btn.failed.active[_ngcontent-%COMP%] {\n background: var(--suite-run-danger);\n border-color: var(--suite-run-danger);\n color: white;\n}\n\n.filter-btn.error[_ngcontent-%COMP%]:hover, \n.filter-btn.error.active[_ngcontent-%COMP%] {\n background: var(--suite-run-warning);\n border-color: var(--suite-run-warning);\n color: white;\n}\n\n.runs-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n\n\n\n\n.test-run-card[_ngcontent-%COMP%] {\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n overflow: hidden;\n transition: var(--suite-run-transition);\n margin-bottom: 10px;\n}\n\n.test-run-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--suite-run-shadow);\n}\n\n.test-run-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.test-run-item[_ngcontent-%COMP%]:hover {\n background: var(--suite-run-primary-light);\n}\n\n.run-header-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 4px;\n}\n\n.run-feedback-indicator[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 2px 8px;\n background: var(--suite-run-info-light);\n color: var(--suite-run-info);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.run-feedback-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.run-tags[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-top: 6px;\n}\n\n.tag-mini[_ngcontent-%COMP%] {\n display: inline-flex;\n padding: 2px 8px;\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-text-secondary);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 500;\n}\n\n.tag-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 3px 10px;\n background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);\n border: 1px solid #bfdbfe;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: #1d4ed8;\n}\n\n.run-expand[_ngcontent-%COMP%] {\n color: var(--suite-run-text-secondary);\n transition: var(--suite-run-transition);\n}\n\n.test-run-item[_ngcontent-%COMP%]:hover .run-expand[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n}\n\n.run-cost[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.run-cost[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.7;\n}\n\n\n\n\n\n.inline-feedback[_ngcontent-%COMP%] {\n padding: 0 16px 16px;\n animation: _ngcontent-%COMP%_slideDown 0.2s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.feedback-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: var(--suite-run-border);\n margin-bottom: 16px;\n}\n\n.feedback-section[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.feedback-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--suite-run-text);\n}\n\n.inline-rating[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.rating-numbers[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.rating-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border: 2px solid var(--suite-run-border);\n border-radius: 8px;\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-text-secondary);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.rating-btn[_ngcontent-%COMP%]:hover, \n.rating-btn.hover[_ngcontent-%COMP%] {\n transform: scale(1.1);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}\n\n.rating-btn.low[_ngcontent-%COMP%]:hover, \n.rating-btn.low.hover[_ngcontent-%COMP%] {\n border-color: var(--suite-run-danger);\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.rating-btn.mid[_ngcontent-%COMP%]:hover, \n.rating-btn.mid.hover[_ngcontent-%COMP%] {\n border-color: var(--suite-run-warning);\n background: var(--suite-run-warning-light);\n color: var(--suite-run-warning);\n}\n\n.rating-btn.high[_ngcontent-%COMP%]:hover, \n.rating-btn.high.hover[_ngcontent-%COMP%] {\n border-color: var(--suite-run-success);\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.rating-btn.selected[_ngcontent-%COMP%] {\n transform: scale(1.1);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}\n\n.rating-btn.selected.low[_ngcontent-%COMP%] {\n border-color: var(--suite-run-danger);\n background: var(--suite-run-danger);\n color: white;\n}\n\n.rating-btn.selected.mid[_ngcontent-%COMP%] {\n border-color: var(--suite-run-warning);\n background: var(--suite-run-warning);\n color: white;\n}\n\n.rating-btn.selected.high[_ngcontent-%COMP%] {\n border-color: var(--suite-run-success);\n background: var(--suite-run-success);\n color: white;\n}\n\n.rating-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 14px;\n background: var(--suite-run-neutral-light);\n border-radius: 8px;\n}\n\n.rating-value[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 700;\n color: var(--suite-run-text);\n}\n\n.rating-label-text[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--suite-run-text-secondary);\n}\n\n.correctness-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.correctness-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--suite-run-text);\n}\n\n.correctness-options[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n}\n\n.radio-opt[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n font-size: 13px;\n color: var(--suite-run-text-secondary);\n}\n\n.radio-opt[_ngcontent-%COMP%] input[type=\"radio\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.comments-row[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.feedback-textarea[_ngcontent-%COMP%] {\n width: 100%;\n padding: 12px;\n border: 1px solid var(--suite-run-border);\n border-radius: 8px;\n font-size: 14px;\n font-family: inherit;\n resize: vertical;\n min-height: 80px;\n}\n\n.feedback-textarea[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--suite-run-primary);\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);\n}\n\n.feedback-actions[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n padding-top: 8px;\n}\n\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\n .runs-toolbar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n }\n\n .run-filters[_ngcontent-%COMP%] {\n justify-content: center;\n }\n\n .runs-actions[_ngcontent-%COMP%] {\n justify-content: center;\n }\n\n .rating-numbers[_ngcontent-%COMP%] {\n justify-content: center;\n }\n\n .rating-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n font-size: 12px;\n }\n\n .correctness-row[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n\n .feedback-actions[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .feedback-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n width: 100%;\n }\n}\n\n\n\n\n\n@keyframes _ngcontent-%COMP%_pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n\n.result-hero.running[_ngcontent-%COMP%] .result-hero-icon[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_pulse 2s ease-in-out infinite;\n}\n\n\n\n.overview-tab[_ngcontent-%COMP%], \n.runs-tab[_ngcontent-%COMP%], \n.details-tab[_ngcontent-%COMP%], \n.analytics-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease;\n}\n\n\n\n\n\n.analytics-tab[_ngcontent-%COMP%] {\n max-width: 1200px;\n margin: 0 auto;\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.analytics-section[_ngcontent-%COMP%] {\n background: var(--suite-run-card);\n border-radius: var(--suite-run-radius);\n padding: 24px;\n box-shadow: var(--suite-run-shadow);\n}\n\n.analytics-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0 0 20px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--suite-run-text);\n padding-bottom: 12px;\n border-bottom: 1px solid var(--suite-run-border);\n}\n\n.analytics-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n}\n\n.analytics-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-bottom: 20px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--suite-run-border);\n}\n\n.analytics-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n padding: 0;\n border: none;\n}\n\n.analytics-legend[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n}\n\n.legend-item.passed[_ngcontent-%COMP%] {\n color: var(--suite-run-success);\n}\n\n.legend-item.failed[_ngcontent-%COMP%] {\n color: var(--suite-run-danger);\n}\n\n.legend-item.error[_ngcontent-%COMP%] {\n color: var(--suite-run-warning);\n}\n\n.legend-item.skipped[_ngcontent-%COMP%] {\n color: var(--suite-run-neutral);\n}\n\n\n\n.performance-matrix[_ngcontent-%COMP%] {\n border: 1px solid var(--suite-run-border);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.matrix-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 120px 150px 100px 100px;\n border-bottom: 1px solid var(--suite-run-border);\n transition: var(--suite-run-transition);\n cursor: pointer;\n}\n\n.matrix-row[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.matrix-row[_ngcontent-%COMP%]:hover:not(.matrix-header-row) {\n background: var(--suite-run-primary-light);\n}\n\n.matrix-row.passed[_ngcontent-%COMP%] {\n border-left: 4px solid var(--suite-run-success);\n}\n\n.matrix-row.failed[_ngcontent-%COMP%] {\n border-left: 4px solid var(--suite-run-danger);\n}\n\n.matrix-row.error[_ngcontent-%COMP%] {\n border-left: 4px solid var(--suite-run-warning);\n}\n\n.matrix-row.skipped[_ngcontent-%COMP%] {\n border-left: 4px solid var(--suite-run-neutral);\n}\n\n.matrix-header-row[_ngcontent-%COMP%] {\n background: var(--suite-run-neutral-light);\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--suite-run-text-secondary);\n cursor: default;\n}\n\n.matrix-cell[_ngcontent-%COMP%] {\n padding: 12px 16px;\n display: flex;\n align-items: center;\n}\n\n.test-name-cell[_ngcontent-%COMP%] {\n gap: 12px;\n}\n\n.test-sequence[_ngcontent-%COMP%] {\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--suite-run-neutral-light);\n border-radius: 50%;\n font-size: 11px;\n font-weight: 600;\n color: var(--suite-run-text-secondary);\n flex-shrink: 0;\n}\n\n.test-name[_ngcontent-%COMP%] {\n font-weight: 500;\n color: var(--suite-run-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.status-indicator[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.status-indicator.status-passed[_ngcontent-%COMP%] {\n color: var(--suite-run-success);\n}\n\n.status-indicator.status-failed[_ngcontent-%COMP%] {\n color: var(--suite-run-danger);\n}\n\n.status-indicator.status-error[_ngcontent-%COMP%] {\n color: var(--suite-run-warning);\n}\n\n.status-indicator.status-skipped[_ngcontent-%COMP%] {\n color: var(--suite-run-neutral);\n}\n\n.status-indicator.status-pending[_ngcontent-%COMP%] {\n color: var(--suite-run-info);\n}\n\n.status-indicator.status-running[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n}\n\n.score-bar[_ngcontent-%COMP%] {\n position: relative;\n width: 100%;\n height: 20px;\n background: var(--suite-run-neutral-light);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.score-fill[_ngcontent-%COMP%] {\n height: 100%;\n border-radius: 10px;\n transition: width 0.3s ease;\n}\n\n.score-fill.high[_ngcontent-%COMP%] {\n background: linear-gradient(90deg, var(--suite-run-success) 0%, #34d399 100%);\n}\n\n.score-fill.medium[_ngcontent-%COMP%] {\n background: linear-gradient(90deg, var(--suite-run-warning) 0%, #fbbf24 100%);\n}\n\n.score-fill.low[_ngcontent-%COMP%] {\n background: linear-gradient(90deg, var(--suite-run-danger) 0%, #f87171 100%);\n}\n\n.score-text[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 11px;\n font-weight: 600;\n color: var(--suite-run-text);\n}\n\n.na-value[_ngcontent-%COMP%] {\n color: var(--suite-run-text-secondary);\n opacity: 0.6;\n}\n\n\n\n.stats-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n}\n\n.stat-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);\n border: 1px solid var(--suite-run-border);\n border-radius: 12px;\n transition: var(--suite-run-transition);\n}\n\n.stat-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--suite-run-shadow);\n}\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 12px;\n font-size: 20px;\n}\n\n.stat-icon.passed[_ngcontent-%COMP%] {\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.stat-icon.failed[_ngcontent-%COMP%] {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.stat-icon.score[_ngcontent-%COMP%] {\n background: var(--suite-run-warning-light);\n color: var(--suite-run-warning);\n}\n\n.stat-icon.duration[_ngcontent-%COMP%] {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n}\n\n.stat-icon.cost[_ngcontent-%COMP%] {\n background: var(--suite-run-info-light);\n color: var(--suite-run-info);\n}\n\n.stat-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.stat-card[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--suite-run-text);\n}\n\n.stat-card[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--suite-run-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.stat-percent[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--suite-run-text-secondary);\n}\n\n\n\n@media (max-width: 768px) {\n .analytics-header[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .matrix-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 8px;\n padding: 12px;\n }\n\n .matrix-header-row[_ngcontent-%COMP%] {\n display: none;\n }\n\n .matrix-cell[_ngcontent-%COMP%] {\n padding: 4px 0;\n }\n\n .test-name-cell[_ngcontent-%COMP%]::before, \n .status-cell[_ngcontent-%COMP%]::before, \n .score-cell[_ngcontent-%COMP%]::before, \n .duration-cell[_ngcontent-%COMP%]::before, \n .cost-cell[_ngcontent-%COMP%]::before {\n font-size: 10px;\n font-weight: 600;\n color: var(--suite-run-text-secondary);\n text-transform: uppercase;\n margin-right: 8px;\n min-width: 80px;\n }\n\n .status-cell[_ngcontent-%COMP%]::before { content: 'Status:'; }\n .score-cell[_ngcontent-%COMP%]::before { content: 'Score:'; }\n .duration-cell[_ngcontent-%COMP%]::before { content: 'Duration:'; }\n .cost-cell[_ngcontent-%COMP%]::before { content: 'Cost:'; }\n\n .stats-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr 1fr;\n }\n\n .stat-card[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .stat-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 16px;\n }\n\n .stat-card[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n}\n\n\n\n.tab[_ngcontent-%COMP%]:focus-visible, \n.test-run-item[_ngcontent-%COMP%]:focus-visible, \nbutton[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--suite-run-primary);\n outline-offset: 2px;\n}\n\n\n\n\n\n.analytics-loading[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 60px 20px;\n color: var(--suite-run-text-secondary);\n}\n\n.analytics-loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n color: var(--suite-run-primary);\n}\n\n\n\n\n\n.results-table-wrapper[_ngcontent-%COMP%] {\n border: 1px solid var(--suite-run-border);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.results-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.results-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] {\n background: var(--suite-run-neutral-light);\n}\n\n.results-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n padding: 12px 16px;\n text-align: left;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--suite-run-text-secondary);\n border-bottom: 1px solid var(--suite-run-border);\n}\n\n.results-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px 16px;\n border-bottom: 1px solid #f1f5f9;\n vertical-align: middle;\n}\n\n.results-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:last-child td[_ngcontent-%COMP%] {\n border-bottom: none;\n}\n\n\n\n.seq-col[_ngcontent-%COMP%] {\n width: 40px;\n min-width: 40px;\n text-align: center;\n white-space: nowrap;\n}\n\n.name-col[_ngcontent-%COMP%] {\n \n\n width: auto;\n max-width: 50%;\n}\n\n.status-col[_ngcontent-%COMP%] {\n width: 1%; \n\n white-space: nowrap;\n}\n\n.score-col[_ngcontent-%COMP%] {\n width: 1%; \n\n min-width: 120px; \n\n white-space: nowrap;\n}\n\n.duration-col[_ngcontent-%COMP%] {\n width: 1%; \n\n white-space: nowrap;\n text-align: right;\n}\n\n.cost-col[_ngcontent-%COMP%] {\n width: 1%; \n\n white-space: nowrap;\n text-align: right;\n}\n\n\n\n.result-row[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.result-row[_ngcontent-%COMP%]:hover {\n background: var(--suite-run-primary-light);\n}\n\n.result-row.row-passed[_ngcontent-%COMP%] {\n border-left: 4px solid var(--suite-run-success);\n}\n\n.result-row.row-failed[_ngcontent-%COMP%] {\n border-left: 4px solid var(--suite-run-danger);\n}\n\n.result-row.row-error[_ngcontent-%COMP%] {\n border-left: 4px solid var(--suite-run-warning);\n}\n\n.result-row.row-skipped[_ngcontent-%COMP%] {\n border-left: 4px solid var(--suite-run-neutral);\n}\n\n\n\n.test-name-wrapper[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.test-name-wrapper[_ngcontent-%COMP%] .test-name[_ngcontent-%COMP%] {\n font-weight: 500;\n color: var(--suite-run-text);\n}\n\n.test-tags[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n\n\n.score-display[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.score-bar-mini[_ngcontent-%COMP%] {\n flex: 1;\n height: 6px;\n background: var(--suite-run-neutral-light);\n border-radius: 3px;\n overflow: hidden;\n min-width: 60px;\n}\n\n.score-bar-mini[_ngcontent-%COMP%] .score-fill[_ngcontent-%COMP%] {\n height: 100%;\n border-radius: 3px;\n transition: width 0.3s ease;\n}\n\n.score-bar-mini[_ngcontent-%COMP%] .score-fill.high[_ngcontent-%COMP%] {\n background: var(--suite-run-success);\n}\n\n.score-bar-mini[_ngcontent-%COMP%] .score-fill.medium[_ngcontent-%COMP%] {\n background: var(--suite-run-warning);\n}\n\n.score-bar-mini[_ngcontent-%COMP%] .score-fill.low[_ngcontent-%COMP%] {\n background: var(--suite-run-danger);\n}\n\n.score-display[_ngcontent-%COMP%] .score-text[_ngcontent-%COMP%] {\n position: static;\n transform: none;\n font-size: 12px;\n font-weight: 600;\n color: var(--suite-run-text);\n min-width: 35px;\n text-align: right;\n}\n\n\n\n.results-table[_ngcontent-%COMP%] .status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.results-table[_ngcontent-%COMP%] .status-badge.status-passed[_ngcontent-%COMP%] {\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.results-table[_ngcontent-%COMP%] .status-badge.status-failed[_ngcontent-%COMP%] {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.results-table[_ngcontent-%COMP%] .status-badge.status-error[_ngcontent-%COMP%] {\n background: var(--suite-run-warning-light);\n color: var(--suite-run-warning);\n}\n\n.results-table[_ngcontent-%COMP%] .status-badge.status-skipped[_ngcontent-%COMP%] {\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-neutral);\n}\n\n.results-table[_ngcontent-%COMP%] .status-badge.status-pending[_ngcontent-%COMP%] {\n background: var(--suite-run-info-light);\n color: var(--suite-run-info);\n}\n\n.results-table[_ngcontent-%COMP%] .status-badge.status-running[_ngcontent-%COMP%] {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n}\n\n\n\n@media (max-width: 768px) {\n .results-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n }\n\n .results-table[_ngcontent-%COMP%] {\n min-width: 600px;\n }\n\n .results-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .results-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 12px;\n }\n\n .name-col[_ngcontent-%COMP%] {\n min-width: 150px;\n }\n}\n\n\n\n\n\n@media (prefers-contrast: high) {\n .status-badge[_ngcontent-%COMP%], \n .status-inline[_ngcontent-%COMP%] {\n border: 2px solid currentColor;\n }\n\n .test-run-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.evaluation-summary[_ngcontent-%COMP%] {\n margin-top: 20px;\n}\n\n.eval-summary-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: 16px;\n}\n\n.eval-summary-card[_ngcontent-%COMP%] {\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n overflow: hidden;\n transition: var(--suite-run-transition);\n}\n\n.eval-summary-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--suite-run-shadow);\n}\n\n.eval-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n background: var(--suite-run-neutral-light);\n border-bottom: 1px solid var(--suite-run-border);\n font-size: 13px;\n font-weight: 600;\n color: var(--suite-run-text);\n}\n\n.eval-card-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n}\n\n.eval-card-body[_ngcontent-%COMP%] {\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.eval-stat-row[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n}\n\n.eval-stat-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--suite-run-text-secondary);\n}\n\n.eval-stat-value[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--suite-run-text);\n}\n\n.eval-stat-value.correct[_ngcontent-%COMP%] {\n color: var(--suite-run-success);\n}\n\n.eval-stat-value.incorrect[_ngcontent-%COMP%] {\n color: var(--suite-run-danger);\n font-weight: 500;\n font-size: 12px;\n}\n\n.eval-stat-value.error[_ngcontent-%COMP%] {\n color: var(--suite-run-danger);\n}\n\n.eval-stat-value.timeout[_ngcontent-%COMP%] {\n color: var(--suite-run-warning);\n}\n\n.eval-card-footer[_ngcontent-%COMP%] {\n padding: 10px 16px;\n background: var(--suite-run-warning-light);\n border-top: 1px solid rgba(245, 158, 11, 0.2);\n}\n\n.pending-badge[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--suite-run-warning);\n}\n\n.pending-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n\n\n\n\n.needs-review-section[_ngcontent-%COMP%] {\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n overflow: hidden;\n}\n\n.needs-review-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14px 20px;\n background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);\n border-bottom: 1px solid rgba(245, 158, 11, 0.3);\n}\n\n.needs-review-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #92400e;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.needs-review-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.review-count[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: #92400e;\n background: rgba(255, 255, 255, 0.6);\n padding: 2px 10px;\n border-radius: 12px;\n}\n\n.needs-review-list[_ngcontent-%COMP%] {\n padding: 8px;\n}\n\n.review-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border-radius: 8px;\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.review-item[_ngcontent-%COMP%]:hover {\n background: var(--suite-run-primary-light);\n}\n\n.review-item-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.review-item.high-priority[_ngcontent-%COMP%] .review-item-icon[_ngcontent-%COMP%] {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.review-item.medium-priority[_ngcontent-%COMP%] .review-item-icon[_ngcontent-%COMP%] {\n background: var(--suite-run-warning-light);\n color: var(--suite-run-warning);\n}\n\n.review-item[_ngcontent-%COMP%]:not(.high-priority):not(.medium-priority) .review-item-icon[_ngcontent-%COMP%] {\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-neutral);\n}\n\n.review-item-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.review-item-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--suite-run-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.review-item-reason[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--suite-run-text-secondary);\n}\n\n.review-item-action[_ngcontent-%COMP%] {\n color: var(--suite-run-text-secondary);\n font-size: 12px;\n}\n\n.review-item[_ngcontent-%COMP%]:hover .review-item-action[_ngcontent-%COMP%] {\n color: var(--suite-run-primary);\n}\n\n.review-more[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n padding: 8px;\n border-top: 1px solid var(--suite-run-border);\n}\n\n\n\n@media (max-width: 768px) {\n .eval-summary-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .eval-card-header[_ngcontent-%COMP%] {\n padding: 10px 14px;\n font-size: 12px;\n }\n\n .eval-card-body[_ngcontent-%COMP%] {\n padding: 12px 14px;\n }\n\n .needs-review-header[_ngcontent-%COMP%] {\n padding: 12px 16px;\n }\n\n .needs-review-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n\n .review-item[_ngcontent-%COMP%] {\n padding: 10px 12px;\n }\n\n .review-item-icon[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n font-size: 12px;\n }\n}\n\n\n\n\n\n.feedback-col[_ngcontent-%COMP%] {\n width: 1%; \n\n white-space: nowrap;\n text-align: center;\n}\n\n.feedback-display[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.feedback-rating[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n padding: 2px 6px;\n border-radius: 4px;\n background: var(--suite-run-neutral-light);\n}\n\n.feedback-rating.low[_ngcontent-%COMP%] {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.feedback-rating.mid[_ngcontent-%COMP%] {\n background: var(--suite-run-warning-light);\n color: var(--suite-run-warning);\n}\n\n.feedback-rating.high[_ngcontent-%COMP%] {\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.feedback-correctness[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.feedback-correctness[_ngcontent-%COMP%] i.correct[_ngcontent-%COMP%] {\n color: var(--suite-run-success);\n}\n\n.feedback-correctness[_ngcontent-%COMP%] i.incorrect[_ngcontent-%COMP%] {\n color: var(--suite-run-danger);\n}\n\n.na-value.needs-review[_ngcontent-%COMP%] {\n color: var(--suite-run-warning);\n opacity: 0.7;\n}\n\n.na-value.needs-review[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}"], changeDetection: 0 }); }
557
2267
  };
558
2268
  TestSuiteRunFormComponentExtended = __decorate([
559
2269
  RegisterClass(BaseFormComponent, 'MJ: Test Suite Runs')
@@ -561,9 +2271,12 @@ TestSuiteRunFormComponentExtended = __decorate([
561
2271
  export { TestSuiteRunFormComponentExtended };
562
2272
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TestSuiteRunFormComponentExtended, [{
563
2273
  type: Component,
564
- args: [{ selector: 'mj-test-suite-run-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"test-suite-run-form\">\n <!-- Header Section -->\n <div class=\"suite-run-header\">\n <div class=\"breadcrumb\" *ngIf=\"testSuite\">\n <a href=\"javascript:void(0)\" (click)=\"openTestSuite()\">\n <i class=\"fas fa-folder\"></i> {{ testSuite.Name }}\n </a>\n <i class=\"fas fa-chevron-right\"></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=\"suite-run-icon\" [style.background-color]=\"getStatusColor()\">\n <i class=\"fas fa-layer-group\"></i>\n </div>\n <div class=\"suite-run-info\">\n <h1>Test Suite Run</h1>\n <div class=\"suite-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=\"environment\" *ngIf=\"record.Environment\">{{ record.Environment }}</span>\n <span class=\"trigger\" *ngIf=\"record.TriggerType\">{{ record.TriggerType }}</span>\n </div>\n </div>\n </div>\n <div class=\"header-actions\">\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\">Pass Rate</div>\n <div class=\"metric-value\">{{ getPassRate().toFixed(1) }}%</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-label\">Cost</div>\n <div class=\"metric-value\">{{ formatCost(record.TotalCostUSD) }}</div>\n </div>\n </div>\n\n <!-- Test Results Summary -->\n <div class=\"results-summary\">\n <div class=\"result-item passed\">\n <i class=\"fas fa-check-circle\"></i>\n <span class=\"count\">{{ record.PassedTests || 0 }}</span>\n <span class=\"label\">Passed</span>\n </div>\n <div class=\"result-item failed\">\n <i class=\"fas fa-times-circle\"></i>\n <span class=\"count\">{{ record.FailedTests || 0 }}</span>\n <span class=\"label\">Failed</span>\n </div>\n <div class=\"result-item skipped\">\n <i class=\"fas fa-forward\"></i>\n <span class=\"count\">{{ record.SkippedTests || 0 }}</span>\n <span class=\"label\">Skipped</span>\n </div>\n <div class=\"result-item error\">\n <i class=\"fas fa-exclamation-circle\"></i>\n <span class=\"count\">{{ record.ErrorTests || 0 }}</span>\n <span class=\"label\">Errors</span>\n </div>\n <div class=\"result-item total\">\n <i class=\"fas fa-list\"></i>\n <span class=\"count\">{{ record.TotalTests || 0 }}</span>\n <span class=\"label\">Total</span>\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 === 'runs'\" (click)=\"changeTab('runs')\">\n <i class=\"fas fa-list\"></i>\n <span>Test Runs</span>\n <span class=\"tab-badge\" *ngIf=\"testRunsLoaded\">{{ testRuns.length }}</span>\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'details'\" (click)=\"changeTab('details')\">\n <i class=\"fas fa-info-circle\"></i>\n <span>Details</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 === 'Completed' && getPassRate() >= 90\" [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>SUITE {{ record.Status.toUpperCase() }}</h2>\n <div class=\"result-stats\">Pass Rate: {{ getPassRate().toFixed(1) }}%</div>\n <div class=\"result-counts\">{{ record.PassedTests }} of {{ record.TotalTests }} tests passed</div>\n </div>\n </div>\n </div>\n\n <!-- Test Runs Tab -->\n <div class=\"runs-tab\" *ngIf=\"activeTab === 'runs'\">\n <div class=\"test-runs-list\" *ngIf=\"testRuns.length > 0\">\n <div class=\"test-run-item\" *ngFor=\"let run of testRuns\" (click)=\"openTestRun(run.ID)\">\n <div class=\"run-sequence\">{{ run.Sequence }}</div>\n <div class=\"run-icon\" [style.background-color]=\"run.Status === 'Passed' ? '#4caf50' : run.Status === 'Failed' ? '#f44336' : '#ff9800'\">\n <i class=\"fas\" [class.fa-check]=\"run.Status === 'Passed'\" [class.fa-times]=\"run.Status === 'Failed'\" [class.fa-exclamation]=\"run.Status === 'Error'\"></i>\n </div>\n <div class=\"run-content\">\n <div class=\"run-name\">{{ run.Test }}</div>\n <div class=\"run-meta\">\n <span class=\"status\" [style.color]=\"run.Status === 'Passed' ? '#4caf50' : run.Status === 'Failed' ? '#f44336' : '#ff9800'\">{{ run.Status }}</span>\n <span *ngIf=\"run.Score != null\">Score: {{ run.Score.toFixed(4) }}</span>\n <span *ngIf=\"run.DurationSeconds\">{{ run.DurationSeconds.toFixed(1) }}s</span>\n </div>\n </div>\n <i class=\"fas fa-chevron-right\"></i>\n </div>\n </div>\n\n <div class=\"no-data\" *ngIf=\"testRunsLoaded && testRuns.length === 0\">\n <i class=\"fas fa-inbox\"></i>\n <p>No test runs found for this suite execution</p>\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\">Run ID</div>\n <div class=\"detail-value\">{{ record.ID }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Test Suite</div>\n <div class=\"detail-value\">\n <a href=\"javascript:void(0)\" (click)=\"openTestSuite()\" *ngIf=\"testSuite\">{{ testSuite.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\">Run By</div>\n <div class=\"detail-value\">{{ record.RunByUser }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Environment</div>\n <div class=\"detail-value\">{{ record.Environment || 'N/A' }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Trigger Type</div>\n <div class=\"detail-value\">{{ record.TriggerType || 'N/A' }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Git Commit</div>\n <div class=\"detail-value\">{{ record.GitCommit || 'N/A' }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Agent Version</div>\n <div class=\"detail-value\">{{ record.AgentVersion || 'N/A' }}</div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".test-suite-run-form {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f8f9fa;\n}\n\n/* Header */\n.suite-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.suite-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.suite-run-info h1 {\n margin: 0 0 8px 0;\n font-size: 24px;\n font-weight: 600;\n color: #333;\n}\n\n.suite-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.environment,\n.trigger {\n font-size: 13px;\n color: #666;\n padding: 4px 8px;\n background: #f0f0f0;\n border-radius: 6px;\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.results-summary {\n display: flex;\n gap: 16px;\n padding-top: 16px;\n border-top: 1px solid #e0e0e0;\n}\n\n.result-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 8px;\n background: #f8f9fa;\n}\n\n.result-item i {\n font-size: 20px;\n}\n\n.result-item .count {\n font-size: 20px;\n font-weight: 700;\n}\n\n.result-item .label {\n font-size: 12px;\n font-weight: 500;\n color: #666;\n}\n\n.result-item.passed i,\n.result-item.passed .count {\n color: #4caf50;\n}\n\n.result-item.failed i,\n.result-item.failed .count {\n color: #f44336;\n}\n\n.result-item.skipped i,\n.result-item.skipped .count {\n color: #9e9e9e;\n}\n\n.result-item.error i,\n.result-item.error .count {\n color: #ff9800;\n}\n\n.result-item.total i,\n.result-item.total .count {\n color: #2196f3;\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-stats {\n font-size: 20px;\n font-weight: 600;\n color: #666;\n margin-bottom: 8px;\n}\n\n.result-counts {\n font-size: 16px;\n color: #999;\n}\n\n/* Test Runs Tab */\n.test-runs-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.test-run-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: white;\n border: 2px solid transparent;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.test-run-item:hover {\n background: #e3f2fd;\n border-color: #90caf9;\n}\n\n.run-sequence {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #f0f0f0;\n border-radius: 50%;\n font-size: 14px;\n font-weight: 700;\n color: #666;\n flex-shrink: 0;\n}\n\n.run-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n color: white;\n font-size: 18px;\n flex-shrink: 0;\n}\n\n.run-content {\n flex: 1;\n}\n\n.run-name {\n font-size: 14px;\n font-weight: 600;\n color: #333;\n margin-bottom: 4px;\n}\n\n.run-meta {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: #666;\n}\n\n.run-meta .status {\n font-weight: 700;\n}\n\n.test-run-item > i {\n color: #999;\n font-size: 14px;\n}\n\n/* Details Tab */\n.details-tab {\n background: white;\n border-radius: 12px;\n padding: 20px;\n}\n\n.details-grid {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 16px;\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/* 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 background: white;\n border-radius: 12px;\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 .results-summary {\n flex-wrap: wrap;\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"] }]
565
- }], () => [{ type: i0.ElementRef }, { type: i1.SharedService }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: i0.ChangeDetectorRef }], null); })();
566
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestSuiteRunFormComponentExtended, { className: "TestSuiteRunFormComponentExtended", filePath: "src/lib/custom/Tests/test-suite-run-form.component.ts", lineNumber: 19 }); })();
2274
+ args: [{ selector: 'mj-test-suite-run-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"test-suite-run-form\" kendoDialogContainer>\n <!-- Header Section -->\n <div class=\"suite-run-header\">\n <!-- Breadcrumb -->\n <div class=\"breadcrumb\" *ngIf=\"testSuite\">\n <a href=\"javascript:void(0)\" (click)=\"openTestSuite()\">\n <i class=\"fas fa-layer-group\"></i>\n {{ testSuite.Name }}\n </a>\n <i class=\"fas fa-chevron-right separator\"></i>\n <span class=\"current\">Run #{{ record.ID.substring(0, 8) }}</span>\n </div>\n\n <!-- Header Content -->\n <div class=\"header-content\">\n <div class=\"header-left\">\n <div class=\"suite-run-icon\" [style.background-color]=\"getStatusColor()\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon()\"></i>\n </div>\n <div class=\"suite-run-info\">\n <h1>Suite Run</h1>\n <div class=\"suite-run-meta\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass()\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon()\"></i>\n {{ record.Status }}\n </span>\n <span class=\"meta-tag environment\" *ngIf=\"record.Environment\">\n <i class=\"fas fa-server\"></i>\n {{ record.Environment }}\n </span>\n <span class=\"meta-tag trigger\" *ngIf=\"record.TriggerType\">\n <i class=\"fas fa-bolt\"></i>\n {{ record.TriggerType }}\n </span>\n </div>\n </div>\n </div>\n <div class=\"header-actions\">\n <!-- Evaluation Mode Toggle -->\n <app-evaluation-mode-toggle></app-evaluation-mode-toggle>\n <button kendoButton (click)=\"reRunSuite()\" themeColor=\"primary\" *ngIf=\"record.SuiteID\">\n <i class=\"fas fa-play\"></i> Re-run Suite\n </button>\n <button kendoButton (click)=\"refresh()\" [disabled]=\"isRefreshing\">\n <i class=\"fas\" [ngClass]=\"isRefreshing ? 'fa-sync fa-spin' : 'fa-sync'\"></i>\n {{ isRefreshing ? 'Refreshing...' : 'Refresh' }}\n </button>\n </div>\n </div>\n\n <!-- 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-value\">{{ calculateDuration() }}</div>\n <div class=\"metric-label\">Duration</div>\n </div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-icon\">\n <i class=\"fas fa-percentage\"></i>\n </div>\n <div class=\"metric-content\">\n <div class=\"metric-value\">{{ getPassRate().toFixed(1) }}%</div>\n <div class=\"metric-label\">Pass Rate</div>\n </div>\n </div>\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-value\">{{ formatCost(record.TotalCostUSD) }}</div>\n <div class=\"metric-label\">Total Cost</div>\n </div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-icon\">\n <i class=\"fas fa-calendar\"></i>\n </div>\n <div class=\"metric-content\">\n <div class=\"metric-value\">{{ getRelativeTime(record.StartedAt) }}</div>\n <div class=\"metric-label\">Started</div>\n </div>\n </div>\n </div>\n\n <!-- Results Summary -->\n <div class=\"results-summary\">\n <div class=\"result-item passed\">\n <div class=\"result-icon\">\n <i class=\"fas fa-check-circle\"></i>\n </div>\n <div class=\"result-content\">\n <span class=\"result-count\">{{ record.PassedTests || 0 }}</span>\n <span class=\"result-label\">Passed</span>\n </div>\n </div>\n <div class=\"result-item failed\">\n <div class=\"result-icon\">\n <i class=\"fas fa-times-circle\"></i>\n </div>\n <div class=\"result-content\">\n <span class=\"result-count\">{{ record.FailedTests || 0 }}</span>\n <span class=\"result-label\">Failed</span>\n </div>\n </div>\n <div class=\"result-item error\">\n <div class=\"result-icon\">\n <i class=\"fas fa-exclamation-circle\"></i>\n </div>\n <div class=\"result-content\">\n <span class=\"result-count\">{{ record.ErrorTests || 0 }}</span>\n <span class=\"result-label\">Errors</span>\n </div>\n </div>\n <div class=\"result-item skipped\">\n <div class=\"result-icon\">\n <i class=\"fas fa-forward\"></i>\n </div>\n <div class=\"result-content\">\n <span class=\"result-count\">{{ record.SkippedTests || 0 }}</span>\n <span class=\"result-label\">Skipped</span>\n </div>\n </div>\n <div class=\"result-item total\">\n <div class=\"result-icon\">\n <i class=\"fas fa-list\"></i>\n </div>\n <div class=\"result-content\">\n <span class=\"result-count\">{{ record.TotalTests || 0 }}</span>\n <span class=\"result-label\">Total</span>\n </div>\n </div>\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\"\n [class.active]=\"activeTab === 'overview'\"\n (click)=\"changeTab('overview')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'overview'\">\n <i class=\"fas fa-th-large\"></i> Overview\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'runs'\"\n (click)=\"changeTab('runs')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'runs'\">\n <i class=\"fas fa-list\"></i> Test Runs\n <span class=\"tab-badge\" *ngIf=\"testRunsLoaded\">{{ testRuns.length }}</span>\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'details'\"\n (click)=\"changeTab('details')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'details'\">\n <i class=\"fas fa-info-circle\"></i> Details\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'analytics'\"\n (click)=\"changeTab('analytics')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'analytics'\"\n title=\"Press 4\">\n <i class=\"fas fa-chart-bar\"></i> Analytics\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'execution'\"\n (click)=\"changeTab('execution')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'execution'\"\n title=\"Press 5\">\n <i class=\"fas fa-microchip\"></i>\n <span>Execution</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\"\n [class.passed]=\"record.Status === 'Completed' && getPassRate() >= 90\"\n [class.failed]=\"record.Status === 'Failed' || getPassRate() < 50\"\n [class.running]=\"record.Status === 'Running'\"\n [class.pending]=\"record.Status === 'Pending'\">\n <div class=\"result-hero-icon\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon()\"></i>\n </div>\n <div class=\"result-hero-text\">\n <h2>SUITE {{ record.Status.toUpperCase() || 'UNKNOWN' }}</h2>\n <div class=\"result-hero-stats\">\n <div class=\"stat-item\">\n <span class=\"stat-value\">{{ getPassRate().toFixed(1) }}%</span>\n <span class=\"stat-label\">Pass Rate</span>\n </div>\n <div class=\"stat-divider\"></div>\n <div class=\"stat-item\">\n <span class=\"stat-value\">{{ record.PassedTests || 0 }} / {{ record.TotalTests || 0 }}</span>\n <span class=\"stat-label\">Tests Passed</span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Evaluation Metrics Summary -->\n <div class=\"evaluation-summary\" *ngIf=\"evaluationMetrics && feedbacksLoaded\">\n <div class=\"eval-summary-grid\">\n <!-- Human Feedback Card -->\n <div class=\"eval-summary-card\" *ngIf=\"evalPreferences.showHuman\">\n <div class=\"eval-card-header\">\n <i class=\"fa-solid fa-user\"></i>\n <span>Human Feedback</span>\n </div>\n <div class=\"eval-card-body\">\n <div class=\"eval-stat-row\">\n <span class=\"eval-stat-label\">Reviewed</span>\n <span class=\"eval-stat-value\">{{ evaluationMetrics.humanReviewedCount }} / {{ evaluationMetrics.totalRuns }}</span>\n </div>\n <div class=\"eval-stat-row\" *ngIf=\"evaluationMetrics.humanReviewedCount > 0\">\n <span class=\"eval-stat-label\">Avg Rating</span>\n <span class=\"eval-stat-value\">{{ evaluationMetrics.humanAvgRating.toFixed(1) }}/10</span>\n </div>\n <div class=\"eval-stat-row\" *ngIf=\"evaluationMetrics.humanReviewedCount > 0\">\n <span class=\"eval-stat-label\">Correct</span>\n <span class=\"eval-stat-value correct\">{{ evaluationMetrics.humanCorrectCount }}</span>\n <span class=\"eval-stat-value incorrect\" *ngIf=\"evaluationMetrics.humanIncorrectCount > 0\">{{ evaluationMetrics.humanIncorrectCount }} incorrect</span>\n </div>\n </div>\n <div class=\"eval-card-footer\" *ngIf=\"evaluationMetrics.humanPendingCount > 0\">\n <span class=\"pending-badge\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ evaluationMetrics.humanPendingCount }} need review\n </span>\n </div>\n </div>\n\n <!-- Auto Score Card -->\n <div class=\"eval-summary-card\" *ngIf=\"evalPreferences.showAuto\">\n <div class=\"eval-card-header\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>Auto Evaluation</span>\n </div>\n <div class=\"eval-card-body\">\n <div class=\"eval-stat-row\">\n <span class=\"eval-stat-label\">Evaluated</span>\n <span class=\"eval-stat-value\">{{ evaluationMetrics.autoEvaluatedCount }} / {{ evaluationMetrics.totalRuns }}</span>\n </div>\n <div class=\"eval-stat-row\" *ngIf=\"evaluationMetrics.autoEvaluatedCount > 0\">\n <span class=\"eval-stat-label\">Avg Score</span>\n <span class=\"eval-stat-value\">{{ (evaluationMetrics.autoAvgScore * 100).toFixed(0) }}%</span>\n </div>\n <div class=\"eval-stat-row\" *ngIf=\"evaluationMetrics.autoEvaluatedCount > 0\">\n <span class=\"eval-stat-label\">Pass Rate</span>\n <span class=\"eval-stat-value\">{{ evaluationMetrics.autoPassRate.toFixed(0) }}%</span>\n </div>\n </div>\n </div>\n\n <!-- Execution Card -->\n <div class=\"eval-summary-card\" *ngIf=\"evalPreferences.showExecution\">\n <div class=\"eval-card-header\">\n <i class=\"fa-solid fa-circle-check\"></i>\n <span>Execution</span>\n </div>\n <div class=\"eval-card-body\">\n <div class=\"eval-stat-row\">\n <span class=\"eval-stat-label\">Completed</span>\n <span class=\"eval-stat-value\">{{ evaluationMetrics.execCompletedCount }} / {{ evaluationMetrics.totalRuns }}</span>\n </div>\n <div class=\"eval-stat-row\">\n <span class=\"eval-stat-label\">Success Rate</span>\n <span class=\"eval-stat-value\">{{ evaluationMetrics.execSuccessRate.toFixed(0) }}%</span>\n </div>\n <div class=\"eval-stat-row\" *ngIf=\"evaluationMetrics.execErrorCount > 0 || evaluationMetrics.execTimeoutCount > 0\">\n <span class=\"eval-stat-label\">Issues</span>\n <span class=\"eval-stat-value error\" *ngIf=\"evaluationMetrics.execErrorCount > 0\">{{ evaluationMetrics.execErrorCount }} errors</span>\n <span class=\"eval-stat-value timeout\" *ngIf=\"evaluationMetrics.execTimeoutCount > 0\">{{ evaluationMetrics.execTimeoutCount }} timeouts</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Needs Review Section -->\n <div class=\"needs-review-section\" *ngIf=\"evalPreferences.showHuman && needsReviewItems.length > 0 && feedbacksLoaded\">\n <div class=\"needs-review-header\">\n <h3><i class=\"fa-solid fa-user-clock\"></i> Needs Review</h3>\n <span class=\"review-count\">{{ needsReviewItems.length }} items</span>\n </div>\n <div class=\"needs-review-list\">\n <div class=\"review-item\" *ngFor=\"let item of needsReviewItems.slice(0, 5)\"\n [class.high-priority]=\"item.priority === 'high'\"\n [class.medium-priority]=\"item.priority === 'medium'\"\n (click)=\"toggleRunExpanded(item.run.id)\">\n <div class=\"review-item-icon\">\n <i class=\"fa-solid fa-exclamation-triangle\" *ngIf=\"item.priority === 'high'\"></i>\n <i class=\"fa-solid fa-circle-dot\" *ngIf=\"item.priority === 'medium'\"></i>\n <i class=\"fa-solid fa-clock\" *ngIf=\"item.priority === 'low'\"></i>\n </div>\n <div class=\"review-item-content\">\n <span class=\"review-item-name\">{{ item.run.testName }}</span>\n <span class=\"review-item-reason\">{{ item.reason }}</span>\n </div>\n <div class=\"review-item-action\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </div>\n </div>\n <div class=\"review-more\" *ngIf=\"needsReviewItems.length > 5\">\n <button kendoButton fillMode=\"flat\" (click)=\"changeTab('runs')\">\n View all {{ needsReviewItems.length }} items\n </button>\n </div>\n </div>\n </div>\n\n <!-- Progress Ring (when running) -->\n <div class=\"progress-section\" *ngIf=\"record.Status === 'Running' || record.Status === 'Pending'\">\n <div class=\"progress-info\">\n <i class=\"fas fa-circle-notch fa-spin\"></i>\n <span>Suite execution in progress...</span>\n </div>\n <div class=\"auto-refresh-notice\">\n <i class=\"fas fa-sync\"></i>\n Auto-refreshing every 5 seconds\n </div>\n </div>\n </div>\n\n <!-- Test Runs Tab -->\n <div class=\"runs-tab\" *ngIf=\"activeTab === 'runs'\">\n <!-- Toolbar -->\n <div class=\"runs-toolbar\" *ngIf=\"testRunsLoaded && testRuns.length > 0\">\n <div class=\"run-filters\">\n <button class=\"filter-btn\"\n [class.active]=\"runStatusFilter === null\"\n (click)=\"setRunStatusFilter(null)\">\n All ({{ testRuns.length }})\n </button>\n <button class=\"filter-btn passed\"\n [class.active]=\"runStatusFilter === 'Passed'\"\n (click)=\"setRunStatusFilter('Passed')\"\n *ngIf=\"getRunCountByStatus('Passed') > 0\">\n <i class=\"fas fa-check\"></i> Passed ({{ getRunCountByStatus('Passed') }})\n </button>\n <button class=\"filter-btn failed\"\n [class.active]=\"runStatusFilter === 'Failed'\"\n (click)=\"setRunStatusFilter('Failed')\"\n *ngIf=\"getRunCountByStatus('Failed') > 0\">\n <i class=\"fas fa-times\"></i> Failed ({{ getRunCountByStatus('Failed') }})\n </button>\n <button class=\"filter-btn error\"\n [class.active]=\"runStatusFilter === 'Error'\"\n (click)=\"setRunStatusFilter('Error')\"\n *ngIf=\"getRunCountByStatus('Error') > 0\">\n <i class=\"fas fa-exclamation\"></i> Error ({{ getRunCountByStatus('Error') }})\n </button>\n </div>\n <div class=\"runs-actions\">\n <button kendoButton (click)=\"exportToCSV()\">\n <i class=\"fas fa-download\"></i> Export CSV\n </button>\n </div>\n </div>\n\n <!-- Loading State -->\n <div class=\"loading-state\" *ngIf=\"loadingTestRuns\">\n <div class=\"skeleton-list\">\n <div class=\"skeleton-card\" *ngFor=\"let i of [1,2,3,4,5]\">\n <div class=\"skeleton-sequence\"></div>\n <div class=\"skeleton-icon\"></div>\n <div class=\"skeleton-content\">\n <div class=\"skeleton-line wide\"></div>\n <div class=\"skeleton-line narrow\"></div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Test Runs List -->\n <div class=\"test-runs-list\" *ngIf=\"!loadingTestRuns && testRuns.length > 0\">\n <div class=\"test-run-card\" *ngFor=\"let run of getFilteredTestRuns()\">\n <div class=\"test-run-item\" (click)=\"toggleRunExpanded(run.ID)\">\n <div class=\"run-sequence\">{{ run.Sequence || '-' }}</div>\n <div class=\"run-icon\" [style.background-color]=\"getRunStatusColor(run.Status)\">\n <i class=\"fas\" [ngClass]=\"getRunStatusIcon(run.Status)\"></i>\n </div>\n <div class=\"run-content\">\n <div class=\"run-header-row\">\n <div class=\"run-name\">{{ run.Test }}</div>\n <!-- Evaluation Badge -->\n <app-evaluation-badge\n [executionStatus]=\"run.Status\"\n [originalStatus]=\"run.Status\"\n [autoScore]=\"run.Score\"\n [humanRating]=\"getFeedbackRating(run.ID) || null\"\n [humanIsCorrect]=\"getHumanIsCorrect(run.ID)\"\n [hasHumanFeedback]=\"hasFeedback(run.ID)\"\n [preferences]=\"evalPreferences\"\n [mode]=\"'compact'\">\n </app-evaluation-badge>\n </div>\n <div class=\"run-meta\">\n <span class=\"run-duration\" *ngIf=\"run.DurationSeconds\">\n <i class=\"fas fa-clock\"></i> {{ run.DurationSeconds.toFixed(1) }}s\n </span>\n <span class=\"run-cost\" *ngIf=\"run.CostUSD\">\n <i class=\"fas fa-dollar-sign\"></i> {{ run.CostUSD.toFixed(6) }}\n </span>\n <mj-entity-link-pill\n *ngIf=\"run.TargetLogEntityID && run.TargetLogID\"\n [entityName]=\"run.TargetLogEntity\"\n [recordId]=\"run.TargetLogID\">\n </mj-entity-link-pill>\n </div>\n <div class=\"run-tags\" *ngIf=\"getRunTags(run).length > 0\">\n <span class=\"tag-chip\" *ngFor=\"let tag of getRunTags(run)\">{{ tag }}</span>\n </div>\n </div>\n <div class=\"run-expand\">\n <i class=\"fas\" [class.fa-chevron-down]=\"expandedRunId !== run.ID\" [class.fa-chevron-up]=\"expandedRunId === run.ID\"></i>\n </div>\n </div>\n\n <!-- Expanded Inline Feedback -->\n <div class=\"inline-feedback\" *ngIf=\"expandedRunId === run.ID\">\n <div class=\"feedback-divider\"></div>\n\n <div class=\"feedback-section\">\n <div class=\"feedback-label\">Quick Feedback</div>\n\n <div class=\"inline-rating\">\n <div class=\"rating-numbers\">\n <button *ngFor=\"let num of [1,2,3,4,5,6,7,8,9,10]\"\n type=\"button\"\n class=\"rating-btn\"\n [class.selected]=\"num === inlineRating\"\n [class.hover]=\"num === inlineHoverRating\"\n [class.low]=\"num <= 3\"\n [class.mid]=\"num >= 4 && num <= 6\"\n [class.high]=\"num >= 7\"\n (click)=\"setInlineRating(num); $event.stopPropagation()\"\n (mouseenter)=\"inlineHoverRating = num\"\n (mouseleave)=\"inlineHoverRating = 0\">\n {{ num }}\n </button>\n </div>\n <div class=\"rating-info\" *ngIf=\"inlineRating > 0\">\n <span class=\"rating-value\">{{ inlineRating }}/10</span>\n <span class=\"rating-label-text\">{{ getInlineRatingLabel() }}</span>\n </div>\n </div>\n\n <div class=\"correctness-row\">\n <span class=\"correctness-label\">Was it correct?</span>\n <div class=\"correctness-options\">\n <label class=\"radio-opt\" (click)=\"$event.stopPropagation()\">\n <input type=\"radio\" name=\"correct-{{run.ID}}\" [value]=\"true\" [(ngModel)]=\"inlineIsCorrect\">\n <span>Yes</span>\n </label>\n <label class=\"radio-opt\" (click)=\"$event.stopPropagation()\">\n <input type=\"radio\" name=\"correct-{{run.ID}}\" [value]=\"false\" [(ngModel)]=\"inlineIsCorrect\">\n <span>No</span>\n </label>\n <label class=\"radio-opt\" (click)=\"$event.stopPropagation()\">\n <input type=\"radio\" name=\"correct-{{run.ID}}\" [value]=\"null\" [(ngModel)]=\"inlineIsCorrect\">\n <span>Not Sure</span>\n </label>\n </div>\n </div>\n\n <div class=\"comments-row\" (click)=\"$event.stopPropagation()\">\n <textarea\n class=\"feedback-textarea\"\n [(ngModel)]=\"inlineComments\"\n placeholder=\"Add comments or corrections...\"\n rows=\"3\"></textarea>\n </div>\n\n <div class=\"feedback-actions\" (click)=\"$event.stopPropagation()\">\n <button kendoButton (click)=\"openTestRun(run.ID)\">\n <i class=\"fas fa-external-link-alt\"></i> View Full Details\n </button>\n <button kendoButton\n themeColor=\"primary\"\n (click)=\"saveInlineFeedback()\"\n [disabled]=\"!canSubmitInlineFeedback() || savingInlineFeedback\">\n <i class=\"fas\" [ngClass]=\"savingInlineFeedback ? 'fa-spinner fa-spin' : 'fa-save'\"></i>\n {{ savingInlineFeedback ? 'Saving...' : (hasFeedback(run.ID) ? 'Update' : 'Save') }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Empty State -->\n <div class=\"empty-state\" *ngIf=\"testRunsLoaded && !loadingTestRuns && testRuns.length === 0\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-inbox\"></i>\n </div>\n <h4>No Test Runs Found</h4>\n <p>No test runs have been recorded for this suite execution.</p>\n </div>\n\n <!-- Filtered Empty -->\n <div class=\"empty-state\" *ngIf=\"testRunsLoaded && !loadingTestRuns && testRuns.length > 0 && getFilteredTestRuns().length === 0\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-filter\"></i>\n </div>\n <h4>No Matching Runs</h4>\n <p>No test runs match the current filter.</p>\n <button kendoButton (click)=\"setRunStatusFilter(null)\">Clear Filter</button>\n </div>\n </div>\n\n <!-- Details Tab -->\n <div class=\"details-tab\" *ngIf=\"activeTab === 'details'\">\n <div class=\"details-card\">\n <h3><i class=\"fas fa-info-circle\"></i> Run Information</h3>\n <div class=\"details-grid\">\n <div class=\"detail-item\">\n <div class=\"detail-label\">Run ID</div>\n <div class=\"detail-value monospace\">{{ record.ID }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Test Suite</div>\n <div class=\"detail-value\">\n <a href=\"javascript:void(0)\" (click)=\"openTestSuite()\" *ngIf=\"testSuite\">{{ testSuite.Name }}</a>\n <span *ngIf=\"!testSuite\">Loading...</span>\n </div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Status</div>\n <div class=\"detail-value\">\n <span class=\"status-inline\" [ngClass]=\"getStatusClass()\">{{ record.Status }}</span>\n </div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Run By</div>\n <div class=\"detail-value\">{{ record.RunByUser || '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\">Environment</div>\n <div class=\"detail-value\">{{ record.Environment || 'N/A' }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Trigger Type</div>\n <div class=\"detail-value\">{{ record.TriggerType || 'N/A' }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Git Commit</div>\n <div class=\"detail-value monospace\">{{ record.GitCommit || 'N/A' }}</div>\n </div>\n <div class=\"detail-item\">\n <div class=\"detail-label\">Agent Version</div>\n <div class=\"detail-value\">{{ record.AgentVersion || 'N/A' }}</div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Analytics Tab -->\n <div class=\"analytics-tab\" *ngIf=\"activeTab === 'analytics'\">\n <!-- Loading State -->\n <div class=\"analytics-loading\" *ngIf=\"loadingTestRuns\">\n <i class=\"fas fa-spinner fa-spin\"></i>\n <span>Loading test results...</span>\n </div>\n\n <!-- Summary Statistics - Moved to top for better overview -->\n <div class=\"analytics-section\" *ngIf=\"!loadingTestRuns && testRuns.length > 0\">\n <h3><i class=\"fas fa-chart-pie\"></i> Summary Statistics</h3>\n <div class=\"stats-grid\">\n <div class=\"stat-card\">\n <div class=\"stat-icon passed\"><i class=\"fas fa-check-circle\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ getPassedCount() }}</div>\n <div class=\"stat-label\">Passed</div>\n <div class=\"stat-percent\">{{ getPassedPercent().toFixed(1) }}%</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon failed\"><i class=\"fas fa-times-circle\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ getFailedCount() }}</div>\n <div class=\"stat-label\">Failed</div>\n <div class=\"stat-percent\">{{ getFailedPercent().toFixed(1) }}%</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon score\"><i class=\"fas fa-star\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ (getAverageScore() * 100).toFixed(1) }}%</div>\n <div class=\"stat-label\">Avg Score</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon duration\"><i class=\"fas fa-clock\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ getAverageDuration().toFixed(1) }}s</div>\n <div class=\"stat-label\">Avg Duration</div>\n </div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-icon cost\"><i class=\"fas fa-dollar-sign\"></i></div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">${{ getTotalCost().toFixed(4) }}</div>\n <div class=\"stat-label\">Total Cost</div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Test Results Table -->\n <div class=\"analytics-section\" *ngIf=\"!loadingTestRuns && testRuns.length > 0\">\n <div class=\"analytics-header\">\n <h3><i class=\"fas fa-table\"></i> Test Results</h3>\n <div class=\"analytics-legend\">\n <span class=\"legend-item passed\"><i class=\"fas fa-check-circle\"></i> Passed</span>\n <span class=\"legend-item failed\"><i class=\"fas fa-times-circle\"></i> Failed</span>\n <span class=\"legend-item error\"><i class=\"fas fa-exclamation-circle\"></i> Error</span>\n <span class=\"legend-item skipped\"><i class=\"fas fa-forward\"></i> Skipped</span>\n </div>\n </div>\n\n <!-- Results Table -->\n <div class=\"results-table-wrapper\">\n <table class=\"results-table\">\n <thead>\n <tr>\n <th class=\"seq-col\">#</th>\n <th class=\"name-col\">Test Name</th>\n <th class=\"status-col\" *ngIf=\"evalPreferences.showExecution\">Status</th>\n <th class=\"score-col\" *ngIf=\"evalPreferences.showAuto\">Auto Score</th>\n <th class=\"feedback-col\" *ngIf=\"evalPreferences.showHuman\">Human Score</th>\n <th class=\"duration-col\">Duration</th>\n <th class=\"cost-col\">Cost</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let run of testRuns; let i = index\"\n class=\"result-row\"\n [class.row-passed]=\"run.Status === 'Passed'\"\n [class.row-failed]=\"run.Status === 'Failed'\"\n [class.row-error]=\"run.Status === 'Error'\"\n [class.row-skipped]=\"run.Status === 'Skipped'\"\n (click)=\"openTestRun(run.ID)\">\n <td class=\"seq-col\">{{ i + 1 }}</td>\n <td class=\"name-col\">\n <div class=\"test-name-wrapper\">\n <span class=\"test-name\">{{ run.Test || 'Unknown Test' }}</span>\n <div class=\"test-tags\" *ngIf=\"getRunTags(run).length > 0\">\n <span class=\"tag-mini\" *ngFor=\"let tag of getRunTags(run).slice(0, 2)\">{{ tag }}</span>\n </div>\n </div>\n </td>\n <td class=\"status-col\" *ngIf=\"evalPreferences.showExecution\">\n <span class=\"status-badge\" [ngClass]=\"'status-' + run.Status.toLowerCase()\">\n <i class=\"fas\"\n [class.fa-check-circle]=\"run.Status === 'Passed'\"\n [class.fa-times-circle]=\"run.Status === 'Failed'\"\n [class.fa-exclamation-circle]=\"run.Status === 'Error'\"\n [class.fa-forward]=\"run.Status === 'Skipped'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-spin]=\"run.Status === 'Running'\"></i>\n {{ run.Status }}\n </span>\n </td>\n <td class=\"score-col\" *ngIf=\"evalPreferences.showAuto\">\n <div class=\"score-display\" *ngIf=\"run.Score != null\">\n <div class=\"score-bar-mini\">\n <div class=\"score-fill\"\n [style.width.%]=\"run.Score * 100\"\n [class.high]=\"run.Score >= 0.8\"\n [class.medium]=\"run.Score >= 0.5 && run.Score < 0.8\"\n [class.low]=\"run.Score < 0.5\"></div>\n </div>\n <span class=\"score-text\">{{ (run.Score * 100).toFixed(0) }}%</span>\n </div>\n <span class=\"na-value\" *ngIf=\"run.Score == null\">\u2014</span>\n </td>\n <td class=\"feedback-col\" *ngIf=\"evalPreferences.showHuman\">\n <div class=\"feedback-display\" *ngIf=\"hasFeedback(run.ID)\">\n <span class=\"feedback-rating\" [class.low]=\"getFeedbackRating(run.ID) <= 3\" [class.mid]=\"getFeedbackRating(run.ID) >= 4 && getFeedbackRating(run.ID) <= 6\" [class.high]=\"getFeedbackRating(run.ID) >= 7\">\n {{ getFeedbackRating(run.ID) }}/10\n </span>\n <span class=\"feedback-correctness\" *ngIf=\"getHumanIsCorrect(run.ID) !== null\">\n <i class=\"fas\" [class.fa-check]=\"getHumanIsCorrect(run.ID) === true\" [class.fa-times]=\"getHumanIsCorrect(run.ID) === false\" [class.correct]=\"getHumanIsCorrect(run.ID) === true\" [class.incorrect]=\"getHumanIsCorrect(run.ID) === false\"></i>\n </span>\n </div>\n <span class=\"na-value needs-review\" *ngIf=\"!hasFeedback(run.ID)\">\n <i class=\"fas fa-user-clock\"></i>\n </span>\n </td>\n <td class=\"duration-col\">\n <span *ngIf=\"run.DurationSeconds\">{{ run.DurationSeconds.toFixed(1) }}s</span>\n <span class=\"na-value\" *ngIf=\"!run.DurationSeconds\">\u2014</span>\n </td>\n <td class=\"cost-col\">\n <span *ngIf=\"run.CostUSD\">${{ run.CostUSD.toFixed(4) }}</span>\n <span class=\"na-value\" *ngIf=\"!run.CostUSD\">\u2014</span>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Empty State -->\n <div class=\"empty-state\" *ngIf=\"!loadingTestRuns && testRunsLoaded && testRuns.length === 0\">\n <div class=\"empty-icon\">\n <i class=\"fas fa-chart-bar\"></i>\n </div>\n <h4>No Test Results Yet</h4>\n <p>Test runs will appear here once the suite execution completes.</p>\n </div>\n </div>\n\n <!-- Execution Tab -->\n <div class=\"execution-tab\" *ngIf=\"activeTab === 'execution'\">\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 </div>\n\n <!-- Keyboard Shortcuts Toggle Button -->\n <button class=\"shortcuts-toggle\" (click)=\"toggleShortcuts()\" [title]=\"showShortcuts ? 'Hide keyboard shortcuts' : 'Show keyboard shortcuts'\">\n <i class=\"fas fa-keyboard\"></i>\n </button>\n\n <!-- Keyboard Shortcuts Hint (Desktop Only) -->\n <div class=\"keyboard-shortcuts\" *ngIf=\"showShortcuts\">\n <div class=\"shortcuts-header\">\n <i class=\"fas fa-keyboard\"></i>\n Shortcuts\n <button class=\"shortcuts-close\" (click)=\"toggleShortcuts()\" title=\"Hide shortcuts\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n <div class=\"shortcut-list\">\n <div class=\"shortcut-item\">\n <span>Refresh</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>R</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Re-run Suite</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>Shift</kbd><kbd>R</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Switch Tabs</span>\n <span class=\"shortcut-keys\"><kbd>1</kbd>-<kbd>5</kbd></span>\n </div>\n </div>\n </div>\n</div>\n", styles: ["/* ===================================\n Test Suite Run Form - Premium UX\n World-class responsive design\n =================================== */\n\n/* CSS Custom Properties */\n:host {\n --suite-run-primary: #3b82f6;\n --suite-run-primary-light: #eff6ff;\n --suite-run-success: #10b981;\n --suite-run-success-light: #ecfdf5;\n --suite-run-danger: #ef4444;\n --suite-run-danger-light: #fef2f2;\n --suite-run-warning: #f59e0b;\n --suite-run-warning-light: #fffbeb;\n --suite-run-info: #8b5cf6;\n --suite-run-info-light: #f5f3ff;\n --suite-run-neutral: #6b7280;\n --suite-run-neutral-light: #f9fafb;\n --suite-run-bg: #f8fafc;\n --suite-run-card: #ffffff;\n --suite-run-border: #e2e8f0;\n --suite-run-text: #1e293b;\n --suite-run-text-secondary: #64748b;\n --suite-run-radius: 12px;\n --suite-run-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);\n --suite-run-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n --suite-run-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* Base Container */\n.test-suite-run-form {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--suite-run-bg);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n}\n\n/* ===================================\n Header Section\n =================================== */\n.suite-run-header {\n background: var(--suite-run-card);\n border-bottom: 1px solid var(--suite-run-border);\n padding: 20px 24px;\n}\n\n/* Breadcrumb */\n.breadcrumb {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: var(--suite-run-text-secondary);\n margin-bottom: 16px;\n}\n\n.breadcrumb a {\n color: var(--suite-run-primary);\n text-decoration: none;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: var(--suite-run-transition);\n}\n\n.breadcrumb a:hover {\n color: #2563eb;\n}\n\n.breadcrumb .separator {\n font-size: 10px;\n color: #cbd5e1;\n}\n\n.breadcrumb .current {\n color: var(--suite-run-text);\n font-weight: 500;\n}\n\n/* Header Content */\n.header-content {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.header-left {\n display: flex;\n gap: 16px;\n align-items: flex-start;\n}\n\n.suite-run-icon {\n width: 56px;\n height: 56px;\n border-radius: var(--suite-run-radius);\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(--suite-run-shadow);\n}\n\n.suite-run-info h1 {\n margin: 0 0 8px 0;\n font-size: 24px;\n font-weight: 700;\n color: var(--suite-run-text);\n letter-spacing: -0.025em;\n}\n\n.suite-run-meta {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.status-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 text-transform: uppercase;\n letter-spacing: 0.025em;\n}\n\n.status-badge.status-completed {\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.status-badge.status-failed {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.status-badge.status-running {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n}\n\n.status-badge.status-pending {\n background: var(--suite-run-info-light);\n color: var(--suite-run-info);\n}\n\n.status-badge.status-cancelled {\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-neutral);\n}\n\n.meta-tag {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--suite-run-neutral-light);\n border-radius: 6px;\n font-size: 12px;\n color: var(--suite-run-text-secondary);\n}\n\n.meta-tag i {\n font-size: 10px;\n opacity: 0.7;\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n/* ===================================\n Metrics Bar\n =================================== */\n.metrics-bar {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 12px;\n margin-bottom: 20px;\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(--suite-run-border);\n border-radius: 10px;\n padding: 14px;\n transition: var(--suite-run-transition);\n}\n\n.metric-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--suite-run-shadow);\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(--suite-run-card);\n border-radius: 10px;\n color: var(--suite-run-primary);\n font-size: 16px;\n box-shadow: var(--suite-run-shadow);\n}\n\n.metric-content {\n flex: 1;\n min-width: 0;\n}\n\n.metric-value {\n font-size: 18px;\n font-weight: 700;\n color: var(--suite-run-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.metric-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--suite-run-text-secondary);\n margin-top: 2px;\n}\n\n/* ===================================\n Results Summary\n =================================== */\n.results-summary {\n display: flex;\n gap: 12px;\n padding-top: 20px;\n border-top: 1px solid var(--suite-run-border);\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.result-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: 10px;\n flex-shrink: 0;\n transition: var(--suite-run-transition);\n}\n\n.result-item:hover {\n transform: translateY(-2px);\n box-shadow: var(--suite-run-shadow);\n}\n\n.result-icon {\n font-size: 24px;\n}\n\n.result-content {\n display: flex;\n flex-direction: column;\n}\n\n.result-count {\n font-size: 20px;\n font-weight: 700;\n line-height: 1.2;\n}\n\n.result-label {\n font-size: 11px;\n font-weight: 500;\n color: var(--suite-run-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.result-item.passed .result-icon,\n.result-item.passed .result-count {\n color: var(--suite-run-success);\n}\n\n.result-item.failed .result-icon,\n.result-item.failed .result-count {\n color: var(--suite-run-danger);\n}\n\n.result-item.error .result-icon,\n.result-item.error .result-count {\n color: var(--suite-run-warning);\n}\n\n.result-item.skipped .result-icon,\n.result-item.skipped .result-count {\n color: var(--suite-run-neutral);\n}\n\n.result-item.total .result-icon,\n.result-item.total .result-count {\n color: var(--suite-run-primary);\n}\n\n/* ===================================\n Tabs\n =================================== */\n.tabs-container {\n background: var(--suite-run-card);\n border-bottom: 1px solid var(--suite-run-border);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n\n.tabs {\n display: flex;\n padding: 0 24px;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: 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: 16px 20px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: var(--suite-run-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--suite-run-transition);\n white-space: nowrap;\n position: relative;\n}\n\n.tab:hover {\n color: var(--suite-run-primary);\n background: var(--suite-run-primary-light);\n}\n\n.tab.active {\n color: var(--suite-run-primary);\n border-bottom-color: var(--suite-run-primary);\n font-weight: 600;\n}\n\n.tab i {\n font-size: 15px;\n}\n\n.tab-badge {\n background: var(--suite-run-border);\n color: var(--suite-run-text-secondary);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active .tab-badge {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n}\n\n.tab-shortcut {\n display: none;\n width: 18px;\n height: 18px;\n background: var(--suite-run-neutral-light);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n color: var(--suite-run-text-secondary);\n align-items: center;\n justify-content: center;\n margin-left: 4px;\n}\n\n/* ===================================\n Tab Content\n =================================== */\n.tab-content {\n flex: 1;\n overflow-y: auto;\n padding: 24px;\n}\n\n/* ===================================\n Overview Tab\n =================================== */\n.overview-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n max-width: 800px;\n margin: 0 auto;\n width: 100%;\n}\n\n.result-hero {\n background: var(--suite-run-card);\n border-radius: var(--suite-run-radius);\n padding: 48px 32px;\n text-align: center;\n border: 2px solid var(--suite-run-border);\n transition: var(--suite-run-transition);\n}\n\n.result-hero.passed {\n background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%);\n border-color: var(--suite-run-success);\n}\n\n.result-hero.failed {\n background: linear-gradient(135deg, #fef2f2 0%, #fecaca 100%);\n border-color: var(--suite-run-danger);\n}\n\n.result-hero.running {\n background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);\n border-color: var(--suite-run-primary);\n}\n\n.result-hero.pending {\n background: linear-gradient(135deg, #f5f3ff 0%, #ede9fe 100%);\n border-color: var(--suite-run-info);\n}\n\n.result-hero-icon {\n font-size: 72px;\n margin-bottom: 20px;\n}\n\n.result-hero.passed .result-hero-icon {\n color: var(--suite-run-success);\n}\n\n.result-hero.failed .result-hero-icon {\n color: var(--suite-run-danger);\n}\n\n.result-hero.running .result-hero-icon {\n color: var(--suite-run-primary);\n}\n\n.result-hero.pending .result-hero-icon {\n color: var(--suite-run-info);\n}\n\n.result-hero-text h2 {\n margin: 0 0 16px 0;\n font-size: 32px;\n font-weight: 800;\n color: var(--suite-run-text);\n letter-spacing: -0.025em;\n}\n\n.result-hero-stats {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 32px;\n}\n\n.stat-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.stat-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--suite-run-text);\n}\n\n.stat-label {\n font-size: 12px;\n font-weight: 500;\n color: var(--suite-run-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.stat-divider {\n width: 1px;\n height: 40px;\n background: var(--suite-run-border);\n}\n\n/* Progress Section */\n.progress-section {\n background: var(--suite-run-primary-light);\n border: 1px solid rgba(59, 130, 246, 0.2);\n border-radius: var(--suite-run-radius);\n padding: 20px;\n text-align: center;\n}\n\n.progress-info {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 500;\n color: var(--suite-run-primary);\n margin-bottom: 8px;\n}\n\n.progress-info i {\n font-size: 20px;\n}\n\n.auto-refresh-notice {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n font-size: 12px;\n color: var(--suite-run-text-secondary);\n}\n\n/* ===================================\n Test Runs Tab\n =================================== */\n.runs-tab {\n max-width: 900px;\n margin: 0 auto;\n width: 100%;\n}\n\n/* Loading Skeleton */\n.loading-state {\n animation: fadeIn 0.3s ease;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\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: 12px;\n padding: 16px;\n background: var(--suite-run-card);\n border-radius: var(--suite-run-radius);\n border: 1px solid var(--suite-run-border);\n}\n\n.skeleton-sequence {\n width: 32px;\n height: 32px;\n background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n border-radius: 50%;\n}\n\n.skeleton-icon {\n width: 40px;\n height: 40px;\n background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n border-radius: 8px;\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 background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n border-radius: 4px;\n}\n\n.skeleton-line.wide {\n width: 70%;\n}\n\n.skeleton-line.narrow {\n width: 40%;\n}\n\n@keyframes shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n/* Test Runs List */\n.test-runs-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.test-run-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.test-run-item:hover {\n background: var(--suite-run-primary-light);\n border-color: #93c5fd;\n transform: translateX(4px);\n}\n\n.test-run-item:active {\n transform: translateX(2px);\n}\n\n.run-sequence {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--suite-run-neutral-light);\n border-radius: 50%;\n font-size: 13px;\n font-weight: 700;\n color: var(--suite-run-text-secondary);\n flex-shrink: 0;\n}\n\n.run-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n color: white;\n font-size: 16px;\n flex-shrink: 0;\n box-shadow: var(--suite-run-shadow);\n}\n\n.run-content {\n flex: 1;\n min-width: 0;\n}\n\n.run-name {\n font-size: 14px;\n font-weight: 600;\n color: var(--suite-run-text);\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.run-meta {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: var(--suite-run-text-secondary);\n flex-wrap: wrap;\n}\n\n.run-status {\n font-weight: 700;\n}\n\n.run-score,\n.run-duration {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.run-score i,\n.run-duration i {\n font-size: 10px;\n opacity: 0.7;\n}\n\n.test-run-item > i {\n color: #cbd5e1;\n font-size: 14px;\n transition: var(--suite-run-transition);\n}\n\n.test-run-item:hover > i {\n color: var(--suite-run-primary);\n transform: translateX(4px);\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n text-align: center;\n background: var(--suite-run-card);\n border-radius: var(--suite-run-radius);\n border: 2px dashed var(--suite-run-border);\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(--suite-run-neutral-light);\n border-radius: 50%;\n margin-bottom: 20px;\n}\n\n.empty-icon i {\n font-size: 32px;\n color: #cbd5e1;\n}\n\n.empty-state h4 {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--suite-run-text);\n}\n\n.empty-state p {\n margin: 0;\n font-size: 14px;\n color: var(--suite-run-text-secondary);\n max-width: 300px;\n}\n\n/* ===================================\n Details Tab\n =================================== */\n.details-tab {\n max-width: 900px;\n margin: 0 auto;\n width: 100%;\n}\n\n.details-card {\n background: var(--suite-run-card);\n border-radius: var(--suite-run-radius);\n padding: 24px;\n box-shadow: var(--suite-run-shadow);\n}\n\n.details-card h3 {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0 0 20px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--suite-run-text);\n padding-bottom: 12px;\n border-bottom: 1px solid var(--suite-run-border);\n}\n\n.details-card h3 i {\n color: var(--suite-run-primary);\n}\n\n.details-grid {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 20px;\n}\n\n.detail-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--suite-run-text-secondary);\n}\n\n.detail-value {\n font-size: 14px;\n color: var(--suite-run-text);\n word-wrap: break-word;\n}\n\n.detail-value.monospace {\n font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;\n font-size: 12px;\n background: var(--suite-run-neutral-light);\n padding: 6px 10px;\n border-radius: 6px;\n}\n\n.detail-value a {\n color: var(--suite-run-primary);\n text-decoration: none;\n font-weight: 500;\n transition: var(--suite-run-transition);\n}\n\n.detail-value a:hover {\n color: #2563eb;\n text-decoration: underline;\n}\n\n.status-inline {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.status-inline.status-completed {\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.status-inline.status-failed {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.status-inline.status-running {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n}\n\n.status-inline.status-pending {\n background: var(--suite-run-info-light);\n color: var(--suite-run-info);\n}\n\n.status-inline.status-cancelled {\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-neutral);\n}\n\n/* ===================================\n Keyboard Shortcuts\n =================================== */\n/* Toggle button - visible when shortcuts are hidden */\n.shortcuts-toggle {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n box-shadow: var(--suite-run-shadow);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--suite-run-text-secondary);\n font-size: 14px;\n z-index: 99;\n transition: var(--suite-run-transition);\n opacity: 0.7;\n}\n\n.shortcuts-toggle:hover {\n opacity: 1;\n transform: scale(1.1);\n color: var(--suite-run-primary);\n border-color: var(--suite-run-primary);\n}\n\n.keyboard-shortcuts {\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n padding: 12px 16px;\n box-shadow: var(--suite-run-shadow-lg);\n font-size: 12px;\n z-index: 100;\n opacity: 0.9;\n transition: var(--suite-run-transition);\n}\n\n.keyboard-shortcuts:hover {\n opacity: 1;\n}\n\n.shortcuts-header {\n display: flex;\n align-items: center;\n gap: 6px;\n font-weight: 600;\n color: var(--suite-run-text);\n margin-bottom: 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--suite-run-border);\n}\n\n.shortcuts-header i {\n color: var(--suite-run-primary);\n}\n\n.shortcuts-close {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--suite-run-text-muted);\n font-size: 12px;\n padding: 2px 4px;\n border-radius: 4px;\n transition: var(--suite-run-transition);\n}\n\n.shortcuts-close:hover {\n color: var(--suite-run-text);\n background: var(--suite-run-border);\n}\n\n.shortcut-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.shortcut-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n}\n\n.shortcut-item span:first-child {\n color: var(--suite-run-text-secondary);\n}\n\n.shortcut-keys {\n display: flex;\n gap: 4px;\n}\n\nkbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n background: linear-gradient(180deg, #f8fafc 0%, #e2e8f0 100%);\n border: 1px solid #cbd5e1;\n border-radius: 4px;\n font-family: inherit;\n font-size: 10px;\n font-weight: 600;\n color: var(--suite-run-text);\n box-shadow: 0 1px 0 #94a3b8;\n}\n\n/* ===================================\n Responsive Design - Tablet\n =================================== */\n@media (max-width: 1024px) {\n .suite-run-header {\n padding: 16px 20px;\n }\n\n .metrics-bar {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .result-hero-stats {\n flex-direction: column;\n gap: 16px;\n }\n\n .stat-divider {\n display: none;\n }\n\n .details-grid {\n grid-template-columns: 1fr;\n }\n\n .tab-shortcut {\n display: none;\n }\n}\n\n/* ===================================\n Responsive Design - Mobile\n =================================== */\n@media (max-width: 768px) {\n .suite-run-header {\n padding: 16px;\n }\n\n .header-content {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-left {\n width: 100%;\n }\n\n .suite-run-icon {\n width: 48px;\n height: 48px;\n font-size: 20px;\n }\n\n .suite-run-info h1 {\n font-size: 20px;\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: 8px;\n }\n\n .metric-card {\n padding: 12px;\n flex-direction: column;\n text-align: center;\n gap: 8px;\n }\n\n .metric-icon {\n width: 36px;\n height: 36px;\n }\n\n .metric-value {\n font-size: 16px;\n }\n\n .results-summary {\n gap: 8px;\n padding-top: 16px;\n flex-wrap: nowrap;\n overflow-x: auto;\n padding-bottom: 8px;\n margin-bottom: -8px;\n }\n\n .result-item {\n padding: 10px 12px;\n min-width: 90px;\n }\n\n .result-icon {\n font-size: 20px;\n }\n\n .result-count {\n font-size: 18px;\n }\n\n .tabs {\n padding: 0 16px;\n }\n\n .tab {\n padding: 14px 16px;\n font-size: 13px;\n }\n\n .tab-content {\n padding: 16px;\n }\n\n .result-hero {\n padding: 32px 20px;\n }\n\n .result-hero-icon {\n font-size: 56px;\n }\n\n .result-hero-text h2 {\n font-size: 24px;\n }\n\n .stat-value {\n font-size: 20px;\n }\n\n .test-run-item {\n padding: 14px;\n }\n\n .run-sequence {\n width: 28px;\n height: 28px;\n font-size: 12px;\n }\n\n .run-icon {\n width: 36px;\n height: 36px;\n font-size: 14px;\n }\n\n .run-name {\n font-size: 13px;\n }\n\n .run-meta {\n gap: 10px;\n font-size: 11px;\n }\n\n .empty-state {\n padding: 40px 16px;\n }\n\n .empty-icon {\n width: 64px;\n height: 64px;\n }\n\n .empty-icon i {\n font-size: 28px;\n }\n\n .details-card {\n padding: 16px;\n }\n\n .details-grid {\n gap: 16px;\n }\n\n .keyboard-shortcuts, .shortcuts-toggle {\n display: none;\n }\n}\n\n/* ===================================\n Responsive Design - Small Mobile\n =================================== */\n@media (max-width: 480px) {\n .suite-run-header {\n padding: 12px;\n }\n\n .breadcrumb {\n font-size: 12px;\n margin-bottom: 12px;\n }\n\n .suite-run-icon {\n width: 44px;\n height: 44px;\n font-size: 18px;\n }\n\n .suite-run-info h1 {\n font-size: 18px;\n }\n\n .suite-run-meta {\n gap: 8px;\n }\n\n .status-badge {\n padding: 4px 10px;\n font-size: 11px;\n }\n\n .meta-tag {\n font-size: 11px;\n padding: 3px 8px;\n }\n\n .metrics-bar {\n grid-template-columns: 1fr 1fr;\n }\n\n .metric-card {\n padding: 10px;\n gap: 6px;\n }\n\n .metric-icon {\n width: 32px;\n height: 32px;\n font-size: 14px;\n }\n\n .metric-value {\n font-size: 14px;\n }\n\n .metric-label {\n font-size: 9px;\n }\n\n .result-item {\n padding: 8px 10px;\n min-width: 80px;\n gap: 8px;\n }\n\n .result-icon {\n font-size: 18px;\n }\n\n .result-count {\n font-size: 16px;\n }\n\n .result-label {\n font-size: 9px;\n }\n\n .tabs {\n padding: 0 12px;\n }\n\n .tab {\n padding: 12px 14px;\n gap: 6px;\n }\n\n .tab i {\n font-size: 14px;\n }\n\n .tab-content {\n padding: 12px;\n }\n\n .result-hero {\n padding: 24px 16px;\n }\n\n .result-hero-icon {\n font-size: 48px;\n margin-bottom: 16px;\n }\n\n .result-hero-text h2 {\n font-size: 20px;\n margin-bottom: 12px;\n }\n\n .stat-value {\n font-size: 18px;\n }\n\n .stat-label {\n font-size: 10px;\n }\n\n .progress-section {\n padding: 16px;\n }\n\n .progress-info {\n font-size: 14px;\n }\n\n .test-run-item {\n padding: 12px;\n gap: 10px;\n }\n\n .run-sequence {\n width: 24px;\n height: 24px;\n font-size: 11px;\n }\n\n .run-icon {\n width: 32px;\n height: 32px;\n font-size: 12px;\n border-radius: 8px;\n }\n\n .run-name {\n font-size: 12px;\n margin-bottom: 3px;\n }\n\n .run-meta {\n gap: 8px;\n font-size: 10px;\n }\n\n .empty-state {\n padding: 32px 12px;\n }\n\n .empty-state h4 {\n font-size: 16px;\n }\n\n .empty-state p {\n font-size: 13px;\n }\n\n .details-card {\n padding: 14px;\n }\n\n .details-card h3 {\n font-size: 14px;\n margin-bottom: 16px;\n }\n\n .detail-label {\n font-size: 10px;\n }\n\n .detail-value {\n font-size: 13px;\n }\n}\n\n/* ===================================\n Touch Device Optimizations\n =================================== */\n@media (hover: none) and (pointer: coarse) {\n .test-run-item {\n min-height: 64px;\n }\n\n .test-run-item:hover {\n transform: none;\n background: var(--suite-run-card);\n border-color: var(--suite-run-border);\n }\n\n .test-run-item:active {\n background: var(--suite-run-primary-light);\n border-color: #93c5fd;\n }\n\n .tab:hover {\n background: transparent;\n color: var(--suite-run-text-secondary);\n }\n\n .tab:active {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n }\n\n .metric-card:hover {\n transform: none;\n box-shadow: none;\n }\n\n .result-item:hover {\n transform: none;\n box-shadow: none;\n }\n\n .keyboard-shortcuts {\n display: none;\n }\n}\n\n/* ===================================\n Print Styles\n =================================== */\n@media print {\n .suite-run-header {\n background: white;\n box-shadow: none;\n border-bottom: 2px solid #000;\n }\n\n .tabs-container,\n .header-actions,\n .keyboard-shortcuts {\n display: none;\n }\n\n .tab-content {\n padding: 20px 0;\n }\n\n .result-hero,\n .test-run-item,\n .details-card {\n box-shadow: none;\n border: 1px solid #ccc;\n }\n}\n\n/* ===================================\n Dark Mode Support (Future)\n =================================== */\n@media (prefers-color-scheme: dark) {\n /* Ready for dark mode implementation */\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(59, 130, 246, 0.04) 0%, rgba(59, 130, 246, 0.08) 100%);\n border: 1px solid rgba(59, 130, 246, 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(--suite-run-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: var(--suite-run-primary-light);\n color: var(--suite-run-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(--suite-run-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(--suite-run-border);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--suite-run-text-secondary);\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.tags-bar-edit:hover {\n border-color: var(--suite-run-primary);\n color: var(--suite-run-primary);\n background: var(--suite-run-primary-light);\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(--suite-run-card);\n border: 1px solid var(--suite-run-primary);\n border-radius: 10px;\n overflow: hidden;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 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: var(--suite-run-primary-light);\n border-bottom: 1px solid rgba(59, 130, 246, 0.2);\n}\n\n.tags-editor-title {\n font-size: 13px;\n font-weight: 600;\n color: var(--suite-run-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(--suite-run-card);\n border: 1px solid var(--suite-run-primary);\n color: var(--suite-run-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(--suite-run-primary);\n cursor: pointer;\n border-radius: 50%;\n font-size: 9px;\n opacity: 0.6;\n transition: var(--suite-run-transition);\n}\n\n.tag-remove-btn:hover {\n opacity: 1;\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.tags-empty-hint {\n font-size: 12px;\n color: var(--suite-run-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(--suite-run-border);\n border-radius: 8px;\n font-size: 13px;\n background: var(--suite-run-neutral-light);\n}\n\n.tag-text-input:focus {\n outline: none;\n border-color: var(--suite-run-primary);\n background: var(--suite-run-card);\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.tag-text-input::placeholder {\n color: var(--suite-run-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(--suite-run-neutral-light);\n border-top: 1px solid var(--suite-run-border);\n}\n\n/* ===================================\n Runs Toolbar\n =================================== */\n.runs-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding: 12px 16px;\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.run-filters {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.filter-btn {\n padding: 6px 14px;\n border: 1px solid var(--suite-run-border);\n background: var(--suite-run-card);\n border-radius: 20px;\n font-size: 12px;\n font-weight: 500;\n color: var(--suite-run-text-secondary);\n cursor: pointer;\n transition: var(--suite-run-transition);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.filter-btn:hover {\n border-color: var(--suite-run-primary);\n color: var(--suite-run-primary);\n}\n\n.filter-btn.active {\n background: var(--suite-run-primary);\n border-color: var(--suite-run-primary);\n color: white;\n}\n\n.filter-btn.passed:hover,\n.filter-btn.passed.active {\n background: var(--suite-run-success);\n border-color: var(--suite-run-success);\n color: white;\n}\n\n.filter-btn.failed:hover,\n.filter-btn.failed.active {\n background: var(--suite-run-danger);\n border-color: var(--suite-run-danger);\n color: white;\n}\n\n.filter-btn.error:hover,\n.filter-btn.error.active {\n background: var(--suite-run-warning);\n border-color: var(--suite-run-warning);\n color: white;\n}\n\n.runs-actions {\n display: flex;\n gap: 8px;\n}\n\n/* ===================================\n Test Run Card (Expandable)\n =================================== */\n.test-run-card {\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n overflow: hidden;\n transition: var(--suite-run-transition);\n margin-bottom: 10px;\n}\n\n.test-run-card:hover {\n box-shadow: var(--suite-run-shadow);\n}\n\n.test-run-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.test-run-item:hover {\n background: var(--suite-run-primary-light);\n}\n\n.run-header-row {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 4px;\n}\n\n.run-feedback-indicator {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 2px 8px;\n background: var(--suite-run-info-light);\n color: var(--suite-run-info);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.run-feedback-indicator i {\n font-size: 10px;\n}\n\n.run-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-top: 6px;\n}\n\n.tag-mini {\n display: inline-flex;\n padding: 2px 8px;\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-text-secondary);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 500;\n}\n\n.tag-chip {\n display: inline-flex;\n align-items: center;\n padding: 3px 10px;\n background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);\n border: 1px solid #bfdbfe;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: #1d4ed8;\n}\n\n.run-expand {\n color: var(--suite-run-text-secondary);\n transition: var(--suite-run-transition);\n}\n\n.test-run-item:hover .run-expand {\n color: var(--suite-run-primary);\n}\n\n.run-cost {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.run-cost i {\n font-size: 10px;\n opacity: 0.7;\n}\n\n/* ===================================\n Inline Feedback\n =================================== */\n.inline-feedback {\n padding: 0 16px 16px;\n animation: slideDown 0.2s ease-out;\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.feedback-divider {\n height: 1px;\n background: var(--suite-run-border);\n margin-bottom: 16px;\n}\n\n.feedback-section {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.feedback-label {\n font-size: 14px;\n font-weight: 600;\n color: var(--suite-run-text);\n}\n\n.inline-rating {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.rating-numbers {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.rating-btn {\n width: 36px;\n height: 36px;\n border: 2px solid var(--suite-run-border);\n border-radius: 8px;\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-text-secondary);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.rating-btn:hover,\n.rating-btn.hover {\n transform: scale(1.1);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}\n\n.rating-btn.low:hover,\n.rating-btn.low.hover {\n border-color: var(--suite-run-danger);\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.rating-btn.mid:hover,\n.rating-btn.mid.hover {\n border-color: var(--suite-run-warning);\n background: var(--suite-run-warning-light);\n color: var(--suite-run-warning);\n}\n\n.rating-btn.high:hover,\n.rating-btn.high.hover {\n border-color: var(--suite-run-success);\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.rating-btn.selected {\n transform: scale(1.1);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}\n\n.rating-btn.selected.low {\n border-color: var(--suite-run-danger);\n background: var(--suite-run-danger);\n color: white;\n}\n\n.rating-btn.selected.mid {\n border-color: var(--suite-run-warning);\n background: var(--suite-run-warning);\n color: white;\n}\n\n.rating-btn.selected.high {\n border-color: var(--suite-run-success);\n background: var(--suite-run-success);\n color: white;\n}\n\n.rating-info {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 14px;\n background: var(--suite-run-neutral-light);\n border-radius: 8px;\n}\n\n.rating-value {\n font-size: 18px;\n font-weight: 700;\n color: var(--suite-run-text);\n}\n\n.rating-label-text {\n font-size: 13px;\n color: var(--suite-run-text-secondary);\n}\n\n.correctness-row {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.correctness-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--suite-run-text);\n}\n\n.correctness-options {\n display: flex;\n gap: 16px;\n}\n\n.radio-opt {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n font-size: 13px;\n color: var(--suite-run-text-secondary);\n}\n\n.radio-opt input[type=\"radio\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.comments-row {\n width: 100%;\n}\n\n.feedback-textarea {\n width: 100%;\n padding: 12px;\n border: 1px solid var(--suite-run-border);\n border-radius: 8px;\n font-size: 14px;\n font-family: inherit;\n resize: vertical;\n min-height: 80px;\n}\n\n.feedback-textarea:focus {\n outline: none;\n border-color: var(--suite-run-primary);\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);\n}\n\n.feedback-actions {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n padding-top: 8px;\n}\n\n/* ===================================\n Mobile Responsive Updates\n =================================== */\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 .runs-toolbar {\n flex-direction: column;\n align-items: stretch;\n }\n\n .run-filters {\n justify-content: center;\n }\n\n .runs-actions {\n justify-content: center;\n }\n\n .rating-numbers {\n justify-content: center;\n }\n\n .rating-btn {\n width: 32px;\n height: 32px;\n font-size: 12px;\n }\n\n .correctness-row {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n\n .feedback-actions {\n flex-direction: column;\n }\n\n .feedback-actions button {\n width: 100%;\n }\n}\n\n/* ===================================\n Animations\n =================================== */\n@keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n\n.result-hero.running .result-hero-icon {\n animation: pulse 2s ease-in-out infinite;\n}\n\n/* Tab content fade in */\n.overview-tab,\n.runs-tab,\n.details-tab,\n.analytics-tab {\n animation: fadeIn 0.3s ease;\n}\n\n/* ===================================\n Analytics Tab\n =================================== */\n.analytics-tab {\n max-width: 1200px;\n margin: 0 auto;\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.analytics-section {\n background: var(--suite-run-card);\n border-radius: var(--suite-run-radius);\n padding: 24px;\n box-shadow: var(--suite-run-shadow);\n}\n\n.analytics-section h3 {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0 0 20px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--suite-run-text);\n padding-bottom: 12px;\n border-bottom: 1px solid var(--suite-run-border);\n}\n\n.analytics-section h3 i {\n color: var(--suite-run-primary);\n}\n\n.analytics-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-bottom: 20px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--suite-run-border);\n}\n\n.analytics-header h3 {\n margin: 0;\n padding: 0;\n border: none;\n}\n\n.analytics-legend {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n}\n\n.legend-item.passed {\n color: var(--suite-run-success);\n}\n\n.legend-item.failed {\n color: var(--suite-run-danger);\n}\n\n.legend-item.error {\n color: var(--suite-run-warning);\n}\n\n.legend-item.skipped {\n color: var(--suite-run-neutral);\n}\n\n/* Performance Matrix */\n.performance-matrix {\n border: 1px solid var(--suite-run-border);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.matrix-row {\n display: grid;\n grid-template-columns: 2fr 120px 150px 100px 100px;\n border-bottom: 1px solid var(--suite-run-border);\n transition: var(--suite-run-transition);\n cursor: pointer;\n}\n\n.matrix-row:last-child {\n border-bottom: none;\n}\n\n.matrix-row:hover:not(.matrix-header-row) {\n background: var(--suite-run-primary-light);\n}\n\n.matrix-row.passed {\n border-left: 4px solid var(--suite-run-success);\n}\n\n.matrix-row.failed {\n border-left: 4px solid var(--suite-run-danger);\n}\n\n.matrix-row.error {\n border-left: 4px solid var(--suite-run-warning);\n}\n\n.matrix-row.skipped {\n border-left: 4px solid var(--suite-run-neutral);\n}\n\n.matrix-header-row {\n background: var(--suite-run-neutral-light);\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--suite-run-text-secondary);\n cursor: default;\n}\n\n.matrix-cell {\n padding: 12px 16px;\n display: flex;\n align-items: center;\n}\n\n.test-name-cell {\n gap: 12px;\n}\n\n.test-sequence {\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--suite-run-neutral-light);\n border-radius: 50%;\n font-size: 11px;\n font-weight: 600;\n color: var(--suite-run-text-secondary);\n flex-shrink: 0;\n}\n\n.test-name {\n font-weight: 500;\n color: var(--suite-run-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.status-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.status-indicator.status-passed {\n color: var(--suite-run-success);\n}\n\n.status-indicator.status-failed {\n color: var(--suite-run-danger);\n}\n\n.status-indicator.status-error {\n color: var(--suite-run-warning);\n}\n\n.status-indicator.status-skipped {\n color: var(--suite-run-neutral);\n}\n\n.status-indicator.status-pending {\n color: var(--suite-run-info);\n}\n\n.status-indicator.status-running {\n color: var(--suite-run-primary);\n}\n\n.score-bar {\n position: relative;\n width: 100%;\n height: 20px;\n background: var(--suite-run-neutral-light);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.score-fill {\n height: 100%;\n border-radius: 10px;\n transition: width 0.3s ease;\n}\n\n.score-fill.high {\n background: linear-gradient(90deg, var(--suite-run-success) 0%, #34d399 100%);\n}\n\n.score-fill.medium {\n background: linear-gradient(90deg, var(--suite-run-warning) 0%, #fbbf24 100%);\n}\n\n.score-fill.low {\n background: linear-gradient(90deg, var(--suite-run-danger) 0%, #f87171 100%);\n}\n\n.score-text {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 11px;\n font-weight: 600;\n color: var(--suite-run-text);\n}\n\n.na-value {\n color: var(--suite-run-text-secondary);\n opacity: 0.6;\n}\n\n/* Summary Statistics Grid */\n.stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n}\n\n.stat-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px;\n background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);\n border: 1px solid var(--suite-run-border);\n border-radius: 12px;\n transition: var(--suite-run-transition);\n}\n\n.stat-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--suite-run-shadow);\n}\n\n.stat-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 12px;\n font-size: 20px;\n}\n\n.stat-icon.passed {\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.stat-icon.failed {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.stat-icon.score {\n background: var(--suite-run-warning-light);\n color: var(--suite-run-warning);\n}\n\n.stat-icon.duration {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n}\n\n.stat-icon.cost {\n background: var(--suite-run-info-light);\n color: var(--suite-run-info);\n}\n\n.stat-content {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.stat-card .stat-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--suite-run-text);\n}\n\n.stat-card .stat-label {\n font-size: 12px;\n font-weight: 500;\n color: var(--suite-run-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.stat-percent {\n font-size: 12px;\n color: var(--suite-run-text-secondary);\n}\n\n/* Responsive Analytics */\n@media (max-width: 768px) {\n .analytics-header {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .matrix-row {\n grid-template-columns: 1fr;\n gap: 8px;\n padding: 12px;\n }\n\n .matrix-header-row {\n display: none;\n }\n\n .matrix-cell {\n padding: 4px 0;\n }\n\n .test-name-cell::before,\n .status-cell::before,\n .score-cell::before,\n .duration-cell::before,\n .cost-cell::before {\n font-size: 10px;\n font-weight: 600;\n color: var(--suite-run-text-secondary);\n text-transform: uppercase;\n margin-right: 8px;\n min-width: 80px;\n }\n\n .status-cell::before { content: 'Status:'; }\n .score-cell::before { content: 'Score:'; }\n .duration-cell::before { content: 'Duration:'; }\n .cost-cell::before { content: 'Cost:'; }\n\n .stats-grid {\n grid-template-columns: 1fr 1fr;\n }\n\n .stat-card {\n padding: 16px;\n }\n\n .stat-icon {\n width: 40px;\n height: 40px;\n font-size: 16px;\n }\n\n .stat-card .stat-value {\n font-size: 20px;\n }\n}\n\n/* Focus States for Accessibility */\n.tab:focus-visible,\n.test-run-item:focus-visible,\nbutton:focus-visible {\n outline: 2px solid var(--suite-run-primary);\n outline-offset: 2px;\n}\n\n/* ===================================\n Analytics Loading State\n =================================== */\n.analytics-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 60px 20px;\n color: var(--suite-run-text-secondary);\n}\n\n.analytics-loading i {\n font-size: 32px;\n color: var(--suite-run-primary);\n}\n\n/* ===================================\n Results Table\n =================================== */\n.results-table-wrapper {\n border: 1px solid var(--suite-run-border);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.results-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.results-table thead {\n background: var(--suite-run-neutral-light);\n}\n\n.results-table th {\n padding: 12px 16px;\n text-align: left;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--suite-run-text-secondary);\n border-bottom: 1px solid var(--suite-run-border);\n}\n\n.results-table td {\n padding: 12px 16px;\n border-bottom: 1px solid #f1f5f9;\n vertical-align: middle;\n}\n\n.results-table tbody tr:last-child td {\n border-bottom: none;\n}\n\n/* Column widths - Fixed columns fit content, name column takes remainder (max 50%) */\n.seq-col {\n width: 40px;\n min-width: 40px;\n text-align: center;\n white-space: nowrap;\n}\n\n.name-col {\n /* Take remaining space, but cap at 50% of table width */\n width: auto;\n max-width: 50%;\n}\n\n.status-col {\n width: 1%; /* Shrink to fit content */\n white-space: nowrap;\n}\n\n.score-col {\n width: 1%; /* Shrink to fit content */\n min-width: 120px; /* Score bar needs some minimum width */\n white-space: nowrap;\n}\n\n.duration-col {\n width: 1%; /* Shrink to fit content */\n white-space: nowrap;\n text-align: right;\n}\n\n.cost-col {\n width: 1%; /* Shrink to fit content */\n white-space: nowrap;\n text-align: right;\n}\n\n/* Result Row */\n.result-row {\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.result-row:hover {\n background: var(--suite-run-primary-light);\n}\n\n.result-row.row-passed {\n border-left: 4px solid var(--suite-run-success);\n}\n\n.result-row.row-failed {\n border-left: 4px solid var(--suite-run-danger);\n}\n\n.result-row.row-error {\n border-left: 4px solid var(--suite-run-warning);\n}\n\n.result-row.row-skipped {\n border-left: 4px solid var(--suite-run-neutral);\n}\n\n/* Test Name Wrapper */\n.test-name-wrapper {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.test-name-wrapper .test-name {\n font-weight: 500;\n color: var(--suite-run-text);\n}\n\n.test-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n/* Score Display */\n.score-display {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.score-bar-mini {\n flex: 1;\n height: 6px;\n background: var(--suite-run-neutral-light);\n border-radius: 3px;\n overflow: hidden;\n min-width: 60px;\n}\n\n.score-bar-mini .score-fill {\n height: 100%;\n border-radius: 3px;\n transition: width 0.3s ease;\n}\n\n.score-bar-mini .score-fill.high {\n background: var(--suite-run-success);\n}\n\n.score-bar-mini .score-fill.medium {\n background: var(--suite-run-warning);\n}\n\n.score-bar-mini .score-fill.low {\n background: var(--suite-run-danger);\n}\n\n.score-display .score-text {\n position: static;\n transform: none;\n font-size: 12px;\n font-weight: 600;\n color: var(--suite-run-text);\n min-width: 35px;\n text-align: right;\n}\n\n/* Status Badge in Table */\n.results-table .status-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.results-table .status-badge.status-passed {\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.results-table .status-badge.status-failed {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.results-table .status-badge.status-error {\n background: var(--suite-run-warning-light);\n color: var(--suite-run-warning);\n}\n\n.results-table .status-badge.status-skipped {\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-neutral);\n}\n\n.results-table .status-badge.status-pending {\n background: var(--suite-run-info-light);\n color: var(--suite-run-info);\n}\n\n.results-table .status-badge.status-running {\n background: var(--suite-run-primary-light);\n color: var(--suite-run-primary);\n}\n\n/* Responsive Results Table */\n@media (max-width: 768px) {\n .results-table-wrapper {\n overflow-x: auto;\n }\n\n .results-table {\n min-width: 600px;\n }\n\n .results-table th,\n .results-table td {\n padding: 10px 12px;\n }\n\n .name-col {\n min-width: 150px;\n }\n}\n\n/* ===================================\n High Contrast Mode\n =================================== */\n@media (prefers-contrast: high) {\n .status-badge,\n .status-inline {\n border: 2px solid currentColor;\n }\n\n .test-run-item {\n border-width: 2px;\n }\n\n .tab.active {\n border-bottom-width: 4px;\n }\n}\n\n/* ===================================\n Evaluation Summary\n =================================== */\n.evaluation-summary {\n margin-top: 20px;\n}\n\n.eval-summary-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: 16px;\n}\n\n.eval-summary-card {\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n overflow: hidden;\n transition: var(--suite-run-transition);\n}\n\n.eval-summary-card:hover {\n box-shadow: var(--suite-run-shadow);\n}\n\n.eval-card-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n background: var(--suite-run-neutral-light);\n border-bottom: 1px solid var(--suite-run-border);\n font-size: 13px;\n font-weight: 600;\n color: var(--suite-run-text);\n}\n\n.eval-card-header i {\n color: var(--suite-run-primary);\n}\n\n.eval-card-body {\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.eval-stat-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n}\n\n.eval-stat-label {\n font-size: 12px;\n color: var(--suite-run-text-secondary);\n}\n\n.eval-stat-value {\n font-size: 14px;\n font-weight: 600;\n color: var(--suite-run-text);\n}\n\n.eval-stat-value.correct {\n color: var(--suite-run-success);\n}\n\n.eval-stat-value.incorrect {\n color: var(--suite-run-danger);\n font-weight: 500;\n font-size: 12px;\n}\n\n.eval-stat-value.error {\n color: var(--suite-run-danger);\n}\n\n.eval-stat-value.timeout {\n color: var(--suite-run-warning);\n}\n\n.eval-card-footer {\n padding: 10px 16px;\n background: var(--suite-run-warning-light);\n border-top: 1px solid rgba(245, 158, 11, 0.2);\n}\n\n.pending-badge {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n color: var(--suite-run-warning);\n}\n\n.pending-badge i {\n font-size: 11px;\n}\n\n/* ===================================\n Needs Review Section\n =================================== */\n.needs-review-section {\n background: var(--suite-run-card);\n border: 1px solid var(--suite-run-border);\n border-radius: var(--suite-run-radius);\n overflow: hidden;\n}\n\n.needs-review-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14px 20px;\n background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);\n border-bottom: 1px solid rgba(245, 158, 11, 0.3);\n}\n\n.needs-review-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #92400e;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.needs-review-header h3 i {\n font-size: 16px;\n}\n\n.review-count {\n font-size: 12px;\n font-weight: 500;\n color: #92400e;\n background: rgba(255, 255, 255, 0.6);\n padding: 2px 10px;\n border-radius: 12px;\n}\n\n.needs-review-list {\n padding: 8px;\n}\n\n.review-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border-radius: 8px;\n cursor: pointer;\n transition: var(--suite-run-transition);\n}\n\n.review-item:hover {\n background: var(--suite-run-primary-light);\n}\n\n.review-item-icon {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.review-item.high-priority .review-item-icon {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.review-item.medium-priority .review-item-icon {\n background: var(--suite-run-warning-light);\n color: var(--suite-run-warning);\n}\n\n.review-item:not(.high-priority):not(.medium-priority) .review-item-icon {\n background: var(--suite-run-neutral-light);\n color: var(--suite-run-neutral);\n}\n\n.review-item-content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.review-item-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--suite-run-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.review-item-reason {\n font-size: 11px;\n color: var(--suite-run-text-secondary);\n}\n\n.review-item-action {\n color: var(--suite-run-text-secondary);\n font-size: 12px;\n}\n\n.review-item:hover .review-item-action {\n color: var(--suite-run-primary);\n}\n\n.review-more {\n display: flex;\n justify-content: center;\n padding: 8px;\n border-top: 1px solid var(--suite-run-border);\n}\n\n/* Mobile Responsive for Evaluation */\n@media (max-width: 768px) {\n .eval-summary-grid {\n grid-template-columns: 1fr;\n }\n\n .eval-card-header {\n padding: 10px 14px;\n font-size: 12px;\n }\n\n .eval-card-body {\n padding: 12px 14px;\n }\n\n .needs-review-header {\n padding: 12px 16px;\n }\n\n .needs-review-header h3 {\n font-size: 13px;\n }\n\n .review-item {\n padding: 10px 12px;\n }\n\n .review-item-icon {\n width: 28px;\n height: 28px;\n font-size: 12px;\n }\n}\n\n/* ===================================\n Feedback Column in Analytics Table\n =================================== */\n.feedback-col {\n width: 1%; /* Shrink to fit content */\n white-space: nowrap;\n text-align: center;\n}\n\n.feedback-display {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.feedback-rating {\n font-size: 13px;\n font-weight: 600;\n padding: 2px 6px;\n border-radius: 4px;\n background: var(--suite-run-neutral-light);\n}\n\n.feedback-rating.low {\n background: var(--suite-run-danger-light);\n color: var(--suite-run-danger);\n}\n\n.feedback-rating.mid {\n background: var(--suite-run-warning-light);\n color: var(--suite-run-warning);\n}\n\n.feedback-rating.high {\n background: var(--suite-run-success-light);\n color: var(--suite-run-success);\n}\n\n.feedback-correctness i {\n font-size: 12px;\n}\n\n.feedback-correctness i.correct {\n color: var(--suite-run-success);\n}\n\n.feedback-correctness i.incorrect {\n color: var(--suite-run-danger);\n}\n\n.na-value.needs-review {\n color: var(--suite-run-warning);\n opacity: 0.7;\n}\n\n.na-value.needs-review i {\n font-size: 14px;\n}\n"] }]
2275
+ }], () => [{ type: i0.ElementRef }, { type: i1.SharedService }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: i0.ChangeDetectorRef }, { type: i3.TestingDialogService }, { type: i3.EvaluationPreferencesService }], { handleKeyboardShortcut: [{
2276
+ type: HostListener,
2277
+ args: ['document:keydown', ['$event']]
2278
+ }] }); })();
2279
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestSuiteRunFormComponentExtended, { className: "TestSuiteRunFormComponentExtended", filePath: "src/lib/custom/Tests/test-suite-run-form.component.ts", lineNumber: 34 }); })();
567
2280
  export function LoadTestSuiteRunFormComponentExtended() {
568
2281
  // Prevents tree-shaking
569
2282
  }