@memberjunction/ng-dashboards 5.4.1 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AI/components/agents/agent-configuration.component.js +4 -4
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +5 -4
- package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +3 -3
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +8 -7
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +3 -3
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +4 -4
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.d.ts.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.js +3 -2
- package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
- package/dist/APIKeys/api-keys-resource.component.js +2 -2
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.d.ts.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.js +4 -3
- package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +3 -3
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js +3 -2
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +2 -2
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +2 -2
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.js +3 -2
- package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.js +3 -2
- package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js +2 -2
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts +6 -0
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +19 -6
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts +4 -0
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +13 -4
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.d.ts +2 -0
- package/dist/Credentials/components/credentials-categories-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +13 -9
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +11 -11
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +3 -3
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.d.ts +2 -0
- package/dist/Credentials/components/credentials-types-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +13 -9
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js +11 -11
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js +4 -3
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.js +4 -3
- package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +6 -6
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.js +4 -1
- package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.d.ts.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.js +9 -8
- package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +2 -2
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Home/home-application.js +2 -2
- package/dist/Home/home-application.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +3 -3
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.d.ts +1 -0
- package/dist/Lists/components/lists-categories-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +17 -14
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +2 -2
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.d.ts +1 -0
- package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +15 -12
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.d.ts.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.js +3 -2
- package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-test-tool-dialog.component.d.ts.map +1 -1
- package/dist/MCP/components/mcp-test-tool-dialog.component.js +8 -7
- package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +22 -22
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.d.ts +2 -0
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +14 -10
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js +2 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts +1 -0
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +22 -18
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-review.component.d.ts +1 -0
- package/dist/Testing/components/testing-review.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-review.component.js +14 -10
- package/dist/Testing/components/testing-review.component.js.map +1 -1
- package/dist/VersionHistory/components/diff-resource.component.js +6 -6
- package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/graph-resource.component.js +2 -2
- package/dist/VersionHistory/components/graph-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.js +3 -3
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/package.json +38 -38
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing-explorer.component.js","sourceRoot":"","sources":["../../../src/Testing/components/testing-explorer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n OnInit,\n OnDestroy,\n ChangeDetectorRef,\n ChangeDetectionStrategy,\n ViewContainerRef\n} from '@angular/core';\nimport { Subject, BehaviorSubject, combineLatest } from 'rxjs';\nimport { takeUntil, debounceTime } from 'rxjs/operators';\nimport { RunView, CompositeKey, Metadata } from '@memberjunction/core';\nimport { MJTestEntity, MJTestSuiteEntity, MJTestSuiteTestEntity, MJTestTypeEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport { TestingDialogService } from '@memberjunction/ng-testing';\nimport { TestEngineBase } from '@memberjunction/testing-engine-base';\nimport { TestingInstrumentationService } from '../services/testing-instrumentation.service';\n\n// ---------------------------------------------------------------------------\n// Interfaces\n// ---------------------------------------------------------------------------\n\ninterface SuiteCardData {\n ID: string;\n Name: string;\n Description: string;\n Status: string;\n TestCount: number;\n PassRate: number;\n AvgScore: number;\n AvgDuration: number; // ms\n LastRunDate: Date | null;\n Tags: string[];\n Tests: SuiteTestItem[]; // first 4-5 for preview\n TotalTestsInSuite: number;\n}\n\ninterface SuiteTestItem {\n TestID: string;\n TestName: string;\n LastStatus: string;\n LastScore: number;\n}\n\ninterface TestCardData {\n ID: string;\n Name: string;\n Description: string;\n Status: string;\n TypeName: string;\n SuiteName: string;\n LastRunStatus: string;\n LastScore: number;\n TotalRuns: number;\n PassRate: number;\n EstDuration: number; // seconds\n EstCost: number;\n LastRunDate: Date | null;\n Tags: string[];\n UpdatedAt: Date;\n}\n\ninterface SidebarSelection {\n Type: 'all' | 'standalone' | 'suite' | 'testType';\n ID: string | null;\n}\n\ninterface SuiteTreeNode {\n ID: string;\n Name: string;\n ParentID: string | null;\n TestCount: number;\n Children: SuiteTreeNode[];\n Expanded: boolean;\n}\n\ntype DisplayMode = 'all' | 'suites' | 'tests';\ntype ViewMode = 'card' | 'list';\ntype SortField = 'name' | 'updated' | 'status';\ntype SortDirection = 'asc' | 'desc';\n\n/** Simple result type for test run stats queries */\ninterface TestRunStatRow {\n ID: string;\n TestID: string;\n Status: string;\n Score: number;\n CostUSD: number;\n StartedAt: string | Date;\n CompletedAt: string | Date | null;\n}\n\n@Component({\n standalone: false,\n selector: 'app-testing-explorer',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n @if (IsLoading) {\n <div class=\"explorer-loading\">\n <mj-loading text=\"Loading test explorer...\"></mj-loading>\n </div>\n } @else {\n <div class=\"explorer-layout\">\n <!-- Left Sidebar -->\n <aside class=\"sidebar\" [class.collapsed]=\"IsSidebarCollapsed\">\n <div class=\"sidebar-header\">\n <h3>Explorer</h3>\n <button class=\"sidebar-toggle\" (click)=\"ToggleSidebar()\">\n <i class=\"fa-solid\" [class.fa-chevron-left]=\"!IsSidebarCollapsed\" [class.fa-chevron-right]=\"IsSidebarCollapsed\"></i>\n </button>\n </div>\n\n @if (!IsSidebarCollapsed) {\n <div class=\"sidebar-content\">\n <!-- Browse Section -->\n <div class=\"sidebar-section\">\n <div class=\"sidebar-section-title\">Browse</div>\n <div\n class=\"sidebar-item\"\n [class.active]=\"SelectedSidebar.Type === 'all'\"\n (click)=\"SelectSidebarItem({ Type: 'all', ID: null })\"\n >\n <i class=\"fa-solid fa-layer-group\"></i>\n <span>All Items</span>\n <span class=\"sidebar-count\">{{ TotalItemCount }}</span>\n </div>\n <div\n class=\"sidebar-item\"\n [class.active]=\"SelectedSidebar.Type === 'standalone'\"\n (click)=\"SelectSidebarItem({ Type: 'standalone', ID: null })\"\n >\n <i class=\"fa-solid fa-vial\"></i>\n <span>Standalone Tests</span>\n <span class=\"sidebar-count\">{{ StandaloneTestCount }}</span>\n </div>\n </div>\n\n <!-- Test Suites Section -->\n <div class=\"sidebar-section\">\n <div class=\"sidebar-section-title\">Test Suites</div>\n @for (node of FilteredSuiteTree; track node.ID) {\n <ng-container\n *ngTemplateOutlet=\"suiteTreeTpl; context: { node: node, depth: 0 }\"\n ></ng-container>\n }\n @if (FilteredSuiteTree.length === 0) {\n <div class=\"sidebar-empty\">No suites found</div>\n }\n </div>\n\n <!-- Test Types Section -->\n <div class=\"sidebar-section\">\n <div class=\"sidebar-section-title\">Test Types</div>\n @for (tt of FilteredTestTypes; track tt.ID) {\n <div\n class=\"sidebar-item\"\n [class.active]=\"SelectedSidebar.Type === 'testType' && SelectedSidebar.ID === tt.ID\"\n (click)=\"SelectSidebarItem({ Type: 'testType', ID: tt.ID })\"\n >\n <i class=\"fa-solid fa-tag\"></i>\n <span>{{ tt.Name }}</span>\n <span class=\"sidebar-count\">{{ GetTestCountForType(tt.ID) }}</span>\n </div>\n }\n </div>\n </div>\n }\n </aside>\n\n <!-- Main Content -->\n <main class=\"main-content\">\n <!-- Toolbar -->\n <div class=\"toolbar\">\n <div class=\"toolbar-left\">\n <div class=\"toolbar-search-box\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search tests and suites...\"\n [value]=\"SearchTerm\"\n (input)=\"OnSearchInput($event)\"\n />\n @if (SearchTerm) {\n <button class=\"clear-search\" (click)=\"ClearSearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n <div class=\"status-chips\">\n @for (status of StatusOptions; track status) {\n <button\n class=\"chip\"\n [class.active]=\"IsStatusActive(status)\"\n [attr.data-status]=\"status.toLowerCase()\"\n (click)=\"ToggleStatus(status)\"\n >\n {{ status }}\n </button>\n }\n </div>\n </div>\n <div class=\"toolbar-right\">\n <span class=\"result-count\">{{ FilteredResultCount }} results</span>\n <div class=\"view-toggle\">\n <button\n class=\"view-btn\"\n [class.active]=\"ViewMode === 'card'\"\n (click)=\"SetViewMode('card')\"\n title=\"Card View\"\n >\n <i class=\"fa-solid fa-grip\"></i>\n </button>\n <button\n class=\"view-btn\"\n [class.active]=\"ViewMode === 'list'\"\n (click)=\"SetViewMode('list')\"\n title=\"List View\"\n >\n <i class=\"fa-solid fa-list\"></i>\n </button>\n </div>\n <button class=\"btn btn-secondary\" (click)=\"OnNewSuite()\">\n <i class=\"fa-solid fa-folder-plus\"></i>\n New Suite\n </button>\n <button class=\"btn btn-primary\" (click)=\"OnNewTest()\">\n <i class=\"fa-solid fa-plus\"></i>\n New Test\n </button>\n </div>\n </div>\n\n <!-- Toggle Bar -->\n <div class=\"toggle-bar\">\n <div class=\"toggle-group\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"DisplayMode === 'all'\"\n (click)=\"SetDisplayMode('all')\"\n >All</button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"DisplayMode === 'suites'\"\n (click)=\"SetDisplayMode('suites')\"\n >Suites Only</button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"DisplayMode === 'tests'\"\n (click)=\"SetDisplayMode('tests')\"\n >Tests Only</button>\n </div>\n <div class=\"sort-indicator\">\n <button class=\"sort-btn\" (click)=\"ToggleSortDirection()\">\n <i class=\"fa-solid fa-arrow-down-short-wide\"></i>\n {{ SortFieldLabel }}\n <i class=\"fa-solid\" [class.fa-arrow-up]=\"SortDirection === 'asc'\" [class.fa-arrow-down]=\"SortDirection === 'desc'\"></i>\n </button>\n </div>\n </div>\n\n <!-- Content Area -->\n <div class=\"content-area\">\n <!-- Suites Section -->\n @if (DisplayMode === 'all' || DisplayMode === 'suites') {\n @if (FilteredSuites.length > 0) {\n <div class=\"content-section\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-folder\"></i>\n Test Suites\n <span class=\"section-count\">{{ FilteredSuites.length }}</span>\n </h3>\n <div class=\"card-grid\">\n @for (suite of FilteredSuites; track suite.ID) {\n <div class=\"suite-card\">\n <div class=\"card-header\">\n <div class=\"card-title-row\">\n <i class=\"fa-solid fa-folder-open card-icon suite-icon\"></i>\n <span class=\"card-name\" [innerHTML]=\"suite.Name | highlightSearch:SearchTerm\"></span>\n <span class=\"status-badge\" [attr.data-status]=\"suite.Status.toLowerCase()\">{{ suite.Status }}</span>\n </div>\n <div class=\"card-subtitle\">\n {{ suite.TestCount }} tests\n @if (suite.LastRunDate) {\n <span class=\"dot-sep\"></span>\n Last run {{ FormatRelativeTime(suite.LastRunDate) }}\n }\n </div>\n @if (suite.Description) {\n <p class=\"card-description\" [innerHTML]=\"suite.Description | highlightSearch:SearchTerm\"></p>\n }\n </div>\n\n <div class=\"card-stats\">\n <div class=\"stat\">\n <span class=\"stat-label\">Pass Rate</span>\n <span class=\"stat-value\" [class]=\"GetScoreClass(suite.PassRate / 100)\">{{ FormatPercent(suite.PassRate) }}</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Tests</span>\n <span class=\"stat-value\">{{ suite.TestCount }}</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Avg Score</span>\n <span class=\"stat-value\" [class]=\"GetScoreClass(suite.AvgScore)\">{{ (suite.AvgScore * 100).toFixed(0) }}%</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Avg Duration</span>\n <span class=\"stat-value\">{{ FormatDuration(suite.AvgDuration) }}</span>\n </div>\n </div>\n\n @if (suite.Tests.length > 0) {\n <div class=\"card-tests-preview\">\n @for (t of suite.Tests; track t.TestID; let i = $index) {\n @if (i < 4) {\n <div class=\"preview-test-row\">\n <span class=\"preview-dot\" [attr.data-status]=\"t.LastStatus.toLowerCase()\"></span>\n <span class=\"preview-test-name\">{{ t.TestName }}</span>\n <span class=\"preview-score\" [class]=\"GetScoreClass(t.LastScore)\">{{ (t.LastScore * 100).toFixed(0) }}%</span>\n <span class=\"preview-bar\">\n <span class=\"preview-bar-fill\" [style.width.%]=\"t.LastScore * 100\" [class]=\"GetScoreClass(t.LastScore) + '-bg'\"></span>\n </span>\n <span class=\"preview-status\" [attr.data-status]=\"t.LastStatus.toLowerCase()\">{{ t.LastStatus }}</span>\n </div>\n }\n }\n @if (suite.TotalTestsInSuite > 4) {\n <div class=\"preview-more\">+{{ suite.TotalTestsInSuite - 4 }} more tests</div>\n }\n </div>\n }\n\n <div class=\"card-actions\">\n <button class=\"btn btn-sm btn-primary\" (click)=\"RunSuite(suite.ID)\">\n <i class=\"fa-solid fa-play\"></i> Run Suite\n </button>\n <button class=\"btn btn-sm btn-secondary\" (click)=\"ViewSuiteResults(suite.ID)\">\n <i class=\"fa-solid fa-chart-bar\"></i> Results\n </button>\n <button class=\"btn btn-sm btn-secondary\" (click)=\"EditItem('MJ: Test Suites', suite.ID)\">\n <i class=\"fa-solid fa-pen\"></i> Edit\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n }\n }\n\n <!-- Tests Section -->\n @if (DisplayMode === 'all' || DisplayMode === 'tests') {\n @if (FilteredTests.length > 0) {\n <div class=\"content-section\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-vial\"></i>\n Tests\n <span class=\"section-count\">{{ FilteredTests.length }}</span>\n </h3>\n <div class=\"card-grid\">\n @for (test of FilteredTests; track test.ID) {\n <div class=\"test-card\">\n <div class=\"card-header\">\n <div class=\"card-title-row\">\n <i class=\"fa-solid fa-vial card-icon test-icon\"></i>\n <span class=\"card-name\" [innerHTML]=\"test.Name | highlightSearch:SearchTerm\"></span>\n <span class=\"status-badge\" [attr.data-status]=\"test.Status.toLowerCase()\">{{ test.Status }}</span>\n </div>\n <div class=\"card-subtitle\">\n {{ test.TypeName }}\n @if (test.SuiteName) {\n <span class=\"dot-sep\"></span>\n {{ test.SuiteName }}\n }\n </div>\n @if (test.Description) {\n <p class=\"card-description\" [innerHTML]=\"test.Description | highlightSearch:SearchTerm\"></p>\n }\n <div class=\"card-meta-row\">\n @if (test.TypeName) {\n <span class=\"meta-item\"><i class=\"fa-solid fa-robot\"></i> {{ test.TypeName }}</span>\n }\n @if (test.EstDuration > 0) {\n <span class=\"meta-item\"><i class=\"fa-solid fa-clock\"></i> ~{{ FormatDurationSeconds(test.EstDuration) }}</span>\n }\n @if (test.EstCost > 0) {\n <span class=\"meta-item\"><i class=\"fa-solid fa-dollar-sign\"></i> {{ FormatCost(test.EstCost) }}</span>\n }\n <span class=\"meta-item\"><i class=\"fa-solid fa-calendar\"></i> {{ FormatRelativeTime(test.UpdatedAt) }}</span>\n </div>\n @if (test.Tags.length > 0) {\n <div class=\"card-tags\">\n @for (tag of test.Tags; track tag; let i = $index) {\n @if (i < 4) {\n <span class=\"tag\">{{ tag }}</span>\n }\n }\n @if (test.Tags.length > 4) {\n <span class=\"tag tag-more\">+{{ test.Tags.length - 4 }}</span>\n }\n </div>\n }\n </div>\n\n <div class=\"card-stats\">\n <div class=\"stat\">\n <span class=\"stat-label\">Last Status</span>\n <span class=\"stat-value status-text\" [attr.data-status]=\"test.LastRunStatus.toLowerCase()\">{{ test.LastRunStatus || 'N/A' }}</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Score</span>\n <span class=\"stat-value\" [class]=\"GetScoreClass(test.LastScore)\">{{ test.LastScore > 0 ? (test.LastScore * 100).toFixed(0) + '%' : 'N/A' }}</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Total Runs</span>\n <span class=\"stat-value\">{{ test.TotalRuns }}</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Pass Rate</span>\n <span class=\"stat-value\" [class]=\"GetScoreClass(test.PassRate / 100)\">{{ test.TotalRuns > 0 ? FormatPercent(test.PassRate) : 'N/A' }}</span>\n </div>\n </div>\n\n <div class=\"card-actions\">\n <button class=\"btn btn-sm btn-primary\" (click)=\"RunTest(test.ID)\">\n <i class=\"fa-solid fa-play\"></i> Run\n </button>\n <button class=\"btn btn-sm btn-secondary\" (click)=\"ViewTestHistory(test.ID)\">\n <i class=\"fa-solid fa-history\"></i> History\n </button>\n <button class=\"btn btn-sm btn-secondary\" (click)=\"EditItem('MJ: Tests', test.ID)\">\n <i class=\"fa-solid fa-pen\"></i> Edit\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n }\n }\n\n <!-- Empty State -->\n @if (FilteredSuites.length === 0 && FilteredTests.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <p>No tests or suites found</p>\n <span class=\"empty-hint\">Try adjusting your search or filters.</span>\n </div>\n }\n </div>\n </main>\n </div>\n }\n\n <!-- Template for recursive suite tree rendering -->\n <ng-template #suiteTreeTpl let-node=\"node\" let-depth=\"depth\">\n <div\n class=\"sidebar-item suite-tree-item\"\n [style.paddingLeft.px]=\"16 + depth * 14\"\n [class.active]=\"SelectedSidebar.Type === 'suite' && SelectedSidebar.ID === node.ID\"\n (click)=\"SelectSidebarItem({ Type: 'suite', ID: node.ID })\"\n >\n @if (node.Children.length > 0) {\n <button class=\"tree-toggle\" (click)=\"ToggleSuiteExpand(node, $event)\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"!node.Expanded\" [class.fa-chevron-down]=\"node.Expanded\"></i>\n </button>\n }\n <i class=\"fa-solid fa-folder\"></i>\n <span class=\"tree-name\">{{ node.Name }}</span>\n <span class=\"sidebar-count\">{{ node.TestCount }}</span>\n </div>\n @if (node.Expanded && node.Children.length > 0) {\n @for (child of node.Children; track child.ID) {\n <ng-container\n *ngTemplateOutlet=\"suiteTreeTpl; context: { node: child, depth: depth + 1 }\"\n ></ng-container>\n }\n }\n </ng-template>\n\n <!-- Slideout Backdrop -->\n @if (SlideoutOpen) {\n <div class=\"slideout-backdrop\" (click)=\"CloseSlideout()\"></div>\n }\n\n <!-- Slideout Panel -->\n <div class=\"slideout-panel\" [class.open]=\"SlideoutOpen\" [style.width.px]=\"SlideoutWidth\">\n <div class=\"slideout-resize-handle\" (mousedown)=\"OnResizeStart($event)\"></div>\n\n @if (SlideoutOpen) {\n <div class=\"slideout-container\">\n <!-- Slideout Header -->\n <div class=\"slideout-header\">\n <div class=\"slideout-title-row\">\n <i class=\"fa-solid fa-plus-circle slideout-title-icon\"></i>\n <span class=\"slideout-title-text\">\n Create {{ SlideoutCreateType === 'test' ? 'Test' : 'Test Suite' }}\n </span>\n </div>\n <button class=\"slideout-close-btn\" (click)=\"CloseSlideout()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <!-- Type Toggle -->\n <div class=\"slideout-type-toggle\">\n <button\n class=\"type-toggle-btn\"\n [class.active]=\"SlideoutCreateType === 'test'\"\n (click)=\"SetSlideoutCreateType('test')\"\n >\n <i class=\"fa-solid fa-vial\"></i> Test\n </button>\n <button\n class=\"type-toggle-btn\"\n [class.active]=\"SlideoutCreateType === 'suite'\"\n (click)=\"SetSlideoutCreateType('suite')\"\n >\n <i class=\"fa-solid fa-folder\"></i> Suite\n </button>\n </div>\n\n <!-- Error Banner -->\n @if (FormErrorMessage) {\n <div class=\"slideout-error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n <span>{{ FormErrorMessage }}</span>\n </div>\n }\n\n <!-- Slideout Body -->\n <div class=\"slideout-body\">\n <div class=\"form-section\">\n <div class=\"form-section-title\">General</div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Name <span class=\"form-required\">*</span></label>\n <input\n class=\"form-input\"\n type=\"text\"\n [(ngModel)]=\"FormName\"\n [placeholder]=\"SlideoutCreateType === 'test' ? 'e.g., Agent Response Quality Test' : 'e.g., Core Agent Test Suite'\"\n />\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Description</label>\n <textarea\n class=\"form-textarea\"\n [(ngModel)]=\"FormDescription\"\n rows=\"3\"\n [placeholder]=\"SlideoutCreateType === 'test' ? 'What does this test evaluate?' : 'What does this suite contain?'\"\n ></textarea>\n </div>\n\n <div class=\"form-row\">\n @if (SlideoutCreateType === 'test') {\n <div class=\"form-group\">\n <label class=\"form-label\">Test Type <span class=\"form-required\">*</span></label>\n <select class=\"form-input\" [(ngModel)]=\"FormTypeID\">\n <option value=\"\" disabled>Select type...</option>\n @for (tt of AllTestTypes; track tt.ID) {\n <option [value]=\"tt.ID\">{{ tt.Name }}</option>\n }\n </select>\n </div>\n }\n @if (SlideoutCreateType === 'suite') {\n <div class=\"form-group\">\n <label class=\"form-label\">Parent Suite</label>\n <select class=\"form-input\" [(ngModel)]=\"FormParentSuiteID\">\n <option value=\"\">None (top-level)</option>\n @for (s of AllSuites; track s.ID) {\n <option [value]=\"s.ID\">{{ s.Name }}</option>\n }\n </select>\n </div>\n }\n <div class=\"form-group\">\n <label class=\"form-label\">Status</label>\n <select class=\"form-input\" [(ngModel)]=\"FormStatus\">\n @for (status of FormStatusOptions; track status) {\n <option [value]=\"status\">{{ status }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n\n @if (SlideoutCreateType === 'test') {\n <div class=\"form-section\">\n <div class=\"form-section-title\">Estimates</div>\n <div class=\"form-row\">\n <div class=\"form-group\">\n <label class=\"form-label\">Duration (seconds)</label>\n <input\n class=\"form-input\"\n type=\"number\"\n [(ngModel)]=\"FormEstDuration\"\n min=\"0\"\n placeholder=\"0\"\n />\n </div>\n <div class=\"form-group\">\n <label class=\"form-label\">Cost (USD)</label>\n <input\n class=\"form-input\"\n type=\"number\"\n [(ngModel)]=\"FormEstCost\"\n min=\"0\"\n step=\"0.01\"\n placeholder=\"0.00\"\n />\n </div>\n </div>\n </div>\n }\n\n <div class=\"form-section\">\n <div class=\"form-section-title\">Tags</div>\n <div class=\"form-group\">\n <input\n class=\"form-input\"\n type=\"text\"\n [(ngModel)]=\"FormTags\"\n placeholder=\"Comma-separated tags, e.g., agent, quality, v2\"\n />\n <span class=\"form-hint\">Separate multiple tags with commas</span>\n </div>\n </div>\n </div>\n\n <!-- Slideout Footer -->\n <div class=\"slideout-footer\">\n <button class=\"btn btn-secondary\" (click)=\"CloseSlideout()\">Cancel</button>\n <button class=\"btn btn-primary\" (click)=\"SaveForm()\" [disabled]=\"!IsFormValid || IsSaving\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n }\n Create {{ SlideoutCreateType === 'test' ? 'Test' : 'Suite' }}\n </button>\n </div>\n </div>\n }\n </div>\n `,\n styles: [`\n /* ==========================================\n Testing Explorer Component\n ========================================== */\n\n :host {\n display: block;\n height: 100%;\n width: 100%;\n }\n\n /* Loading */\n .explorer-loading {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n min-height: 400px;\n background: #f5f6fa;\n }\n\n /* Layout */\n .explorer-layout {\n display: flex;\n height: 100%;\n background: #f5f6fa;\n overflow: hidden;\n }\n\n /* ==========================================\n Sidebar\n ========================================== */\n .sidebar {\n width: 280px;\n min-width: 280px;\n background: #fff;\n border-right: 1px solid #e8ecef;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transition: width 0.2s ease, min-width 0.2s ease;\n }\n\n .sidebar.collapsed {\n width: 48px;\n min-width: 48px;\n }\n\n .sidebar-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px;\n border-bottom: 1px solid #e8ecef;\n }\n\n .sidebar-header h3 {\n margin: 0;\n font-size: 15px;\n font-weight: 700;\n color: #2d3436;\n }\n\n .sidebar.collapsed .sidebar-header h3 {\n display: none;\n }\n\n .sidebar-toggle {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n color: #636e72;\n cursor: pointer;\n font-size: 11px;\n transition: all 0.15s ease;\n }\n\n .sidebar-toggle:hover {\n background: #f5f6fa;\n color: #2d3436;\n }\n\n .sidebar-content {\n flex: 1;\n overflow-y: auto;\n padding: 8px 0;\n }\n\n .sidebar-section {\n margin-bottom: 8px;\n }\n\n .sidebar-section-title {\n padding: 8px 16px 4px;\n font-size: 10px;\n font-weight: 700;\n color: #b2bec3;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n }\n\n .sidebar-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n font-size: 13px;\n color: #636e72;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n overflow: hidden;\n }\n\n .sidebar-item:hover {\n background: #f5f6fa;\n color: #2d3436;\n }\n\n .sidebar-item.active {\n background: #e0f2f1;\n color: #00897b;\n font-weight: 600;\n }\n\n .sidebar-item i {\n font-size: 12px;\n width: 16px;\n text-align: center;\n flex-shrink: 0;\n }\n\n .sidebar-item span:not(.sidebar-count) {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sidebar-count {\n font-size: 11px;\n color: #b2bec3;\n font-weight: 500;\n flex-shrink: 0;\n }\n\n .sidebar-item.active .sidebar-count {\n color: #00897b;\n }\n\n .sidebar-empty {\n padding: 8px 16px;\n font-size: 12px;\n color: #b2bec3;\n font-style: italic;\n }\n\n /* Tree nodes */\n .suite-tree-item {\n gap: 6px;\n }\n\n .tree-toggle {\n width: 18px;\n height: 18px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n color: #b2bec3;\n cursor: pointer;\n font-size: 9px;\n flex-shrink: 0;\n border-radius: 4px;\n padding: 0;\n }\n\n .tree-toggle:hover {\n background: #e8ecef;\n color: #636e72;\n }\n\n .tree-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n /* ==========================================\n Main Content\n ========================================== */\n .main-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n /* Toolbar */\n .toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n padding: 16px 24px;\n background: #fff;\n border-bottom: 1px solid #e8ecef;\n flex-shrink: 0;\n }\n\n .toolbar-left {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n }\n\n .toolbar-search-box {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n background: #f5f6fa;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n min-width: 240px;\n max-width: 360px;\n flex: 1;\n transition: border-color 0.2s ease;\n }\n\n .toolbar-search-box:focus-within {\n border-color: #00897b;\n background: #fff;\n }\n\n .toolbar-search-box i {\n color: #b2bec3;\n font-size: 13px;\n }\n\n .toolbar-search-box input {\n flex: 1;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: #2d3436;\n }\n\n .toolbar-search-box input::placeholder {\n color: #b2bec3;\n }\n\n .clear-search {\n border: none;\n background: transparent;\n color: #b2bec3;\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 4px;\n }\n\n .clear-search:hover {\n color: #636e72;\n background: #e8ecef;\n }\n\n .status-chips {\n display: flex;\n gap: 6px;\n }\n\n .chip {\n display: inline-flex;\n align-items: center;\n padding: 6px 14px;\n background: #f5f6fa;\n border: 1px solid transparent;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 600;\n color: #636e72;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n\n .chip:hover {\n background: #e8ecef;\n }\n\n .chip.active {\n color: #fff;\n }\n\n .chip.active[data-status=\"active\"] {\n background: #2e7d32;\n border-color: #2e7d32;\n }\n\n .chip.active[data-status=\"pending\"] {\n background: #e65100;\n border-color: #e65100;\n }\n\n .chip.active[data-status=\"disabled\"] {\n background: #636e72;\n border-color: #636e72;\n }\n\n .toolbar-right {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n }\n\n .result-count {\n font-size: 12px;\n color: #b2bec3;\n font-weight: 500;\n white-space: nowrap;\n }\n\n .view-toggle {\n display: flex;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n overflow: hidden;\n }\n\n .view-btn {\n width: 34px;\n height: 34px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #fff;\n border: none;\n color: #b2bec3;\n cursor: pointer;\n font-size: 13px;\n transition: all 0.15s ease;\n }\n\n .view-btn:not(:last-child) {\n border-right: 1px solid #e8ecef;\n }\n\n .view-btn:hover {\n background: #f5f6fa;\n color: #636e72;\n }\n\n .view-btn.active {\n background: #00897b;\n color: #fff;\n }\n\n /* Buttons */\n .btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 9px 16px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n\n .btn-primary {\n background: #00897b;\n color: #fff;\n }\n\n .btn-primary:hover {\n background: #00796b;\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 137, 123, 0.3);\n }\n\n .btn-secondary {\n background: #fff;\n color: #636e72;\n border: 1px solid #e8ecef;\n }\n\n .btn-secondary:hover {\n background: #f5f6fa;\n }\n\n .btn-sm {\n padding: 6px 12px;\n font-size: 12px;\n }\n\n /* Toggle Bar */\n .toggle-bar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 24px;\n background: #fafafa;\n border-bottom: 1px solid #e8ecef;\n flex-shrink: 0;\n }\n\n .toggle-group {\n display: flex;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n overflow: hidden;\n }\n\n .toggle-btn {\n padding: 6px 16px;\n background: #fff;\n border: none;\n font-size: 12px;\n font-weight: 600;\n color: #636e72;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n\n .toggle-btn:not(:last-child) {\n border-right: 1px solid #e8ecef;\n }\n\n .toggle-btn.active {\n background: #00897b;\n color: #fff;\n }\n\n .toggle-btn:hover:not(.active) {\n background: #f5f6fa;\n }\n\n .sort-indicator {\n display: flex;\n align-items: center;\n }\n\n .sort-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: #636e72;\n cursor: pointer;\n }\n\n .sort-btn:hover {\n background: #f5f6fa;\n }\n\n .sort-btn i {\n font-size: 11px;\n }\n\n /* Content Area */\n .content-area {\n flex: 1;\n overflow-y: auto;\n padding: 24px;\n }\n\n .content-section {\n margin-bottom: 32px;\n }\n\n .section-title {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 700;\n color: #2d3436;\n }\n\n .section-title i {\n color: #00897b;\n font-size: 14px;\n }\n\n .section-count {\n font-size: 12px;\n font-weight: 600;\n color: #b2bec3;\n background: #f5f6fa;\n padding: 2px 8px;\n border-radius: 10px;\n }\n\n /* Card Grid */\n .card-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));\n gap: 16px;\n }\n\n /* Suite Card */\n .suite-card,\n .test-card {\n background: #fff;\n border: 1px solid #e8ecef;\n border-radius: 10px;\n overflow: hidden;\n transition: all 0.2s ease;\n }\n\n .suite-card:hover,\n .test-card:hover {\n border-color: #b2dfdb;\n box-shadow: 0 4px 16px rgba(0, 137, 123, 0.1);\n }\n\n .card-header {\n padding: 16px 16px 12px;\n }\n\n .card-title-row {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n }\n\n .card-icon {\n font-size: 14px;\n flex-shrink: 0;\n }\n\n .suite-icon {\n color: #00897b;\n }\n\n .test-icon {\n color: #6366f1;\n }\n\n .card-name {\n flex: 1;\n font-size: 14px;\n font-weight: 700;\n color: #2d3436;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .status-badge {\n font-size: 10px;\n font-weight: 700;\n padding: 3px 8px;\n border-radius: 4px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n flex-shrink: 0;\n }\n\n .status-badge[data-status=\"active\"] {\n background: #e8f5e9;\n color: #2e7d32;\n }\n\n .status-badge[data-status=\"pending\"] {\n background: #fff3e0;\n color: #e65100;\n }\n\n .status-badge[data-status=\"disabled\"] {\n background: #f5f6fa;\n color: #636e72;\n }\n\n .card-subtitle {\n font-size: 12px;\n color: #636e72;\n margin-bottom: 6px;\n }\n\n .dot-sep {\n display: inline-block;\n width: 3px;\n height: 3px;\n background: #b2bec3;\n border-radius: 50%;\n vertical-align: middle;\n margin: 0 6px;\n }\n\n .card-description {\n margin: 0;\n font-size: 12px;\n color: #636e72;\n line-height: 1.5;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .card-meta-row {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n margin-top: 8px;\n }\n\n .meta-item {\n font-size: 11px;\n color: #636e72;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .meta-item i {\n font-size: 10px;\n color: #b2bec3;\n }\n\n .card-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-top: 8px;\n }\n\n .tag {\n font-size: 10px;\n font-weight: 600;\n padding: 2px 8px;\n background: #f5f6fa;\n color: #636e72;\n border-radius: 4px;\n }\n\n .tag-more {\n background: #e8ecef;\n color: #b2bec3;\n }\n\n /* Card Stats */\n .card-stats {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 1px;\n background: #e8ecef;\n border-top: 1px solid #e8ecef;\n }\n\n .stat {\n background: #fafafa;\n padding: 10px 12px;\n text-align: center;\n }\n\n .stat-label {\n display: block;\n font-size: 10px;\n font-weight: 600;\n color: #b2bec3;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n margin-bottom: 2px;\n }\n\n .stat-value {\n font-size: 14px;\n font-weight: 700;\n color: #2d3436;\n }\n\n .stat-value.good { color: #2e7d32; }\n .stat-value.warn { color: #e65100; }\n .stat-value.bad { color: #c62828; }\n\n .status-text[data-status=\"passed\"] { color: #2e7d32; }\n .status-text[data-status=\"failed\"] { color: #c62828; }\n .status-text[data-status=\"error\"] { color: #e65100; }\n .status-text[data-status=\"running\"] { color: #1565c0; }\n .status-text[data-status=\"pending\"] { color: #e65100; }\n .status-text[data-status=\"skipped\"] { color: #636e72; }\n\n /* Suite Tests Preview */\n .card-tests-preview {\n padding: 10px 16px;\n border-top: 1px solid #e8ecef;\n }\n\n .preview-test-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n font-size: 12px;\n }\n\n .preview-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .preview-dot[data-status=\"passed\"] { background: #2e7d32; }\n .preview-dot[data-status=\"failed\"] { background: #c62828; }\n .preview-dot[data-status=\"error\"] { background: #e65100; }\n .preview-dot[data-status=\"running\"] { background: #1565c0; }\n .preview-dot[data-status=\"\"] { background: #b2bec3; }\n\n .preview-test-name {\n flex: 1;\n color: #2d3436;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .preview-score {\n font-weight: 600;\n font-size: 11px;\n min-width: 32px;\n text-align: right;\n }\n\n .preview-score.good { color: #2e7d32; }\n .preview-score.warn { color: #e65100; }\n .preview-score.bad { color: #c62828; }\n\n .preview-bar {\n width: 48px;\n height: 4px;\n background: #e8ecef;\n border-radius: 2px;\n overflow: hidden;\n flex-shrink: 0;\n }\n\n .preview-bar-fill {\n height: 100%;\n border-radius: 2px;\n transition: width 0.3s ease;\n }\n\n .good-bg { background: #2e7d32; }\n .warn-bg { background: #e65100; }\n .bad-bg { background: #c62828; }\n\n .preview-status {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n min-width: 44px;\n text-align: right;\n }\n\n .preview-status[data-status=\"passed\"] { color: #2e7d32; }\n .preview-status[data-status=\"failed\"] { color: #c62828; }\n .preview-status[data-status=\"error\"] { color: #e65100; }\n .preview-status[data-status=\"\"] { color: #b2bec3; }\n\n .preview-more {\n padding: 4px 0 0;\n font-size: 11px;\n color: #b2bec3;\n font-style: italic;\n }\n\n /* Card Actions */\n .card-actions {\n display: flex;\n gap: 8px;\n padding: 12px 16px;\n border-top: 1px solid #e8ecef;\n background: #fafafa;\n }\n\n /* Empty State */\n .empty-state {\n padding: 80px 40px;\n text-align: center;\n }\n\n .empty-state i {\n font-size: 48px;\n color: #b2bec3;\n margin-bottom: 16px;\n }\n\n .empty-state p {\n font-size: 16px;\n color: #636e72;\n margin: 0 0 8px 0;\n }\n\n .empty-hint {\n font-size: 13px;\n color: #b2bec3;\n }\n\n /* ==========================================\n Slideout Panel\n ========================================== */\n .slideout-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 999;\n animation: fadeInBackdrop 0.2s ease;\n }\n\n @keyframes fadeInBackdrop {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n .slideout-panel {\n position: fixed;\n top: 0;\n right: -100%;\n height: 100vh;\n background: #fff;\n box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .slideout-panel.open {\n right: 0;\n }\n\n .slideout-resize-handle {\n position: absolute;\n top: 0;\n left: 0;\n width: 5px;\n height: 100%;\n cursor: col-resize;\n background: transparent;\n z-index: 10;\n transition: background 0.2s;\n }\n\n .slideout-resize-handle:hover {\n background: rgba(0, 137, 123, 0.3);\n }\n\n .slideout-resize-handle:active {\n background: rgba(0, 137, 123, 0.5);\n }\n\n .slideout-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n }\n\n .slideout-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n border-bottom: 1px solid #e8ecef;\n flex-shrink: 0;\n }\n\n .slideout-title-row {\n display: flex;\n align-items: center;\n gap: 10px;\n }\n\n .slideout-title-icon {\n font-size: 18px;\n color: #00897b;\n }\n\n .slideout-title-text {\n font-size: 18px;\n font-weight: 700;\n color: #2d3436;\n }\n\n .slideout-close-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n color: #636e72;\n cursor: pointer;\n font-size: 14px;\n transition: all 0.15s ease;\n }\n\n .slideout-close-btn:hover {\n background: #f5f6fa;\n color: #2d3436;\n border-color: #ccc;\n }\n\n /* Type Toggle */\n .slideout-type-toggle {\n display: flex;\n gap: 0;\n padding: 16px 24px;\n border-bottom: 1px solid #e8ecef;\n flex-shrink: 0;\n }\n\n .type-toggle-btn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px 16px;\n background: #f5f6fa;\n border: 1px solid #e8ecef;\n font-size: 13px;\n font-weight: 600;\n color: #636e72;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n\n .type-toggle-btn:first-child {\n border-radius: 8px 0 0 8px;\n border-right: none;\n }\n\n .type-toggle-btn:last-child {\n border-radius: 0 8px 8px 0;\n }\n\n .type-toggle-btn.active {\n background: #00897b;\n border-color: #00897b;\n color: #fff;\n }\n\n .type-toggle-btn:hover:not(.active) {\n background: #e8ecef;\n }\n\n /* Error Banner */\n .slideout-error {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 16px 24px 0;\n padding: 12px 16px;\n background: #fff5f5;\n border: 1px solid #fed7d7;\n border-radius: 8px;\n color: #c53030;\n font-size: 13px;\n flex-shrink: 0;\n }\n\n .slideout-error i {\n font-size: 14px;\n flex-shrink: 0;\n }\n\n /* Slideout Body */\n .slideout-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px 24px;\n }\n\n .form-section {\n margin-bottom: 24px;\n }\n\n .form-section-title {\n font-size: 12px;\n font-weight: 700;\n color: #b2bec3;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n margin-bottom: 14px;\n padding-bottom: 8px;\n border-bottom: 1px solid #f0f0f0;\n }\n\n .form-group {\n margin-bottom: 16px;\n }\n\n .form-label {\n display: block;\n font-size: 13px;\n font-weight: 600;\n color: #2d3436;\n margin-bottom: 6px;\n }\n\n .form-required {\n color: #e53e3e;\n }\n\n .form-input,\n .form-textarea {\n width: 100%;\n padding: 10px 14px;\n background: #fff;\n border: 1px solid #e8ecef;\n border-radius: 8px;\n font-size: 13px;\n color: #2d3436;\n transition: border-color 0.2s ease;\n outline: none;\n box-sizing: border-box;\n font-family: inherit;\n }\n\n .form-input:focus,\n .form-textarea:focus {\n border-color: #00897b;\n box-shadow: 0 0 0 3px rgba(0, 137, 123, 0.1);\n }\n\n .form-input::placeholder,\n .form-textarea::placeholder {\n color: #b2bec3;\n }\n\n .form-textarea {\n resize: vertical;\n min-height: 80px;\n }\n\n .form-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n }\n\n .form-hint {\n display: block;\n font-size: 11px;\n color: #b2bec3;\n margin-top: 4px;\n }\n\n /* Slideout Footer */\n .slideout-footer {\n display: flex;\n justify-content: flex-end;\n gap: 10px;\n padding: 16px 24px;\n border-top: 1px solid #e8ecef;\n background: #fafafa;\n flex-shrink: 0;\n }\n\n .slideout-footer .btn {\n min-width: 100px;\n justify-content: center;\n }\n\n .slideout-footer .btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n box-shadow: none;\n }\n\n /* Search Highlight */\n ::ng-deep mark.search-highlight {\n background: #fff9c4;\n color: inherit;\n padding: 1px 2px;\n border-radius: 2px;\n font-weight: 700;\n }\n\n /* ==========================================\n Responsive\n ========================================== */\n @media (max-width: 1200px) {\n .card-grid {\n grid-template-columns: 1fr;\n }\n }\n\n @media (max-width: 900px) {\n .sidebar {\n display: none;\n }\n\n .toolbar {\n flex-direction: column;\n align-items: stretch;\n }\n\n .toolbar-left, .toolbar-right {\n flex-wrap: wrap;\n justify-content: center;\n }\n }\n\n @media (max-width: 600px) {\n .content-area {\n padding: 16px;\n }\n\n .card-stats {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .slideout-panel {\n width: 100% !important;\n }\n\n .slideout-resize-handle {\n display: none;\n }\n\n .form-row {\n grid-template-columns: 1fr;\n }\n }\n `]\n})\nexport class TestingExplorerComponent implements OnInit, OnDestroy {\n\n private destroy$ = new Subject<void>();\n\n // Raw cached data\n private allTests: MJTestEntity[] = [];\n AllSuites: MJTestSuiteEntity[] = [];\n private allSuiteTests: MJTestSuiteTestEntity[] = [];\n AllTestTypes: MJTestTypeEntity[] = [];\n private testRunStats: TestRunStatRow[] = [];\n\n // Computed card data\n private suiteCards: SuiteCardData[] = [];\n private testCards: TestCardData[] = [];\n\n // State subjects\n private _searchTerm$ = new BehaviorSubject<string>('');\n private _statusFilters$ = new BehaviorSubject<Set<string>>(new Set());\n private _viewMode$ = new BehaviorSubject<ViewMode>('card');\n private _displayMode$ = new BehaviorSubject<DisplayMode>('all');\n private _selectedSidebar$ = new BehaviorSubject<SidebarSelection>({ Type: 'all', ID: null });\n private _sortField$ = new BehaviorSubject<SortField>('name');\n private _sortDirection$ = new BehaviorSubject<SortDirection>('asc');\n\n // Template-bound state\n IsLoading = true;\n IsSidebarCollapsed = false;\n SearchTerm = '';\n StatusFilters = new Set<string>();\n ViewMode: ViewMode = 'card';\n DisplayMode: DisplayMode = 'all';\n SelectedSidebar: SidebarSelection = { Type: 'all', ID: null };\n SortField: SortField = 'name';\n SortDirection: SortDirection = 'asc';\n\n // Filtered results\n FilteredSuites: SuiteCardData[] = [];\n FilteredTests: TestCardData[] = [];\n FilteredSuiteTree: SuiteTreeNode[] = [];\n FilteredTestTypes: MJTestTypeEntity[] = [];\n\n // Counts\n TotalItemCount = 0;\n StandaloneTestCount = 0;\n FilteredResultCount = 0;\n\n readonly StatusOptions: string[] = ['Active', 'Pending', 'Disabled'];\n readonly FormStatusOptions: string[] = ['Active', 'Pending', 'Disabled'];\n\n // Settings keys\n private static readonly PANEL_WIDTH_KEY = 'Testing.ExplorerPanelWidth';\n private static readonly SEARCH_STATE_KEY = 'Testing.ExplorerSearchState';\n private settingsPersistSubject = new Subject<void>();\n private settingsLoaded = false;\n\n // Slideout state\n SlideoutOpen = false;\n SlideoutCreateType: 'test' | 'suite' = 'test';\n SlideoutWidth = 560;\n IsSaving = false;\n FormErrorMessage = '';\n\n // Resize state\n private resizeStartX = 0;\n private resizeStartWidth = 0;\n\n // Form fields\n FormName = '';\n FormDescription = '';\n FormTypeID = '';\n FormStatus: 'Active' | 'Pending' | 'Disabled' = 'Active';\n FormParentSuiteID = '';\n FormEstDuration = 0;\n FormEstCost = 0;\n FormTags = '';\n\n get IsFormValid(): boolean {\n if (!this.FormName.trim()) return false;\n if (this.SlideoutCreateType === 'test' && !this.FormTypeID) return false;\n return true;\n }\n\n get SortFieldLabel(): string {\n switch (this.SortField) {\n case 'name': return 'Name';\n case 'updated': return 'Updated';\n case 'status': return 'Status';\n default: return 'Name';\n }\n }\n\n constructor(\n private cdr: ChangeDetectorRef,\n private viewContainerRef: ViewContainerRef,\n private testingDialogService: TestingDialogService,\n public instrumentationService: TestingInstrumentationService\n ) {}\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n async ngOnInit(): Promise<void> {\n this.loadUserSettings();\n this.setupSettingsPersistence();\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n try {\n await TestEngineBase.Instance.Config(false);\n await this.LoadData();\n } catch (err) {\n console.error('TestingExplorerComponent: Failed to load data', err);\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n\n this.subscribeToStateChanges();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n document.removeEventListener('mousemove', this.onResizeMove);\n document.removeEventListener('mouseup', this.onResizeEnd);\n UserInfoEngine.Instance.FlushPendingSettings();\n }\n\n // ---------------------------------------------------------------------------\n // Public Methods\n // ---------------------------------------------------------------------------\n\n async LoadData(): Promise<void> {\n this.loadCachedMetadata();\n await this.loadTestRunStats();\n this.buildSuiteCards();\n this.buildTestCards();\n this.buildSuiteTree();\n this.computeCounts();\n this.applyFilters();\n }\n\n SelectSidebarItem(selection: SidebarSelection): void {\n this._selectedSidebar$.next(selection);\n }\n\n ToggleStatus(status: string): void {\n const current = new Set(this._statusFilters$.value);\n if (current.has(status)) {\n current.delete(status);\n } else {\n current.add(status);\n }\n this._statusFilters$.next(current);\n }\n\n IsStatusActive(status: string): boolean {\n return this.StatusFilters.has(status);\n }\n\n SetDisplayMode(mode: DisplayMode): void {\n this._displayMode$.next(mode);\n }\n\n SetViewMode(mode: ViewMode): void {\n this._viewMode$.next(mode);\n }\n\n OnSearchInput(event: Event): void {\n const input = event.target as HTMLInputElement;\n this._searchTerm$.next(input.value);\n }\n\n ClearSearch(): void {\n this._searchTerm$.next('');\n }\n\n ToggleSidebar(): void {\n this.IsSidebarCollapsed = !this.IsSidebarCollapsed;\n this.cdr.markForCheck();\n }\n\n ToggleSuiteExpand(node: SuiteTreeNode, event: MouseEvent): void {\n event.stopPropagation();\n node.Expanded = !node.Expanded;\n this.cdr.markForCheck();\n }\n\n ToggleSortDirection(): void {\n const newDir = this.SortDirection === 'asc' ? 'desc' : 'asc';\n this._sortDirection$.next(newDir);\n }\n\n RunTest(testId: string): void {\n this.testingDialogService.OpenTestDialog(testId, this.viewContainerRef);\n }\n\n RunSuite(suiteId: string): void {\n this.testingDialogService.OpenSuiteDialog(suiteId, this.viewContainerRef);\n }\n\n EditItem(entityName: string, id: string): void {\n SharedService.Instance.OpenEntityRecord(entityName, CompositeKey.FromID(id));\n }\n\n ViewTestHistory(testId: string): void {\n SharedService.Instance.OpenEntityRecord('MJ: Tests', CompositeKey.FromID(testId));\n }\n\n ViewSuiteResults(suiteId: string): void {\n SharedService.Instance.OpenEntityRecord('MJ: Test Suites', CompositeKey.FromID(suiteId));\n }\n\n OnNewTest(): void {\n this.OpenSlideout('test');\n }\n\n OnNewSuite(): void {\n this.OpenSlideout('suite');\n }\n\n OpenSlideout(type: 'test' | 'suite'): void {\n this.SlideoutCreateType = type;\n this.resetForm();\n this.SlideoutOpen = true;\n this.cdr.markForCheck();\n }\n\n CloseSlideout(): void {\n this.SlideoutOpen = false;\n this.FormErrorMessage = '';\n this.cdr.markForCheck();\n }\n\n SetSlideoutCreateType(type: 'test' | 'suite'): void {\n this.SlideoutCreateType = type;\n this.resetForm();\n this.cdr.markForCheck();\n }\n\n async SaveForm(): Promise<void> {\n if (!this.IsFormValid || this.IsSaving) return;\n\n this.IsSaving = true;\n this.FormErrorMessage = '';\n this.cdr.markForCheck();\n\n try {\n if (this.SlideoutCreateType === 'test') {\n await this.saveNewTest();\n } else {\n await this.saveNewSuite();\n }\n this.CloseSlideout();\n await TestEngineBase.Instance.Config(true);\n await this.LoadData();\n this.cdr.markForCheck();\n } catch (err) {\n const message = err instanceof Error ? err.message : 'An error occurred while saving.';\n this.FormErrorMessage = message;\n console.error('TestingExplorerComponent: Save failed', err);\n } finally {\n this.IsSaving = false;\n this.cdr.markForCheck();\n }\n }\n\n // ── Resize ──────────────────────────────────────────\n OnResizeStart(event: MouseEvent): void {\n event.preventDefault();\n this.resizeStartX = event.clientX;\n this.resizeStartWidth = this.SlideoutWidth;\n document.addEventListener('mousemove', this.onResizeMove);\n document.addEventListener('mouseup', this.onResizeEnd);\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n }\n\n private onResizeMove = (event: MouseEvent): void => {\n const delta = this.resizeStartX - event.clientX;\n this.SlideoutWidth = Math.max(400, Math.min(900, this.resizeStartWidth + delta));\n this.cdr.detectChanges();\n };\n\n private onResizeEnd = (): void => {\n document.removeEventListener('mousemove', this.onResizeMove);\n document.removeEventListener('mouseup', this.onResizeEnd);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n UserInfoEngine.Instance.SetSettingDebounced(\n TestingExplorerComponent.PANEL_WIDTH_KEY,\n String(this.SlideoutWidth)\n );\n };\n\n GetTestCountForType(typeId: string): number {\n return this.allTests.filter(t => t.TypeID === typeId).length;\n }\n\n // ---------------------------------------------------------------------------\n // Formatting Helpers\n // ---------------------------------------------------------------------------\n\n FormatDuration(ms: number): string {\n if (ms <= 0) return '0s';\n if (ms < 1000) return `${Math.round(ms)}ms`;\n const totalSeconds = Math.floor(ms / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n if (minutes > 0) return `${minutes}m ${seconds}s`;\n return `${seconds}s`;\n }\n\n FormatDurationSeconds(seconds: number): string {\n if (seconds <= 0) return '0s';\n const minutes = Math.floor(seconds / 60);\n const secs = seconds % 60;\n if (minutes > 0) return `${minutes}m ${secs}s`;\n return `${secs}s`;\n }\n\n FormatRelativeTime(date: Date | null): string {\n if (!date) return 'Never';\n const d = date instanceof Date ? date : new Date(date);\n const now = Date.now();\n const diffMs = now - d.getTime();\n const diffMinutes = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMinutes < 1) return 'Just now';\n if (diffMinutes < 60) return `${diffMinutes}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays < 30) return `${diffDays}d ago`;\n return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });\n }\n\n FormatPercent(value: number): string {\n return `${Math.round(value)}%`;\n }\n\n FormatCost(cost: number): string {\n if (cost < 0.01) return '$0.00';\n return `$${cost.toFixed(2)}`;\n }\n\n GetScoreClass(score: number): string {\n if (score >= 0.7) return 'good';\n if (score >= 0.4) return 'warn';\n return 'bad';\n }\n\n GetStatusClass(status: string): string {\n switch (status.toLowerCase()) {\n case 'passed': return 'status-passed';\n case 'failed': return 'status-failed';\n case 'error': return 'status-error';\n case 'running': return 'status-running';\n default: return 'status-default';\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private: Data Loading\n // ---------------------------------------------------------------------------\n\n private loadCachedMetadata(): void {\n const engine = TestEngineBase.Instance;\n this.allTests = engine.Tests;\n this.AllSuites = engine.TestSuites;\n this.allSuiteTests = engine.TestSuiteTests;\n this.AllTestTypes = engine.TestTypes;\n }\n\n private async loadTestRunStats(): Promise<void> {\n const rv = new RunView();\n const result = await rv.RunView<TestRunStatRow>({\n EntityName: 'MJ: Test Runs',\n Fields: ['ID', 'TestID', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt'],\n OrderBy: 'StartedAt DESC',\n MaxRows: 5000,\n ResultType: 'simple'\n });\n\n this.testRunStats = result.Success ? (result.Results || []) : [];\n }\n\n // ---------------------------------------------------------------------------\n // Private: Build Card Data\n // ---------------------------------------------------------------------------\n\n private buildSuiteCards(): void {\n this.suiteCards = this.AllSuites.map(suite => this.buildSingleSuiteCard(suite));\n }\n\n private buildSingleSuiteCard(suite: MJTestSuiteEntity): SuiteCardData {\n const suiteTestLinks = this.allSuiteTests.filter(st => st.SuiteID === suite.ID);\n const testIds = new Set(suiteTestLinks.map(st => st.TestID));\n const runsForSuite = this.testRunStats.filter(r => testIds.has(r.TestID));\n\n const passedRuns = runsForSuite.filter(r => r.Status === 'Passed');\n const passRate = runsForSuite.length > 0 ? (passedRuns.length / runsForSuite.length) * 100 : 0;\n const avgScore = runsForSuite.length > 0\n ? runsForSuite.reduce((s, r) => s + (r.Score || 0), 0) / runsForSuite.length\n : 0;\n const avgDuration = this.computeAvgDuration(runsForSuite);\n const lastRunDate = this.findLastRunDate(runsForSuite);\n const previewTests = this.buildSuiteTestPreviews(suiteTestLinks);\n\n return {\n ID: suite.ID,\n Name: suite.Name,\n Description: suite.Description || '',\n Status: suite.Status,\n TestCount: testIds.size,\n PassRate: passRate,\n AvgScore: avgScore,\n AvgDuration: avgDuration,\n LastRunDate: lastRunDate,\n Tags: this.parseTags(suite.Tags),\n Tests: previewTests,\n TotalTestsInSuite: testIds.size\n };\n }\n\n private buildSuiteTestPreviews(suiteTestLinks: MJTestSuiteTestEntity[]): SuiteTestItem[] {\n return suiteTestLinks\n .sort((a, b) => a.Sequence - b.Sequence)\n .slice(0, 5)\n .map(st => {\n const test = this.allTests.find(t => t.ID === st.TestID);\n const lastRun = this.findLastRunForTest(st.TestID);\n return {\n TestID: st.TestID,\n TestName: test?.Name || st.Test || 'Unknown',\n LastStatus: lastRun?.Status || '',\n LastScore: lastRun?.Score || 0\n };\n });\n }\n\n private buildTestCards(): void {\n this.testCards = this.allTests.map(test => this.buildSingleTestCard(test));\n }\n\n private buildSingleTestCard(test: MJTestEntity): TestCardData {\n const runsForTest = this.testRunStats.filter(r => r.TestID === test.ID);\n const lastRun = runsForTest.length > 0 ? runsForTest[0] : null; // already sorted DESC\n const passedRuns = runsForTest.filter(r => r.Status === 'Passed');\n const passRate = runsForTest.length > 0 ? (passedRuns.length / runsForTest.length) * 100 : 0;\n\n const typeName = this.AllTestTypes.find(t => t.ID === test.TypeID)?.Name || '';\n const suiteName = this.findSuiteNameForTest(test.ID);\n\n return {\n ID: test.ID,\n Name: test.Name,\n Description: test.Description || '',\n Status: test.Status,\n TypeName: typeName,\n SuiteName: suiteName,\n LastRunStatus: lastRun?.Status || '',\n LastScore: lastRun?.Score || 0,\n TotalRuns: runsForTest.length,\n PassRate: passRate,\n EstDuration: test.EstimatedDurationSeconds || 0,\n EstCost: test.EstimatedCostUSD || 0,\n LastRunDate: lastRun ? this.toDate(lastRun.StartedAt) : null,\n Tags: this.parseTags(test.Tags),\n UpdatedAt: test.__mj_UpdatedAt\n };\n }\n\n // ---------------------------------------------------------------------------\n // Private: Build Suite Tree\n // ---------------------------------------------------------------------------\n\n private buildSuiteTree(): void {\n const filteredSuites = this.AllSuites;\n\n const nodeMap = new Map<string, SuiteTreeNode>();\n\n for (const suite of filteredSuites) {\n nodeMap.set(suite.ID, {\n ID: suite.ID,\n Name: suite.Name,\n ParentID: suite.ParentID,\n TestCount: this.allSuiteTests.filter(st => st.SuiteID === suite.ID).length,\n Children: [],\n Expanded: false\n });\n }\n\n const roots: SuiteTreeNode[] = [];\n nodeMap.forEach(node => {\n if (node.ParentID && nodeMap.has(node.ParentID)) {\n nodeMap.get(node.ParentID)!.Children.push(node);\n } else {\n roots.push(node);\n }\n });\n\n this.FilteredSuiteTree = roots;\n this.filterTestTypes();\n }\n\n private filterTestTypes(): void {\n this.FilteredTestTypes = this.AllTestTypes;\n }\n\n // ---------------------------------------------------------------------------\n // Private: Filtering & Sorting\n // ---------------------------------------------------------------------------\n\n private subscribeToStateChanges(): void {\n combineLatest([\n this._searchTerm$,\n this._statusFilters$,\n this._displayMode$,\n this._selectedSidebar$,\n this._sortField$,\n this._sortDirection$,\n this._viewMode$\n ]).pipe(\n takeUntil(this.destroy$)\n ).subscribe(([searchTerm, statusFilters, displayMode, selectedSidebar, sortField, sortDirection, viewMode]) => {\n this.SearchTerm = searchTerm;\n this.StatusFilters = statusFilters;\n this.DisplayMode = displayMode;\n this.SelectedSidebar = selectedSidebar;\n this.SortField = sortField;\n this.SortDirection = sortDirection;\n this.ViewMode = viewMode;\n this.applyFilters();\n this.settingsPersistSubject.next();\n this.cdr.markForCheck();\n });\n }\n\n private applyFilters(): void {\n this.FilteredSuites = this.filterSuiteCards();\n this.FilteredTests = this.filterTestCards();\n this.FilteredResultCount = this.FilteredSuites.length + this.FilteredTests.length;\n }\n\n private filterSuiteCards(): SuiteCardData[] {\n let result = [...this.suiteCards];\n result = this.applySidebarFilterToSuites(result);\n result = this.applySearchFilterToSuites(result);\n result = this.applyStatusFilterToSuites(result);\n result = this.sortSuiteCards(result);\n return result;\n }\n\n private filterTestCards(): TestCardData[] {\n let result = [...this.testCards];\n result = this.applySidebarFilterToTests(result);\n result = this.applySearchFilterToTests(result);\n result = this.applyStatusFilterToTests(result);\n result = this.sortTestCards(result);\n return result;\n }\n\n private applySidebarFilterToSuites(suites: SuiteCardData[]): SuiteCardData[] {\n const sel = this.SelectedSidebar;\n switch (sel.Type) {\n case 'suite':\n return suites.filter(s => s.ID === sel.ID);\n case 'standalone':\n return []; // standalone = tests only\n case 'testType':\n return []; // test types apply to tests only\n default:\n return suites;\n }\n }\n\n private applySidebarFilterToTests(tests: TestCardData[]): TestCardData[] {\n const sel = this.SelectedSidebar;\n switch (sel.Type) {\n case 'suite': {\n const testIds = new Set(\n this.allSuiteTests.filter(st => st.SuiteID === sel.ID).map(st => st.TestID)\n );\n return tests.filter(t => testIds.has(t.ID));\n }\n case 'standalone': {\n const testIdsInSuites = new Set(this.allSuiteTests.map(st => st.TestID));\n return tests.filter(t => !testIdsInSuites.has(t.ID));\n }\n case 'testType':\n return tests.filter(t => {\n const testEntity = this.allTests.find(te => te.ID === t.ID);\n return testEntity?.TypeID === sel.ID;\n });\n default:\n return tests;\n }\n }\n\n private applySearchFilterToSuites(suites: SuiteCardData[]): SuiteCardData[] {\n const term = this.SearchTerm.toLowerCase().trim();\n if (!term) return suites;\n return suites.filter(s =>\n s.Name.toLowerCase().includes(term) ||\n s.Description.toLowerCase().includes(term)\n );\n }\n\n private applySearchFilterToTests(tests: TestCardData[]): TestCardData[] {\n const term = this.SearchTerm.toLowerCase().trim();\n if (!term) return tests;\n return tests.filter(t =>\n t.Name.toLowerCase().includes(term) ||\n t.Description.toLowerCase().includes(term)\n );\n }\n\n private applyStatusFilterToSuites(suites: SuiteCardData[]): SuiteCardData[] {\n if (this.StatusFilters.size === 0) return suites;\n return suites.filter(s => this.StatusFilters.has(s.Status));\n }\n\n private applyStatusFilterToTests(tests: TestCardData[]): TestCardData[] {\n if (this.StatusFilters.size === 0) return tests;\n return tests.filter(t => this.StatusFilters.has(t.Status));\n }\n\n private sortSuiteCards(suites: SuiteCardData[]): SuiteCardData[] {\n const dir = this.SortDirection === 'asc' ? 1 : -1;\n return suites.sort((a, b) => this.compareBySortField(a.Name, a.Status, a.LastRunDate, b.Name, b.Status, b.LastRunDate, dir));\n }\n\n private sortTestCards(tests: TestCardData[]): TestCardData[] {\n const dir = this.SortDirection === 'asc' ? 1 : -1;\n return tests.sort((a, b) => this.compareBySortField(a.Name, a.Status, a.UpdatedAt, b.Name, b.Status, b.UpdatedAt, dir));\n }\n\n private compareBySortField(\n aName: string, aStatus: string, aDate: Date | null,\n bName: string, bStatus: string, bDate: Date | null,\n dir: number\n ): number {\n switch (this.SortField) {\n case 'name':\n return aName.localeCompare(bName) * dir;\n case 'status':\n return aStatus.localeCompare(bStatus) * dir;\n case 'updated': {\n const aTime = aDate ? new Date(aDate).getTime() : 0;\n const bTime = bDate ? new Date(bDate).getTime() : 0;\n return (aTime - bTime) * dir;\n }\n default:\n return 0;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private: Helpers\n // ---------------------------------------------------------------------------\n\n private computeCounts(): void {\n const testIdsInSuites = new Set(this.allSuiteTests.map(st => st.TestID));\n this.StandaloneTestCount = this.allTests.filter(t => !testIdsInSuites.has(t.ID)).length;\n this.TotalItemCount = this.allTests.length + this.AllSuites.length;\n }\n\n private computeAvgDuration(runs: TestRunStatRow[]): number {\n const completed = runs.filter(r => r.CompletedAt != null && r.StartedAt != null);\n if (completed.length === 0) return 0;\n\n const totalMs = completed.reduce((sum, r) => {\n const start = this.toDate(r.StartedAt).getTime();\n const end = this.toDate(r.CompletedAt!).getTime();\n return sum + (end - start);\n }, 0);\n\n return totalMs / completed.length;\n }\n\n private findLastRunDate(runs: TestRunStatRow[]): Date | null {\n if (runs.length === 0) return null;\n return this.toDate(runs[0].StartedAt);\n }\n\n private findLastRunForTest(testId: string): TestRunStatRow | null {\n return this.testRunStats.find(r => r.TestID === testId) || null;\n }\n\n private findSuiteNameForTest(testId: string): string {\n const suiteTest = this.allSuiteTests.find(st => st.TestID === testId);\n if (!suiteTest) return '';\n const suite = this.AllSuites.find(s => s.ID === suiteTest.SuiteID);\n return suite?.Name || suiteTest.Suite || '';\n }\n\n private parseTags(tagsJson: string | null): string[] {\n if (!tagsJson) return [];\n try {\n const parsed = JSON.parse(tagsJson);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n }\n\n private toDate(value: string | Date | null): Date {\n if (!value) return new Date(0);\n return value instanceof Date ? value : new Date(value);\n }\n\n // ---------------------------------------------------------------------------\n // Private: User Settings\n // ---------------------------------------------------------------------------\n\n private loadUserSettings(): void {\n try {\n const widthStr = UserInfoEngine.Instance.GetSetting(TestingExplorerComponent.PANEL_WIDTH_KEY);\n if (widthStr) {\n const width = parseInt(widthStr, 10);\n if (!isNaN(width) && width >= 400 && width <= 900) {\n this.SlideoutWidth = width;\n }\n }\n const stateStr = UserInfoEngine.Instance.GetSetting(TestingExplorerComponent.SEARCH_STATE_KEY);\n if (stateStr) {\n const state = JSON.parse(stateStr) as Record<string, string>;\n if (state.searchTerm) {\n this.SearchTerm = state.searchTerm;\n this._searchTerm$.next(state.searchTerm);\n }\n }\n } catch (error) {\n console.warn('[TestingExplorer] Failed to load user settings:', error);\n } finally {\n this.settingsLoaded = true;\n }\n }\n\n private setupSettingsPersistence(): void {\n this.settingsPersistSubject.pipe(\n debounceTime(500),\n takeUntil(this.destroy$)\n ).subscribe(() => {\n this.persistSearchState();\n });\n }\n\n private persistSearchState(): void {\n if (!this.settingsLoaded) return;\n try {\n const state = { searchTerm: this.SearchTerm };\n UserInfoEngine.Instance.SetSettingDebounced(\n TestingExplorerComponent.SEARCH_STATE_KEY,\n JSON.stringify(state)\n );\n } catch (error) {\n console.warn('[TestingExplorer] Failed to persist search state:', error);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private: Form Management\n // ---------------------------------------------------------------------------\n\n private resetForm(): void {\n this.FormName = '';\n this.FormDescription = '';\n this.FormTypeID = this.AllTestTypes.length > 0 ? this.AllTestTypes[0].ID : '';\n this.FormStatus = 'Active';\n this.FormParentSuiteID = '';\n this.FormEstDuration = 0;\n this.FormEstCost = 0;\n this.FormTags = '';\n this.FormErrorMessage = '';\n }\n\n private async saveNewTest(): Promise<void> {\n const md = new Metadata();\n const test = await md.GetEntityObject<MJTestEntity>('MJ: Tests');\n test.NewRecord();\n test.Name = this.FormName.trim();\n test.Description = this.FormDescription.trim() || null;\n test.TypeID = this.FormTypeID;\n test.Status = this.FormStatus;\n if (this.FormEstDuration > 0) test.EstimatedDurationSeconds = this.FormEstDuration;\n if (this.FormEstCost > 0) test.EstimatedCostUSD = this.FormEstCost;\n if (this.FormTags.trim()) {\n const tags = this.FormTags.split(',').map(t => t.trim()).filter(t => t.length > 0);\n test.Tags = JSON.stringify(tags);\n }\n const saved = await test.Save();\n if (!saved) throw new Error('Failed to save test. Please check your input and try again.');\n }\n\n private async saveNewSuite(): Promise<void> {\n const md = new Metadata();\n const suite = await md.GetEntityObject<MJTestSuiteEntity>('MJ: Test Suites');\n suite.NewRecord();\n suite.Name = this.FormName.trim();\n suite.Description = this.FormDescription.trim() || null;\n suite.Status = this.FormStatus;\n if (this.FormParentSuiteID) suite.ParentID = this.FormParentSuiteID;\n if (this.FormTags.trim()) {\n const tags = this.FormTags.split(',').map(t => t.trim()).filter(t => t.length > 0);\n suite.Tags = JSON.stringify(tags);\n }\n const saved = await suite.Save();\n if (!saved) throw new Error('Failed to save test suite. Please check your input and try again.');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"testing-explorer.component.js","sourceRoot":"","sources":["../../../src/Testing/components/testing-explorer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n OnInit,\n OnDestroy,\n ChangeDetectorRef,\n ChangeDetectionStrategy,\n ViewContainerRef\n} from '@angular/core';\nimport { Subject, BehaviorSubject, combineLatest } from 'rxjs';\nimport { takeUntil, debounceTime } from 'rxjs/operators';\nimport { RunView, CompositeKey, Metadata } from '@memberjunction/core';\nimport { MJTestEntity, MJTestSuiteEntity, MJTestSuiteTestEntity, MJTestTypeEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport { TestingDialogService } from '@memberjunction/ng-testing';\nimport { TestEngineBase } from '@memberjunction/testing-engine-base';\nimport { TestingInstrumentationService } from '../services/testing-instrumentation.service';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n// ---------------------------------------------------------------------------\n// Interfaces\n// ---------------------------------------------------------------------------\n\ninterface SuiteCardData {\n ID: string;\n Name: string;\n Description: string;\n Status: string;\n TestCount: number;\n PassRate: number;\n AvgScore: number;\n AvgDuration: number; // ms\n LastRunDate: Date | null;\n Tags: string[];\n Tests: SuiteTestItem[]; // first 4-5 for preview\n TotalTestsInSuite: number;\n}\n\ninterface SuiteTestItem {\n TestID: string;\n TestName: string;\n LastStatus: string;\n LastScore: number;\n}\n\ninterface TestCardData {\n ID: string;\n Name: string;\n Description: string;\n Status: string;\n TypeName: string;\n SuiteName: string;\n LastRunStatus: string;\n LastScore: number;\n TotalRuns: number;\n PassRate: number;\n EstDuration: number; // seconds\n EstCost: number;\n LastRunDate: Date | null;\n Tags: string[];\n UpdatedAt: Date;\n}\n\ninterface SidebarSelection {\n Type: 'all' | 'standalone' | 'suite' | 'testType';\n ID: string | null;\n}\n\ninterface SuiteTreeNode {\n ID: string;\n Name: string;\n ParentID: string | null;\n TestCount: number;\n Children: SuiteTreeNode[];\n Expanded: boolean;\n}\n\ntype DisplayMode = 'all' | 'suites' | 'tests';\ntype ViewMode = 'card' | 'list';\ntype SortField = 'name' | 'updated' | 'status';\ntype SortDirection = 'asc' | 'desc';\n\n/** Simple result type for test run stats queries */\ninterface TestRunStatRow {\n ID: string;\n TestID: string;\n Status: string;\n Score: number;\n CostUSD: number;\n StartedAt: string | Date;\n CompletedAt: string | Date | null;\n}\n\n@Component({\n standalone: false,\n selector: 'app-testing-explorer',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n @if (IsLoading) {\n <div class=\"explorer-loading\">\n <mj-loading text=\"Loading test explorer...\"></mj-loading>\n </div>\n } @else {\n <div class=\"explorer-layout\">\n <!-- Left Sidebar -->\n <aside class=\"sidebar\" [class.collapsed]=\"IsSidebarCollapsed\">\n <div class=\"sidebar-header\">\n <h3>Explorer</h3>\n <button class=\"sidebar-toggle\" (click)=\"ToggleSidebar()\">\n <i class=\"fa-solid\" [class.fa-chevron-left]=\"!IsSidebarCollapsed\" [class.fa-chevron-right]=\"IsSidebarCollapsed\"></i>\n </button>\n </div>\n\n @if (!IsSidebarCollapsed) {\n <div class=\"sidebar-content\">\n <!-- Browse Section -->\n <div class=\"sidebar-section\">\n <div class=\"sidebar-section-title\">Browse</div>\n <div\n class=\"sidebar-item\"\n [class.active]=\"SelectedSidebar.Type === 'all'\"\n (click)=\"SelectSidebarItem({ Type: 'all', ID: null })\"\n >\n <i class=\"fa-solid fa-layer-group\"></i>\n <span>All Items</span>\n <span class=\"sidebar-count\">{{ TotalItemCount }}</span>\n </div>\n <div\n class=\"sidebar-item\"\n [class.active]=\"SelectedSidebar.Type === 'standalone'\"\n (click)=\"SelectSidebarItem({ Type: 'standalone', ID: null })\"\n >\n <i class=\"fa-solid fa-vial\"></i>\n <span>Standalone Tests</span>\n <span class=\"sidebar-count\">{{ StandaloneTestCount }}</span>\n </div>\n </div>\n\n <!-- Test Suites Section -->\n <div class=\"sidebar-section\">\n <div class=\"sidebar-section-title\">Test Suites</div>\n @for (node of FilteredSuiteTree; track node.ID) {\n <ng-container\n *ngTemplateOutlet=\"suiteTreeTpl; context: { node: node, depth: 0 }\"\n ></ng-container>\n }\n @if (FilteredSuiteTree.length === 0) {\n <div class=\"sidebar-empty\">No suites found</div>\n }\n </div>\n\n <!-- Test Types Section -->\n <div class=\"sidebar-section\">\n <div class=\"sidebar-section-title\">Test Types</div>\n @for (tt of FilteredTestTypes; track tt.ID) {\n <div\n class=\"sidebar-item\"\n [class.active]=\"SelectedSidebar.Type === 'testType' && IsSidebarSelected(tt.ID)\"\n (click)=\"SelectSidebarItem({ Type: 'testType', ID: tt.ID })\"\n >\n <i class=\"fa-solid fa-tag\"></i>\n <span>{{ tt.Name }}</span>\n <span class=\"sidebar-count\">{{ GetTestCountForType(tt.ID) }}</span>\n </div>\n }\n </div>\n </div>\n }\n </aside>\n\n <!-- Main Content -->\n <main class=\"main-content\">\n <!-- Toolbar -->\n <div class=\"toolbar\">\n <div class=\"toolbar-left\">\n <div class=\"toolbar-search-box\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search tests and suites...\"\n [value]=\"SearchTerm\"\n (input)=\"OnSearchInput($event)\"\n />\n @if (SearchTerm) {\n <button class=\"clear-search\" (click)=\"ClearSearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n <div class=\"status-chips\">\n @for (status of StatusOptions; track status) {\n <button\n class=\"chip\"\n [class.active]=\"IsStatusActive(status)\"\n [attr.data-status]=\"status.toLowerCase()\"\n (click)=\"ToggleStatus(status)\"\n >\n {{ status }}\n </button>\n }\n </div>\n </div>\n <div class=\"toolbar-right\">\n <span class=\"result-count\">{{ FilteredResultCount }} results</span>\n <div class=\"view-toggle\">\n <button\n class=\"view-btn\"\n [class.active]=\"ViewMode === 'card'\"\n (click)=\"SetViewMode('card')\"\n title=\"Card View\"\n >\n <i class=\"fa-solid fa-grip\"></i>\n </button>\n <button\n class=\"view-btn\"\n [class.active]=\"ViewMode === 'list'\"\n (click)=\"SetViewMode('list')\"\n title=\"List View\"\n >\n <i class=\"fa-solid fa-list\"></i>\n </button>\n </div>\n <button class=\"btn btn-secondary\" (click)=\"OnNewSuite()\">\n <i class=\"fa-solid fa-folder-plus\"></i>\n New Suite\n </button>\n <button class=\"btn btn-primary\" (click)=\"OnNewTest()\">\n <i class=\"fa-solid fa-plus\"></i>\n New Test\n </button>\n </div>\n </div>\n\n <!-- Toggle Bar -->\n <div class=\"toggle-bar\">\n <div class=\"toggle-group\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"DisplayMode === 'all'\"\n (click)=\"SetDisplayMode('all')\"\n >All</button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"DisplayMode === 'suites'\"\n (click)=\"SetDisplayMode('suites')\"\n >Suites Only</button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"DisplayMode === 'tests'\"\n (click)=\"SetDisplayMode('tests')\"\n >Tests Only</button>\n </div>\n <div class=\"sort-indicator\">\n <button class=\"sort-btn\" (click)=\"ToggleSortDirection()\">\n <i class=\"fa-solid fa-arrow-down-short-wide\"></i>\n {{ SortFieldLabel }}\n <i class=\"fa-solid\" [class.fa-arrow-up]=\"SortDirection === 'asc'\" [class.fa-arrow-down]=\"SortDirection === 'desc'\"></i>\n </button>\n </div>\n </div>\n\n <!-- Content Area -->\n <div class=\"content-area\">\n <!-- Suites Section -->\n @if (DisplayMode === 'all' || DisplayMode === 'suites') {\n @if (FilteredSuites.length > 0) {\n <div class=\"content-section\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-folder\"></i>\n Test Suites\n <span class=\"section-count\">{{ FilteredSuites.length }}</span>\n </h3>\n <div class=\"card-grid\">\n @for (suite of FilteredSuites; track suite.ID) {\n <div class=\"suite-card\">\n <div class=\"card-header\">\n <div class=\"card-title-row\">\n <i class=\"fa-solid fa-folder-open card-icon suite-icon\"></i>\n <span class=\"card-name\" [innerHTML]=\"suite.Name | highlightSearch:SearchTerm\"></span>\n <span class=\"status-badge\" [attr.data-status]=\"suite.Status.toLowerCase()\">{{ suite.Status }}</span>\n </div>\n <div class=\"card-subtitle\">\n {{ suite.TestCount }} tests\n @if (suite.LastRunDate) {\n <span class=\"dot-sep\"></span>\n Last run {{ FormatRelativeTime(suite.LastRunDate) }}\n }\n </div>\n @if (suite.Description) {\n <p class=\"card-description\" [innerHTML]=\"suite.Description | highlightSearch:SearchTerm\"></p>\n }\n </div>\n\n <div class=\"card-stats\">\n <div class=\"stat\">\n <span class=\"stat-label\">Pass Rate</span>\n <span class=\"stat-value\" [class]=\"GetScoreClass(suite.PassRate / 100)\">{{ FormatPercent(suite.PassRate) }}</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Tests</span>\n <span class=\"stat-value\">{{ suite.TestCount }}</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Avg Score</span>\n <span class=\"stat-value\" [class]=\"GetScoreClass(suite.AvgScore)\">{{ (suite.AvgScore * 100).toFixed(0) }}%</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Avg Duration</span>\n <span class=\"stat-value\">{{ FormatDuration(suite.AvgDuration) }}</span>\n </div>\n </div>\n\n @if (suite.Tests.length > 0) {\n <div class=\"card-tests-preview\">\n @for (t of suite.Tests; track t.TestID; let i = $index) {\n @if (i < 4) {\n <div class=\"preview-test-row\">\n <span class=\"preview-dot\" [attr.data-status]=\"t.LastStatus.toLowerCase()\"></span>\n <span class=\"preview-test-name\">{{ t.TestName }}</span>\n <span class=\"preview-score\" [class]=\"GetScoreClass(t.LastScore)\">{{ (t.LastScore * 100).toFixed(0) }}%</span>\n <span class=\"preview-bar\">\n <span class=\"preview-bar-fill\" [style.width.%]=\"t.LastScore * 100\" [class]=\"GetScoreClass(t.LastScore) + '-bg'\"></span>\n </span>\n <span class=\"preview-status\" [attr.data-status]=\"t.LastStatus.toLowerCase()\">{{ t.LastStatus }}</span>\n </div>\n }\n }\n @if (suite.TotalTestsInSuite > 4) {\n <div class=\"preview-more\">+{{ suite.TotalTestsInSuite - 4 }} more tests</div>\n }\n </div>\n }\n\n <div class=\"card-actions\">\n <button class=\"btn btn-sm btn-primary\" (click)=\"RunSuite(suite.ID)\">\n <i class=\"fa-solid fa-play\"></i> Run Suite\n </button>\n <button class=\"btn btn-sm btn-secondary\" (click)=\"ViewSuiteResults(suite.ID)\">\n <i class=\"fa-solid fa-chart-bar\"></i> Results\n </button>\n <button class=\"btn btn-sm btn-secondary\" (click)=\"EditItem('MJ: Test Suites', suite.ID)\">\n <i class=\"fa-solid fa-pen\"></i> Edit\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n }\n }\n\n <!-- Tests Section -->\n @if (DisplayMode === 'all' || DisplayMode === 'tests') {\n @if (FilteredTests.length > 0) {\n <div class=\"content-section\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-vial\"></i>\n Tests\n <span class=\"section-count\">{{ FilteredTests.length }}</span>\n </h3>\n <div class=\"card-grid\">\n @for (test of FilteredTests; track test.ID) {\n <div class=\"test-card\">\n <div class=\"card-header\">\n <div class=\"card-title-row\">\n <i class=\"fa-solid fa-vial card-icon test-icon\"></i>\n <span class=\"card-name\" [innerHTML]=\"test.Name | highlightSearch:SearchTerm\"></span>\n <span class=\"status-badge\" [attr.data-status]=\"test.Status.toLowerCase()\">{{ test.Status }}</span>\n </div>\n <div class=\"card-subtitle\">\n {{ test.TypeName }}\n @if (test.SuiteName) {\n <span class=\"dot-sep\"></span>\n {{ test.SuiteName }}\n }\n </div>\n @if (test.Description) {\n <p class=\"card-description\" [innerHTML]=\"test.Description | highlightSearch:SearchTerm\"></p>\n }\n <div class=\"card-meta-row\">\n @if (test.TypeName) {\n <span class=\"meta-item\"><i class=\"fa-solid fa-robot\"></i> {{ test.TypeName }}</span>\n }\n @if (test.EstDuration > 0) {\n <span class=\"meta-item\"><i class=\"fa-solid fa-clock\"></i> ~{{ FormatDurationSeconds(test.EstDuration) }}</span>\n }\n @if (test.EstCost > 0) {\n <span class=\"meta-item\"><i class=\"fa-solid fa-dollar-sign\"></i> {{ FormatCost(test.EstCost) }}</span>\n }\n <span class=\"meta-item\"><i class=\"fa-solid fa-calendar\"></i> {{ FormatRelativeTime(test.UpdatedAt) }}</span>\n </div>\n @if (test.Tags.length > 0) {\n <div class=\"card-tags\">\n @for (tag of test.Tags; track tag; let i = $index) {\n @if (i < 4) {\n <span class=\"tag\">{{ tag }}</span>\n }\n }\n @if (test.Tags.length > 4) {\n <span class=\"tag tag-more\">+{{ test.Tags.length - 4 }}</span>\n }\n </div>\n }\n </div>\n\n <div class=\"card-stats\">\n <div class=\"stat\">\n <span class=\"stat-label\">Last Status</span>\n <span class=\"stat-value status-text\" [attr.data-status]=\"test.LastRunStatus.toLowerCase()\">{{ test.LastRunStatus || 'N/A' }}</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Score</span>\n <span class=\"stat-value\" [class]=\"GetScoreClass(test.LastScore)\">{{ test.LastScore > 0 ? (test.LastScore * 100).toFixed(0) + '%' : 'N/A' }}</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Total Runs</span>\n <span class=\"stat-value\">{{ test.TotalRuns }}</span>\n </div>\n <div class=\"stat\">\n <span class=\"stat-label\">Pass Rate</span>\n <span class=\"stat-value\" [class]=\"GetScoreClass(test.PassRate / 100)\">{{ test.TotalRuns > 0 ? FormatPercent(test.PassRate) : 'N/A' }}</span>\n </div>\n </div>\n\n <div class=\"card-actions\">\n <button class=\"btn btn-sm btn-primary\" (click)=\"RunTest(test.ID)\">\n <i class=\"fa-solid fa-play\"></i> Run\n </button>\n <button class=\"btn btn-sm btn-secondary\" (click)=\"ViewTestHistory(test.ID)\">\n <i class=\"fa-solid fa-history\"></i> History\n </button>\n <button class=\"btn btn-sm btn-secondary\" (click)=\"EditItem('MJ: Tests', test.ID)\">\n <i class=\"fa-solid fa-pen\"></i> Edit\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n }\n }\n\n <!-- Empty State -->\n @if (FilteredSuites.length === 0 && FilteredTests.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <p>No tests or suites found</p>\n <span class=\"empty-hint\">Try adjusting your search or filters.</span>\n </div>\n }\n </div>\n </main>\n </div>\n }\n\n <!-- Template for recursive suite tree rendering -->\n <ng-template #suiteTreeTpl let-node=\"node\" let-depth=\"depth\">\n <div\n class=\"sidebar-item suite-tree-item\"\n [style.paddingLeft.px]=\"16 + depth * 14\"\n [class.active]=\"SelectedSidebar.Type === 'suite' && IsSidebarSelected(node.ID)\"\n (click)=\"SelectSidebarItem({ Type: 'suite', ID: node.ID })\"\n >\n @if (node.Children.length > 0) {\n <button class=\"tree-toggle\" (click)=\"ToggleSuiteExpand(node, $event)\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"!node.Expanded\" [class.fa-chevron-down]=\"node.Expanded\"></i>\n </button>\n }\n <i class=\"fa-solid fa-folder\"></i>\n <span class=\"tree-name\">{{ node.Name }}</span>\n <span class=\"sidebar-count\">{{ node.TestCount }}</span>\n </div>\n @if (node.Expanded && node.Children.length > 0) {\n @for (child of node.Children; track child.ID) {\n <ng-container\n *ngTemplateOutlet=\"suiteTreeTpl; context: { node: child, depth: depth + 1 }\"\n ></ng-container>\n }\n }\n </ng-template>\n\n <!-- Slideout Backdrop -->\n @if (SlideoutOpen) {\n <div class=\"slideout-backdrop\" (click)=\"CloseSlideout()\"></div>\n }\n\n <!-- Slideout Panel -->\n <div class=\"slideout-panel\" [class.open]=\"SlideoutOpen\" [style.width.px]=\"SlideoutWidth\">\n <div class=\"slideout-resize-handle\" (mousedown)=\"OnResizeStart($event)\"></div>\n\n @if (SlideoutOpen) {\n <div class=\"slideout-container\">\n <!-- Slideout Header -->\n <div class=\"slideout-header\">\n <div class=\"slideout-title-row\">\n <i class=\"fa-solid fa-plus-circle slideout-title-icon\"></i>\n <span class=\"slideout-title-text\">\n Create {{ SlideoutCreateType === 'test' ? 'Test' : 'Test Suite' }}\n </span>\n </div>\n <button class=\"slideout-close-btn\" (click)=\"CloseSlideout()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <!-- Type Toggle -->\n <div class=\"slideout-type-toggle\">\n <button\n class=\"type-toggle-btn\"\n [class.active]=\"SlideoutCreateType === 'test'\"\n (click)=\"SetSlideoutCreateType('test')\"\n >\n <i class=\"fa-solid fa-vial\"></i> Test\n </button>\n <button\n class=\"type-toggle-btn\"\n [class.active]=\"SlideoutCreateType === 'suite'\"\n (click)=\"SetSlideoutCreateType('suite')\"\n >\n <i class=\"fa-solid fa-folder\"></i> Suite\n </button>\n </div>\n\n <!-- Error Banner -->\n @if (FormErrorMessage) {\n <div class=\"slideout-error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n <span>{{ FormErrorMessage }}</span>\n </div>\n }\n\n <!-- Slideout Body -->\n <div class=\"slideout-body\">\n <div class=\"form-section\">\n <div class=\"form-section-title\">General</div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Name <span class=\"form-required\">*</span></label>\n <input\n class=\"form-input\"\n type=\"text\"\n [(ngModel)]=\"FormName\"\n [placeholder]=\"SlideoutCreateType === 'test' ? 'e.g., Agent Response Quality Test' : 'e.g., Core Agent Test Suite'\"\n />\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Description</label>\n <textarea\n class=\"form-textarea\"\n [(ngModel)]=\"FormDescription\"\n rows=\"3\"\n [placeholder]=\"SlideoutCreateType === 'test' ? 'What does this test evaluate?' : 'What does this suite contain?'\"\n ></textarea>\n </div>\n\n <div class=\"form-row\">\n @if (SlideoutCreateType === 'test') {\n <div class=\"form-group\">\n <label class=\"form-label\">Test Type <span class=\"form-required\">*</span></label>\n <select class=\"form-input\" [(ngModel)]=\"FormTypeID\">\n <option value=\"\" disabled>Select type...</option>\n @for (tt of AllTestTypes; track tt.ID) {\n <option [value]=\"tt.ID\">{{ tt.Name }}</option>\n }\n </select>\n </div>\n }\n @if (SlideoutCreateType === 'suite') {\n <div class=\"form-group\">\n <label class=\"form-label\">Parent Suite</label>\n <select class=\"form-input\" [(ngModel)]=\"FormParentSuiteID\">\n <option value=\"\">None (top-level)</option>\n @for (s of AllSuites; track s.ID) {\n <option [value]=\"s.ID\">{{ s.Name }}</option>\n }\n </select>\n </div>\n }\n <div class=\"form-group\">\n <label class=\"form-label\">Status</label>\n <select class=\"form-input\" [(ngModel)]=\"FormStatus\">\n @for (status of FormStatusOptions; track status) {\n <option [value]=\"status\">{{ status }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n\n @if (SlideoutCreateType === 'test') {\n <div class=\"form-section\">\n <div class=\"form-section-title\">Estimates</div>\n <div class=\"form-row\">\n <div class=\"form-group\">\n <label class=\"form-label\">Duration (seconds)</label>\n <input\n class=\"form-input\"\n type=\"number\"\n [(ngModel)]=\"FormEstDuration\"\n min=\"0\"\n placeholder=\"0\"\n />\n </div>\n <div class=\"form-group\">\n <label class=\"form-label\">Cost (USD)</label>\n <input\n class=\"form-input\"\n type=\"number\"\n [(ngModel)]=\"FormEstCost\"\n min=\"0\"\n step=\"0.01\"\n placeholder=\"0.00\"\n />\n </div>\n </div>\n </div>\n }\n\n <div class=\"form-section\">\n <div class=\"form-section-title\">Tags</div>\n <div class=\"form-group\">\n <input\n class=\"form-input\"\n type=\"text\"\n [(ngModel)]=\"FormTags\"\n placeholder=\"Comma-separated tags, e.g., agent, quality, v2\"\n />\n <span class=\"form-hint\">Separate multiple tags with commas</span>\n </div>\n </div>\n </div>\n\n <!-- Slideout Footer -->\n <div class=\"slideout-footer\">\n <button class=\"btn btn-secondary\" (click)=\"CloseSlideout()\">Cancel</button>\n <button class=\"btn btn-primary\" (click)=\"SaveForm()\" [disabled]=\"!IsFormValid || IsSaving\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-check\"></i>\n }\n Create {{ SlideoutCreateType === 'test' ? 'Test' : 'Suite' }}\n </button>\n </div>\n </div>\n }\n </div>\n `,\n styles: [`\n /* ==========================================\n Testing Explorer Component\n ========================================== */\n\n :host {\n display: block;\n height: 100%;\n width: 100%;\n }\n\n /* Loading */\n .explorer-loading {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n min-height: 400px;\n background: #f5f6fa;\n }\n\n /* Layout */\n .explorer-layout {\n display: flex;\n height: 100%;\n background: #f5f6fa;\n overflow: hidden;\n }\n\n /* ==========================================\n Sidebar\n ========================================== */\n .sidebar {\n width: 280px;\n min-width: 280px;\n background: #fff;\n border-right: 1px solid #e8ecef;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transition: width 0.2s ease, min-width 0.2s ease;\n }\n\n .sidebar.collapsed {\n width: 48px;\n min-width: 48px;\n }\n\n .sidebar-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px;\n border-bottom: 1px solid #e8ecef;\n }\n\n .sidebar-header h3 {\n margin: 0;\n font-size: 15px;\n font-weight: 700;\n color: #2d3436;\n }\n\n .sidebar.collapsed .sidebar-header h3 {\n display: none;\n }\n\n .sidebar-toggle {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n color: #636e72;\n cursor: pointer;\n font-size: 11px;\n transition: all 0.15s ease;\n }\n\n .sidebar-toggle:hover {\n background: #f5f6fa;\n color: #2d3436;\n }\n\n .sidebar-content {\n flex: 1;\n overflow-y: auto;\n padding: 8px 0;\n }\n\n .sidebar-section {\n margin-bottom: 8px;\n }\n\n .sidebar-section-title {\n padding: 8px 16px 4px;\n font-size: 10px;\n font-weight: 700;\n color: #b2bec3;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n }\n\n .sidebar-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n font-size: 13px;\n color: #636e72;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n overflow: hidden;\n }\n\n .sidebar-item:hover {\n background: #f5f6fa;\n color: #2d3436;\n }\n\n .sidebar-item.active {\n background: #e0f2f1;\n color: #00897b;\n font-weight: 600;\n }\n\n .sidebar-item i {\n font-size: 12px;\n width: 16px;\n text-align: center;\n flex-shrink: 0;\n }\n\n .sidebar-item span:not(.sidebar-count) {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sidebar-count {\n font-size: 11px;\n color: #b2bec3;\n font-weight: 500;\n flex-shrink: 0;\n }\n\n .sidebar-item.active .sidebar-count {\n color: #00897b;\n }\n\n .sidebar-empty {\n padding: 8px 16px;\n font-size: 12px;\n color: #b2bec3;\n font-style: italic;\n }\n\n /* Tree nodes */\n .suite-tree-item {\n gap: 6px;\n }\n\n .tree-toggle {\n width: 18px;\n height: 18px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n color: #b2bec3;\n cursor: pointer;\n font-size: 9px;\n flex-shrink: 0;\n border-radius: 4px;\n padding: 0;\n }\n\n .tree-toggle:hover {\n background: #e8ecef;\n color: #636e72;\n }\n\n .tree-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n /* ==========================================\n Main Content\n ========================================== */\n .main-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n /* Toolbar */\n .toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n padding: 16px 24px;\n background: #fff;\n border-bottom: 1px solid #e8ecef;\n flex-shrink: 0;\n }\n\n .toolbar-left {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n }\n\n .toolbar-search-box {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n background: #f5f6fa;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n min-width: 240px;\n max-width: 360px;\n flex: 1;\n transition: border-color 0.2s ease;\n }\n\n .toolbar-search-box:focus-within {\n border-color: #00897b;\n background: #fff;\n }\n\n .toolbar-search-box i {\n color: #b2bec3;\n font-size: 13px;\n }\n\n .toolbar-search-box input {\n flex: 1;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: #2d3436;\n }\n\n .toolbar-search-box input::placeholder {\n color: #b2bec3;\n }\n\n .clear-search {\n border: none;\n background: transparent;\n color: #b2bec3;\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 4px;\n }\n\n .clear-search:hover {\n color: #636e72;\n background: #e8ecef;\n }\n\n .status-chips {\n display: flex;\n gap: 6px;\n }\n\n .chip {\n display: inline-flex;\n align-items: center;\n padding: 6px 14px;\n background: #f5f6fa;\n border: 1px solid transparent;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 600;\n color: #636e72;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n\n .chip:hover {\n background: #e8ecef;\n }\n\n .chip.active {\n color: #fff;\n }\n\n .chip.active[data-status=\"active\"] {\n background: #2e7d32;\n border-color: #2e7d32;\n }\n\n .chip.active[data-status=\"pending\"] {\n background: #e65100;\n border-color: #e65100;\n }\n\n .chip.active[data-status=\"disabled\"] {\n background: #636e72;\n border-color: #636e72;\n }\n\n .toolbar-right {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n }\n\n .result-count {\n font-size: 12px;\n color: #b2bec3;\n font-weight: 500;\n white-space: nowrap;\n }\n\n .view-toggle {\n display: flex;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n overflow: hidden;\n }\n\n .view-btn {\n width: 34px;\n height: 34px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #fff;\n border: none;\n color: #b2bec3;\n cursor: pointer;\n font-size: 13px;\n transition: all 0.15s ease;\n }\n\n .view-btn:not(:last-child) {\n border-right: 1px solid #e8ecef;\n }\n\n .view-btn:hover {\n background: #f5f6fa;\n color: #636e72;\n }\n\n .view-btn.active {\n background: #00897b;\n color: #fff;\n }\n\n /* Buttons */\n .btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 9px 16px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n\n .btn-primary {\n background: #00897b;\n color: #fff;\n }\n\n .btn-primary:hover {\n background: #00796b;\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 137, 123, 0.3);\n }\n\n .btn-secondary {\n background: #fff;\n color: #636e72;\n border: 1px solid #e8ecef;\n }\n\n .btn-secondary:hover {\n background: #f5f6fa;\n }\n\n .btn-sm {\n padding: 6px 12px;\n font-size: 12px;\n }\n\n /* Toggle Bar */\n .toggle-bar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 24px;\n background: #fafafa;\n border-bottom: 1px solid #e8ecef;\n flex-shrink: 0;\n }\n\n .toggle-group {\n display: flex;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n overflow: hidden;\n }\n\n .toggle-btn {\n padding: 6px 16px;\n background: #fff;\n border: none;\n font-size: 12px;\n font-weight: 600;\n color: #636e72;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n\n .toggle-btn:not(:last-child) {\n border-right: 1px solid #e8ecef;\n }\n\n .toggle-btn.active {\n background: #00897b;\n color: #fff;\n }\n\n .toggle-btn:hover:not(.active) {\n background: #f5f6fa;\n }\n\n .sort-indicator {\n display: flex;\n align-items: center;\n }\n\n .sort-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n color: #636e72;\n cursor: pointer;\n }\n\n .sort-btn:hover {\n background: #f5f6fa;\n }\n\n .sort-btn i {\n font-size: 11px;\n }\n\n /* Content Area */\n .content-area {\n flex: 1;\n overflow-y: auto;\n padding: 24px;\n }\n\n .content-section {\n margin-bottom: 32px;\n }\n\n .section-title {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 700;\n color: #2d3436;\n }\n\n .section-title i {\n color: #00897b;\n font-size: 14px;\n }\n\n .section-count {\n font-size: 12px;\n font-weight: 600;\n color: #b2bec3;\n background: #f5f6fa;\n padding: 2px 8px;\n border-radius: 10px;\n }\n\n /* Card Grid */\n .card-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));\n gap: 16px;\n }\n\n /* Suite Card */\n .suite-card,\n .test-card {\n background: #fff;\n border: 1px solid #e8ecef;\n border-radius: 10px;\n overflow: hidden;\n transition: all 0.2s ease;\n }\n\n .suite-card:hover,\n .test-card:hover {\n border-color: #b2dfdb;\n box-shadow: 0 4px 16px rgba(0, 137, 123, 0.1);\n }\n\n .card-header {\n padding: 16px 16px 12px;\n }\n\n .card-title-row {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n }\n\n .card-icon {\n font-size: 14px;\n flex-shrink: 0;\n }\n\n .suite-icon {\n color: #00897b;\n }\n\n .test-icon {\n color: #6366f1;\n }\n\n .card-name {\n flex: 1;\n font-size: 14px;\n font-weight: 700;\n color: #2d3436;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .status-badge {\n font-size: 10px;\n font-weight: 700;\n padding: 3px 8px;\n border-radius: 4px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n flex-shrink: 0;\n }\n\n .status-badge[data-status=\"active\"] {\n background: #e8f5e9;\n color: #2e7d32;\n }\n\n .status-badge[data-status=\"pending\"] {\n background: #fff3e0;\n color: #e65100;\n }\n\n .status-badge[data-status=\"disabled\"] {\n background: #f5f6fa;\n color: #636e72;\n }\n\n .card-subtitle {\n font-size: 12px;\n color: #636e72;\n margin-bottom: 6px;\n }\n\n .dot-sep {\n display: inline-block;\n width: 3px;\n height: 3px;\n background: #b2bec3;\n border-radius: 50%;\n vertical-align: middle;\n margin: 0 6px;\n }\n\n .card-description {\n margin: 0;\n font-size: 12px;\n color: #636e72;\n line-height: 1.5;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .card-meta-row {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n margin-top: 8px;\n }\n\n .meta-item {\n font-size: 11px;\n color: #636e72;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .meta-item i {\n font-size: 10px;\n color: #b2bec3;\n }\n\n .card-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-top: 8px;\n }\n\n .tag {\n font-size: 10px;\n font-weight: 600;\n padding: 2px 8px;\n background: #f5f6fa;\n color: #636e72;\n border-radius: 4px;\n }\n\n .tag-more {\n background: #e8ecef;\n color: #b2bec3;\n }\n\n /* Card Stats */\n .card-stats {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 1px;\n background: #e8ecef;\n border-top: 1px solid #e8ecef;\n }\n\n .stat {\n background: #fafafa;\n padding: 10px 12px;\n text-align: center;\n }\n\n .stat-label {\n display: block;\n font-size: 10px;\n font-weight: 600;\n color: #b2bec3;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n margin-bottom: 2px;\n }\n\n .stat-value {\n font-size: 14px;\n font-weight: 700;\n color: #2d3436;\n }\n\n .stat-value.good { color: #2e7d32; }\n .stat-value.warn { color: #e65100; }\n .stat-value.bad { color: #c62828; }\n\n .status-text[data-status=\"passed\"] { color: #2e7d32; }\n .status-text[data-status=\"failed\"] { color: #c62828; }\n .status-text[data-status=\"error\"] { color: #e65100; }\n .status-text[data-status=\"running\"] { color: #1565c0; }\n .status-text[data-status=\"pending\"] { color: #e65100; }\n .status-text[data-status=\"skipped\"] { color: #636e72; }\n\n /* Suite Tests Preview */\n .card-tests-preview {\n padding: 10px 16px;\n border-top: 1px solid #e8ecef;\n }\n\n .preview-test-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n font-size: 12px;\n }\n\n .preview-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .preview-dot[data-status=\"passed\"] { background: #2e7d32; }\n .preview-dot[data-status=\"failed\"] { background: #c62828; }\n .preview-dot[data-status=\"error\"] { background: #e65100; }\n .preview-dot[data-status=\"running\"] { background: #1565c0; }\n .preview-dot[data-status=\"\"] { background: #b2bec3; }\n\n .preview-test-name {\n flex: 1;\n color: #2d3436;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .preview-score {\n font-weight: 600;\n font-size: 11px;\n min-width: 32px;\n text-align: right;\n }\n\n .preview-score.good { color: #2e7d32; }\n .preview-score.warn { color: #e65100; }\n .preview-score.bad { color: #c62828; }\n\n .preview-bar {\n width: 48px;\n height: 4px;\n background: #e8ecef;\n border-radius: 2px;\n overflow: hidden;\n flex-shrink: 0;\n }\n\n .preview-bar-fill {\n height: 100%;\n border-radius: 2px;\n transition: width 0.3s ease;\n }\n\n .good-bg { background: #2e7d32; }\n .warn-bg { background: #e65100; }\n .bad-bg { background: #c62828; }\n\n .preview-status {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n min-width: 44px;\n text-align: right;\n }\n\n .preview-status[data-status=\"passed\"] { color: #2e7d32; }\n .preview-status[data-status=\"failed\"] { color: #c62828; }\n .preview-status[data-status=\"error\"] { color: #e65100; }\n .preview-status[data-status=\"\"] { color: #b2bec3; }\n\n .preview-more {\n padding: 4px 0 0;\n font-size: 11px;\n color: #b2bec3;\n font-style: italic;\n }\n\n /* Card Actions */\n .card-actions {\n display: flex;\n gap: 8px;\n padding: 12px 16px;\n border-top: 1px solid #e8ecef;\n background: #fafafa;\n }\n\n /* Empty State */\n .empty-state {\n padding: 80px 40px;\n text-align: center;\n }\n\n .empty-state i {\n font-size: 48px;\n color: #b2bec3;\n margin-bottom: 16px;\n }\n\n .empty-state p {\n font-size: 16px;\n color: #636e72;\n margin: 0 0 8px 0;\n }\n\n .empty-hint {\n font-size: 13px;\n color: #b2bec3;\n }\n\n /* ==========================================\n Slideout Panel\n ========================================== */\n .slideout-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 999;\n animation: fadeInBackdrop 0.2s ease;\n }\n\n @keyframes fadeInBackdrop {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n .slideout-panel {\n position: fixed;\n top: 0;\n right: -100%;\n height: 100vh;\n background: #fff;\n box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .slideout-panel.open {\n right: 0;\n }\n\n .slideout-resize-handle {\n position: absolute;\n top: 0;\n left: 0;\n width: 5px;\n height: 100%;\n cursor: col-resize;\n background: transparent;\n z-index: 10;\n transition: background 0.2s;\n }\n\n .slideout-resize-handle:hover {\n background: rgba(0, 137, 123, 0.3);\n }\n\n .slideout-resize-handle:active {\n background: rgba(0, 137, 123, 0.5);\n }\n\n .slideout-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n }\n\n .slideout-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n border-bottom: 1px solid #e8ecef;\n flex-shrink: 0;\n }\n\n .slideout-title-row {\n display: flex;\n align-items: center;\n gap: 10px;\n }\n\n .slideout-title-icon {\n font-size: 18px;\n color: #00897b;\n }\n\n .slideout-title-text {\n font-size: 18px;\n font-weight: 700;\n color: #2d3436;\n }\n\n .slideout-close-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid #e8ecef;\n border-radius: 6px;\n color: #636e72;\n cursor: pointer;\n font-size: 14px;\n transition: all 0.15s ease;\n }\n\n .slideout-close-btn:hover {\n background: #f5f6fa;\n color: #2d3436;\n border-color: #ccc;\n }\n\n /* Type Toggle */\n .slideout-type-toggle {\n display: flex;\n gap: 0;\n padding: 16px 24px;\n border-bottom: 1px solid #e8ecef;\n flex-shrink: 0;\n }\n\n .type-toggle-btn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px 16px;\n background: #f5f6fa;\n border: 1px solid #e8ecef;\n font-size: 13px;\n font-weight: 600;\n color: #636e72;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n\n .type-toggle-btn:first-child {\n border-radius: 8px 0 0 8px;\n border-right: none;\n }\n\n .type-toggle-btn:last-child {\n border-radius: 0 8px 8px 0;\n }\n\n .type-toggle-btn.active {\n background: #00897b;\n border-color: #00897b;\n color: #fff;\n }\n\n .type-toggle-btn:hover:not(.active) {\n background: #e8ecef;\n }\n\n /* Error Banner */\n .slideout-error {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 16px 24px 0;\n padding: 12px 16px;\n background: #fff5f5;\n border: 1px solid #fed7d7;\n border-radius: 8px;\n color: #c53030;\n font-size: 13px;\n flex-shrink: 0;\n }\n\n .slideout-error i {\n font-size: 14px;\n flex-shrink: 0;\n }\n\n /* Slideout Body */\n .slideout-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px 24px;\n }\n\n .form-section {\n margin-bottom: 24px;\n }\n\n .form-section-title {\n font-size: 12px;\n font-weight: 700;\n color: #b2bec3;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n margin-bottom: 14px;\n padding-bottom: 8px;\n border-bottom: 1px solid #f0f0f0;\n }\n\n .form-group {\n margin-bottom: 16px;\n }\n\n .form-label {\n display: block;\n font-size: 13px;\n font-weight: 600;\n color: #2d3436;\n margin-bottom: 6px;\n }\n\n .form-required {\n color: #e53e3e;\n }\n\n .form-input,\n .form-textarea {\n width: 100%;\n padding: 10px 14px;\n background: #fff;\n border: 1px solid #e8ecef;\n border-radius: 8px;\n font-size: 13px;\n color: #2d3436;\n transition: border-color 0.2s ease;\n outline: none;\n box-sizing: border-box;\n font-family: inherit;\n }\n\n .form-input:focus,\n .form-textarea:focus {\n border-color: #00897b;\n box-shadow: 0 0 0 3px rgba(0, 137, 123, 0.1);\n }\n\n .form-input::placeholder,\n .form-textarea::placeholder {\n color: #b2bec3;\n }\n\n .form-textarea {\n resize: vertical;\n min-height: 80px;\n }\n\n .form-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n }\n\n .form-hint {\n display: block;\n font-size: 11px;\n color: #b2bec3;\n margin-top: 4px;\n }\n\n /* Slideout Footer */\n .slideout-footer {\n display: flex;\n justify-content: flex-end;\n gap: 10px;\n padding: 16px 24px;\n border-top: 1px solid #e8ecef;\n background: #fafafa;\n flex-shrink: 0;\n }\n\n .slideout-footer .btn {\n min-width: 100px;\n justify-content: center;\n }\n\n .slideout-footer .btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n box-shadow: none;\n }\n\n /* Search Highlight */\n ::ng-deep mark.search-highlight {\n background: #fff9c4;\n color: inherit;\n padding: 1px 2px;\n border-radius: 2px;\n font-weight: 700;\n }\n\n /* ==========================================\n Responsive\n ========================================== */\n @media (max-width: 1200px) {\n .card-grid {\n grid-template-columns: 1fr;\n }\n }\n\n @media (max-width: 900px) {\n .sidebar {\n display: none;\n }\n\n .toolbar {\n flex-direction: column;\n align-items: stretch;\n }\n\n .toolbar-left, .toolbar-right {\n flex-wrap: wrap;\n justify-content: center;\n }\n }\n\n @media (max-width: 600px) {\n .content-area {\n padding: 16px;\n }\n\n .card-stats {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .slideout-panel {\n width: 100% !important;\n }\n\n .slideout-resize-handle {\n display: none;\n }\n\n .form-row {\n grid-template-columns: 1fr;\n }\n }\n `]\n})\nexport class TestingExplorerComponent implements OnInit, OnDestroy {\n\n private destroy$ = new Subject<void>();\n\n // Raw cached data\n private allTests: MJTestEntity[] = [];\n AllSuites: MJTestSuiteEntity[] = [];\n private allSuiteTests: MJTestSuiteTestEntity[] = [];\n AllTestTypes: MJTestTypeEntity[] = [];\n private testRunStats: TestRunStatRow[] = [];\n\n // Computed card data\n private suiteCards: SuiteCardData[] = [];\n private testCards: TestCardData[] = [];\n\n // State subjects\n private _searchTerm$ = new BehaviorSubject<string>('');\n private _statusFilters$ = new BehaviorSubject<Set<string>>(new Set());\n private _viewMode$ = new BehaviorSubject<ViewMode>('card');\n private _displayMode$ = new BehaviorSubject<DisplayMode>('all');\n private _selectedSidebar$ = new BehaviorSubject<SidebarSelection>({ Type: 'all', ID: null });\n private _sortField$ = new BehaviorSubject<SortField>('name');\n private _sortDirection$ = new BehaviorSubject<SortDirection>('asc');\n\n // Template-bound state\n IsLoading = true;\n IsSidebarCollapsed = false;\n SearchTerm = '';\n StatusFilters = new Set<string>();\n ViewMode: ViewMode = 'card';\n DisplayMode: DisplayMode = 'all';\n SelectedSidebar: SidebarSelection = { Type: 'all', ID: null };\n SortField: SortField = 'name';\n SortDirection: SortDirection = 'asc';\n\n // Filtered results\n FilteredSuites: SuiteCardData[] = [];\n FilteredTests: TestCardData[] = [];\n FilteredSuiteTree: SuiteTreeNode[] = [];\n FilteredTestTypes: MJTestTypeEntity[] = [];\n\n // Counts\n TotalItemCount = 0;\n StandaloneTestCount = 0;\n FilteredResultCount = 0;\n\n readonly StatusOptions: string[] = ['Active', 'Pending', 'Disabled'];\n readonly FormStatusOptions: string[] = ['Active', 'Pending', 'Disabled'];\n\n // Settings keys\n private static readonly PANEL_WIDTH_KEY = 'Testing.ExplorerPanelWidth';\n private static readonly SEARCH_STATE_KEY = 'Testing.ExplorerSearchState';\n private settingsPersistSubject = new Subject<void>();\n private settingsLoaded = false;\n\n // Slideout state\n SlideoutOpen = false;\n SlideoutCreateType: 'test' | 'suite' = 'test';\n SlideoutWidth = 560;\n IsSaving = false;\n FormErrorMessage = '';\n\n // Resize state\n private resizeStartX = 0;\n private resizeStartWidth = 0;\n\n // Form fields\n FormName = '';\n FormDescription = '';\n FormTypeID = '';\n FormStatus: 'Active' | 'Pending' | 'Disabled' = 'Active';\n FormParentSuiteID = '';\n FormEstDuration = 0;\n FormEstCost = 0;\n FormTags = '';\n\n get IsFormValid(): boolean {\n if (!this.FormName.trim()) return false;\n if (this.SlideoutCreateType === 'test' && !this.FormTypeID) return false;\n return true;\n }\n\n get SortFieldLabel(): string {\n switch (this.SortField) {\n case 'name': return 'Name';\n case 'updated': return 'Updated';\n case 'status': return 'Status';\n default: return 'Name';\n }\n }\n\n constructor(\n private cdr: ChangeDetectorRef,\n private viewContainerRef: ViewContainerRef,\n private testingDialogService: TestingDialogService,\n public instrumentationService: TestingInstrumentationService\n ) {}\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n async ngOnInit(): Promise<void> {\n this.loadUserSettings();\n this.setupSettingsPersistence();\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n try {\n await TestEngineBase.Instance.Config(false);\n await this.LoadData();\n } catch (err) {\n console.error('TestingExplorerComponent: Failed to load data', err);\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n\n this.subscribeToStateChanges();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n document.removeEventListener('mousemove', this.onResizeMove);\n document.removeEventListener('mouseup', this.onResizeEnd);\n UserInfoEngine.Instance.FlushPendingSettings();\n }\n\n // ---------------------------------------------------------------------------\n // Public Methods\n // ---------------------------------------------------------------------------\n\n async LoadData(): Promise<void> {\n this.loadCachedMetadata();\n await this.loadTestRunStats();\n this.buildSuiteCards();\n this.buildTestCards();\n this.buildSuiteTree();\n this.computeCounts();\n this.applyFilters();\n }\n\n IsSidebarSelected(id: string): boolean {\n return UUIDsEqual(this.SelectedSidebar.ID, id);\n }\n\n SelectSidebarItem(selection: SidebarSelection): void {\n this._selectedSidebar$.next(selection);\n }\n\n ToggleStatus(status: string): void {\n const current = new Set(this._statusFilters$.value);\n if (current.has(status)) {\n current.delete(status);\n } else {\n current.add(status);\n }\n this._statusFilters$.next(current);\n }\n\n IsStatusActive(status: string): boolean {\n return this.StatusFilters.has(status);\n }\n\n SetDisplayMode(mode: DisplayMode): void {\n this._displayMode$.next(mode);\n }\n\n SetViewMode(mode: ViewMode): void {\n this._viewMode$.next(mode);\n }\n\n OnSearchInput(event: Event): void {\n const input = event.target as HTMLInputElement;\n this._searchTerm$.next(input.value);\n }\n\n ClearSearch(): void {\n this._searchTerm$.next('');\n }\n\n ToggleSidebar(): void {\n this.IsSidebarCollapsed = !this.IsSidebarCollapsed;\n this.cdr.markForCheck();\n }\n\n ToggleSuiteExpand(node: SuiteTreeNode, event: MouseEvent): void {\n event.stopPropagation();\n node.Expanded = !node.Expanded;\n this.cdr.markForCheck();\n }\n\n ToggleSortDirection(): void {\n const newDir = this.SortDirection === 'asc' ? 'desc' : 'asc';\n this._sortDirection$.next(newDir);\n }\n\n RunTest(testId: string): void {\n this.testingDialogService.OpenTestDialog(testId, this.viewContainerRef);\n }\n\n RunSuite(suiteId: string): void {\n this.testingDialogService.OpenSuiteDialog(suiteId, this.viewContainerRef);\n }\n\n EditItem(entityName: string, id: string): void {\n SharedService.Instance.OpenEntityRecord(entityName, CompositeKey.FromID(id));\n }\n\n ViewTestHistory(testId: string): void {\n SharedService.Instance.OpenEntityRecord('MJ: Tests', CompositeKey.FromID(testId));\n }\n\n ViewSuiteResults(suiteId: string): void {\n SharedService.Instance.OpenEntityRecord('MJ: Test Suites', CompositeKey.FromID(suiteId));\n }\n\n OnNewTest(): void {\n this.OpenSlideout('test');\n }\n\n OnNewSuite(): void {\n this.OpenSlideout('suite');\n }\n\n OpenSlideout(type: 'test' | 'suite'): void {\n this.SlideoutCreateType = type;\n this.resetForm();\n this.SlideoutOpen = true;\n this.cdr.markForCheck();\n }\n\n CloseSlideout(): void {\n this.SlideoutOpen = false;\n this.FormErrorMessage = '';\n this.cdr.markForCheck();\n }\n\n SetSlideoutCreateType(type: 'test' | 'suite'): void {\n this.SlideoutCreateType = type;\n this.resetForm();\n this.cdr.markForCheck();\n }\n\n async SaveForm(): Promise<void> {\n if (!this.IsFormValid || this.IsSaving) return;\n\n this.IsSaving = true;\n this.FormErrorMessage = '';\n this.cdr.markForCheck();\n\n try {\n if (this.SlideoutCreateType === 'test') {\n await this.saveNewTest();\n } else {\n await this.saveNewSuite();\n }\n this.CloseSlideout();\n await TestEngineBase.Instance.Config(true);\n await this.LoadData();\n this.cdr.markForCheck();\n } catch (err) {\n const message = err instanceof Error ? err.message : 'An error occurred while saving.';\n this.FormErrorMessage = message;\n console.error('TestingExplorerComponent: Save failed', err);\n } finally {\n this.IsSaving = false;\n this.cdr.markForCheck();\n }\n }\n\n // ── Resize ──────────────────────────────────────────\n OnResizeStart(event: MouseEvent): void {\n event.preventDefault();\n this.resizeStartX = event.clientX;\n this.resizeStartWidth = this.SlideoutWidth;\n document.addEventListener('mousemove', this.onResizeMove);\n document.addEventListener('mouseup', this.onResizeEnd);\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n }\n\n private onResizeMove = (event: MouseEvent): void => {\n const delta = this.resizeStartX - event.clientX;\n this.SlideoutWidth = Math.max(400, Math.min(900, this.resizeStartWidth + delta));\n this.cdr.detectChanges();\n };\n\n private onResizeEnd = (): void => {\n document.removeEventListener('mousemove', this.onResizeMove);\n document.removeEventListener('mouseup', this.onResizeEnd);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n UserInfoEngine.Instance.SetSettingDebounced(\n TestingExplorerComponent.PANEL_WIDTH_KEY,\n String(this.SlideoutWidth)\n );\n };\n\n GetTestCountForType(typeId: string): number {\n return this.allTests.filter(t => UUIDsEqual(t.TypeID, typeId)).length\n }\n\n // ---------------------------------------------------------------------------\n // Formatting Helpers\n // ---------------------------------------------------------------------------\n\n FormatDuration(ms: number): string {\n if (ms <= 0) return '0s';\n if (ms < 1000) return `${Math.round(ms)}ms`;\n const totalSeconds = Math.floor(ms / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n if (minutes > 0) return `${minutes}m ${seconds}s`;\n return `${seconds}s`;\n }\n\n FormatDurationSeconds(seconds: number): string {\n if (seconds <= 0) return '0s';\n const minutes = Math.floor(seconds / 60);\n const secs = seconds % 60;\n if (minutes > 0) return `${minutes}m ${secs}s`;\n return `${secs}s`;\n }\n\n FormatRelativeTime(date: Date | null): string {\n if (!date) return 'Never';\n const d = date instanceof Date ? date : new Date(date);\n const now = Date.now();\n const diffMs = now - d.getTime();\n const diffMinutes = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMinutes < 1) return 'Just now';\n if (diffMinutes < 60) return `${diffMinutes}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays < 30) return `${diffDays}d ago`;\n return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });\n }\n\n FormatPercent(value: number): string {\n return `${Math.round(value)}%`;\n }\n\n FormatCost(cost: number): string {\n if (cost < 0.01) return '$0.00';\n return `$${cost.toFixed(2)}`;\n }\n\n GetScoreClass(score: number): string {\n if (score >= 0.7) return 'good';\n if (score >= 0.4) return 'warn';\n return 'bad';\n }\n\n GetStatusClass(status: string): string {\n switch (status.toLowerCase()) {\n case 'passed': return 'status-passed';\n case 'failed': return 'status-failed';\n case 'error': return 'status-error';\n case 'running': return 'status-running';\n default: return 'status-default';\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private: Data Loading\n // ---------------------------------------------------------------------------\n\n private loadCachedMetadata(): void {\n const engine = TestEngineBase.Instance;\n this.allTests = engine.Tests;\n this.AllSuites = engine.TestSuites;\n this.allSuiteTests = engine.TestSuiteTests;\n this.AllTestTypes = engine.TestTypes;\n }\n\n private async loadTestRunStats(): Promise<void> {\n const rv = new RunView();\n const result = await rv.RunView<TestRunStatRow>({\n EntityName: 'MJ: Test Runs',\n Fields: ['ID', 'TestID', 'Status', 'Score', 'CostUSD', 'StartedAt', 'CompletedAt'],\n OrderBy: 'StartedAt DESC',\n MaxRows: 5000,\n ResultType: 'simple'\n });\n\n this.testRunStats = result.Success ? (result.Results || []) : [];\n }\n\n // ---------------------------------------------------------------------------\n // Private: Build Card Data\n // ---------------------------------------------------------------------------\n\n private buildSuiteCards(): void {\n this.suiteCards = this.AllSuites.map(suite => this.buildSingleSuiteCard(suite));\n }\n\n private buildSingleSuiteCard(suite: MJTestSuiteEntity): SuiteCardData {\n const suiteTestLinks = this.allSuiteTests.filter(st => UUIDsEqual(st.SuiteID, suite.ID));\n const testIds = new Set(suiteTestLinks.map(st => st.TestID));\n const runsForSuite = this.testRunStats.filter(r => testIds.has(r.TestID));\n\n const passedRuns = runsForSuite.filter(r => r.Status === 'Passed');\n const passRate = runsForSuite.length > 0 ? (passedRuns.length / runsForSuite.length) * 100 : 0;\n const avgScore = runsForSuite.length > 0\n ? runsForSuite.reduce((s, r) => s + (r.Score || 0), 0) / runsForSuite.length\n : 0;\n const avgDuration = this.computeAvgDuration(runsForSuite);\n const lastRunDate = this.findLastRunDate(runsForSuite);\n const previewTests = this.buildSuiteTestPreviews(suiteTestLinks);\n\n return {\n ID: suite.ID,\n Name: suite.Name,\n Description: suite.Description || '',\n Status: suite.Status,\n TestCount: testIds.size,\n PassRate: passRate,\n AvgScore: avgScore,\n AvgDuration: avgDuration,\n LastRunDate: lastRunDate,\n Tags: this.parseTags(suite.Tags),\n Tests: previewTests,\n TotalTestsInSuite: testIds.size\n };\n }\n\n private buildSuiteTestPreviews(suiteTestLinks: MJTestSuiteTestEntity[]): SuiteTestItem[] {\n return suiteTestLinks\n .sort((a, b) => a.Sequence - b.Sequence)\n .slice(0, 5)\n .map(st => {\n const test = this.allTests.find(t => UUIDsEqual(t.ID, st.TestID));\n const lastRun = this.findLastRunForTest(st.TestID);\n return {\n TestID: st.TestID,\n TestName: test?.Name || st.Test || 'Unknown',\n LastStatus: lastRun?.Status || '',\n LastScore: lastRun?.Score || 0\n };\n });\n }\n\n private buildTestCards(): void {\n this.testCards = this.allTests.map(test => this.buildSingleTestCard(test));\n }\n\n private buildSingleTestCard(test: MJTestEntity): TestCardData {\n const runsForTest = this.testRunStats.filter(r => UUIDsEqual(r.TestID, test.ID));\n const lastRun = runsForTest.length > 0 ? runsForTest[0] : null; // already sorted DESC\n const passedRuns = runsForTest.filter(r => r.Status === 'Passed');\n const passRate = runsForTest.length > 0 ? (passedRuns.length / runsForTest.length) * 100 : 0;\n\n const typeName = this.AllTestTypes.find(t => UUIDsEqual(t.ID, test.TypeID))?.Name || '';\n const suiteName = this.findSuiteNameForTest(test.ID);\n\n return {\n ID: test.ID,\n Name: test.Name,\n Description: test.Description || '',\n Status: test.Status,\n TypeName: typeName,\n SuiteName: suiteName,\n LastRunStatus: lastRun?.Status || '',\n LastScore: lastRun?.Score || 0,\n TotalRuns: runsForTest.length,\n PassRate: passRate,\n EstDuration: test.EstimatedDurationSeconds || 0,\n EstCost: test.EstimatedCostUSD || 0,\n LastRunDate: lastRun ? this.toDate(lastRun.StartedAt) : null,\n Tags: this.parseTags(test.Tags),\n UpdatedAt: test.__mj_UpdatedAt\n };\n }\n\n // ---------------------------------------------------------------------------\n // Private: Build Suite Tree\n // ---------------------------------------------------------------------------\n\n private buildSuiteTree(): void {\n const filteredSuites = this.AllSuites;\n\n const nodeMap = new Map<string, SuiteTreeNode>();\n\n for (const suite of filteredSuites) {\n nodeMap.set(suite.ID, {\n ID: suite.ID,\n Name: suite.Name,\n ParentID: suite.ParentID,\n TestCount: this.allSuiteTests.filter(st => UUIDsEqual(st.SuiteID, suite.ID)).length,\n Children: [],\n Expanded: false\n });\n }\n\n const roots: SuiteTreeNode[] = [];\n nodeMap.forEach(node => {\n if (node.ParentID && nodeMap.has(node.ParentID)) {\n nodeMap.get(node.ParentID)!.Children.push(node);\n } else {\n roots.push(node);\n }\n });\n\n this.FilteredSuiteTree = roots;\n this.filterTestTypes();\n }\n\n private filterTestTypes(): void {\n this.FilteredTestTypes = this.AllTestTypes;\n }\n\n // ---------------------------------------------------------------------------\n // Private: Filtering & Sorting\n // ---------------------------------------------------------------------------\n\n private subscribeToStateChanges(): void {\n combineLatest([\n this._searchTerm$,\n this._statusFilters$,\n this._displayMode$,\n this._selectedSidebar$,\n this._sortField$,\n this._sortDirection$,\n this._viewMode$\n ]).pipe(\n takeUntil(this.destroy$)\n ).subscribe(([searchTerm, statusFilters, displayMode, selectedSidebar, sortField, sortDirection, viewMode]) => {\n this.SearchTerm = searchTerm;\n this.StatusFilters = statusFilters;\n this.DisplayMode = displayMode;\n this.SelectedSidebar = selectedSidebar;\n this.SortField = sortField;\n this.SortDirection = sortDirection;\n this.ViewMode = viewMode;\n this.applyFilters();\n this.settingsPersistSubject.next();\n this.cdr.markForCheck();\n });\n }\n\n private applyFilters(): void {\n this.FilteredSuites = this.filterSuiteCards();\n this.FilteredTests = this.filterTestCards();\n this.FilteredResultCount = this.FilteredSuites.length + this.FilteredTests.length;\n }\n\n private filterSuiteCards(): SuiteCardData[] {\n let result = [...this.suiteCards];\n result = this.applySidebarFilterToSuites(result);\n result = this.applySearchFilterToSuites(result);\n result = this.applyStatusFilterToSuites(result);\n result = this.sortSuiteCards(result);\n return result;\n }\n\n private filterTestCards(): TestCardData[] {\n let result = [...this.testCards];\n result = this.applySidebarFilterToTests(result);\n result = this.applySearchFilterToTests(result);\n result = this.applyStatusFilterToTests(result);\n result = this.sortTestCards(result);\n return result;\n }\n\n private applySidebarFilterToSuites(suites: SuiteCardData[]): SuiteCardData[] {\n const sel = this.SelectedSidebar;\n switch (sel.Type) {\n case 'suite':\n return suites.filter(s => UUIDsEqual(s.ID, sel.ID));\n case 'standalone':\n return []; // standalone = tests only\n case 'testType':\n return []; // test types apply to tests only\n default:\n return suites;\n }\n }\n\n private applySidebarFilterToTests(tests: TestCardData[]): TestCardData[] {\n const sel = this.SelectedSidebar;\n switch (sel.Type) {\n case 'suite': {\n const testIds = new Set(\n this.allSuiteTests.filter(st => UUIDsEqual(st.SuiteID, sel.ID)).map(st => st.TestID)\n );\n return tests.filter(t => testIds.has(t.ID));\n }\n case 'standalone': {\n const testIdsInSuites = new Set(this.allSuiteTests.map(st => st.TestID));\n return tests.filter(t => !testIdsInSuites.has(t.ID));\n }\n case 'testType':\n return tests.filter(t => {\n const testEntity = this.allTests.find(te => UUIDsEqual(te.ID, t.ID));\n return UUIDsEqual(testEntity?.TypeID, sel.ID);\n });\n default:\n return tests;\n }\n }\n\n private applySearchFilterToSuites(suites: SuiteCardData[]): SuiteCardData[] {\n const term = this.SearchTerm.toLowerCase().trim();\n if (!term) return suites;\n return suites.filter(s =>\n s.Name.toLowerCase().includes(term) ||\n s.Description.toLowerCase().includes(term)\n );\n }\n\n private applySearchFilterToTests(tests: TestCardData[]): TestCardData[] {\n const term = this.SearchTerm.toLowerCase().trim();\n if (!term) return tests;\n return tests.filter(t =>\n t.Name.toLowerCase().includes(term) ||\n t.Description.toLowerCase().includes(term)\n );\n }\n\n private applyStatusFilterToSuites(suites: SuiteCardData[]): SuiteCardData[] {\n if (this.StatusFilters.size === 0) return suites;\n return suites.filter(s => this.StatusFilters.has(s.Status));\n }\n\n private applyStatusFilterToTests(tests: TestCardData[]): TestCardData[] {\n if (this.StatusFilters.size === 0) return tests;\n return tests.filter(t => this.StatusFilters.has(t.Status));\n }\n\n private sortSuiteCards(suites: SuiteCardData[]): SuiteCardData[] {\n const dir = this.SortDirection === 'asc' ? 1 : -1;\n return suites.sort((a, b) => this.compareBySortField(a.Name, a.Status, a.LastRunDate, b.Name, b.Status, b.LastRunDate, dir));\n }\n\n private sortTestCards(tests: TestCardData[]): TestCardData[] {\n const dir = this.SortDirection === 'asc' ? 1 : -1;\n return tests.sort((a, b) => this.compareBySortField(a.Name, a.Status, a.UpdatedAt, b.Name, b.Status, b.UpdatedAt, dir));\n }\n\n private compareBySortField(\n aName: string, aStatus: string, aDate: Date | null,\n bName: string, bStatus: string, bDate: Date | null,\n dir: number\n ): number {\n switch (this.SortField) {\n case 'name':\n return aName.localeCompare(bName) * dir;\n case 'status':\n return aStatus.localeCompare(bStatus) * dir;\n case 'updated': {\n const aTime = aDate ? new Date(aDate).getTime() : 0;\n const bTime = bDate ? new Date(bDate).getTime() : 0;\n return (aTime - bTime) * dir;\n }\n default:\n return 0;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private: Helpers\n // ---------------------------------------------------------------------------\n\n private computeCounts(): void {\n const testIdsInSuites = new Set(this.allSuiteTests.map(st => st.TestID));\n this.StandaloneTestCount = this.allTests.filter(t => !testIdsInSuites.has(t.ID)).length;\n this.TotalItemCount = this.allTests.length + this.AllSuites.length;\n }\n\n private computeAvgDuration(runs: TestRunStatRow[]): number {\n const completed = runs.filter(r => r.CompletedAt != null && r.StartedAt != null);\n if (completed.length === 0) return 0;\n\n const totalMs = completed.reduce((sum, r) => {\n const start = this.toDate(r.StartedAt).getTime();\n const end = this.toDate(r.CompletedAt!).getTime();\n return sum + (end - start);\n }, 0);\n\n return totalMs / completed.length;\n }\n\n private findLastRunDate(runs: TestRunStatRow[]): Date | null {\n if (runs.length === 0) return null;\n return this.toDate(runs[0].StartedAt);\n }\n\n private findLastRunForTest(testId: string): TestRunStatRow | null {\n return this.testRunStats.find(r => UUIDsEqual(r.TestID, testId)) || null;\n }\n\n private findSuiteNameForTest(testId: string): string {\n const suiteTest = this.allSuiteTests.find(st => UUIDsEqual(st.TestID, testId));\n if (!suiteTest) return '';\n const suite = this.AllSuites.find(s => UUIDsEqual(s.ID, suiteTest.SuiteID));\n return suite?.Name || suiteTest.Suite || '';\n }\n\n private parseTags(tagsJson: string | null): string[] {\n if (!tagsJson) return [];\n try {\n const parsed = JSON.parse(tagsJson);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n }\n\n private toDate(value: string | Date | null): Date {\n if (!value) return new Date(0);\n return value instanceof Date ? value : new Date(value);\n }\n\n // ---------------------------------------------------------------------------\n // Private: User Settings\n // ---------------------------------------------------------------------------\n\n private loadUserSettings(): void {\n try {\n const widthStr = UserInfoEngine.Instance.GetSetting(TestingExplorerComponent.PANEL_WIDTH_KEY);\n if (widthStr) {\n const width = parseInt(widthStr, 10);\n if (!isNaN(width) && width >= 400 && width <= 900) {\n this.SlideoutWidth = width;\n }\n }\n const stateStr = UserInfoEngine.Instance.GetSetting(TestingExplorerComponent.SEARCH_STATE_KEY);\n if (stateStr) {\n const state = JSON.parse(stateStr) as Record<string, string>;\n if (state.searchTerm) {\n this.SearchTerm = state.searchTerm;\n this._searchTerm$.next(state.searchTerm);\n }\n }\n } catch (error) {\n console.warn('[TestingExplorer] Failed to load user settings:', error);\n } finally {\n this.settingsLoaded = true;\n }\n }\n\n private setupSettingsPersistence(): void {\n this.settingsPersistSubject.pipe(\n debounceTime(500),\n takeUntil(this.destroy$)\n ).subscribe(() => {\n this.persistSearchState();\n });\n }\n\n private persistSearchState(): void {\n if (!this.settingsLoaded) return;\n try {\n const state = { searchTerm: this.SearchTerm };\n UserInfoEngine.Instance.SetSettingDebounced(\n TestingExplorerComponent.SEARCH_STATE_KEY,\n JSON.stringify(state)\n );\n } catch (error) {\n console.warn('[TestingExplorer] Failed to persist search state:', error);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private: Form Management\n // ---------------------------------------------------------------------------\n\n private resetForm(): void {\n this.FormName = '';\n this.FormDescription = '';\n this.FormTypeID = this.AllTestTypes.length > 0 ? this.AllTestTypes[0].ID : '';\n this.FormStatus = 'Active';\n this.FormParentSuiteID = '';\n this.FormEstDuration = 0;\n this.FormEstCost = 0;\n this.FormTags = '';\n this.FormErrorMessage = '';\n }\n\n private async saveNewTest(): Promise<void> {\n const md = new Metadata();\n const test = await md.GetEntityObject<MJTestEntity>('MJ: Tests');\n test.NewRecord();\n test.Name = this.FormName.trim();\n test.Description = this.FormDescription.trim() || null;\n test.TypeID = this.FormTypeID;\n test.Status = this.FormStatus;\n if (this.FormEstDuration > 0) test.EstimatedDurationSeconds = this.FormEstDuration;\n if (this.FormEstCost > 0) test.EstimatedCostUSD = this.FormEstCost;\n if (this.FormTags.trim()) {\n const tags = this.FormTags.split(',').map(t => t.trim()).filter(t => t.length > 0);\n test.Tags = JSON.stringify(tags);\n }\n const saved = await test.Save();\n if (!saved) throw new Error('Failed to save test. Please check your input and try again.');\n }\n\n private async saveNewSuite(): Promise<void> {\n const md = new Metadata();\n const suite = await md.GetEntityObject<MJTestSuiteEntity>('MJ: Test Suites');\n suite.NewRecord();\n suite.Name = this.FormName.trim();\n suite.Description = this.FormDescription.trim() || null;\n suite.Status = this.FormStatus;\n if (this.FormParentSuiteID) suite.ParentID = this.FormParentSuiteID;\n if (this.FormTags.trim()) {\n const tags = this.FormTags.split(',').map(t => t.trim()).filter(t => t.length > 0);\n suite.Tags = JSON.stringify(tags);\n }\n const saved = await suite.Save();\n if (!saved) throw new Error('Failed to save test suite. Please check your input and try again.');\n }\n}\n"]}
|