@molecule/app-ide-react 1.13.0 → 1.15.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/README.md +578 -1
- package/dist/command-metadata.d.ts.map +1 -1
- package/dist/command-metadata.js +7 -2
- package/dist/command-metadata.js.map +1 -1
- package/dist/components/ChatPanel.d.ts +9 -1
- package/dist/components/ChatPanel.d.ts.map +1 -1
- package/dist/components/ChatPanel.js +177 -18
- package/dist/components/ChatPanel.js.map +1 -1
- package/dist/components/TestsBar.d.ts +55 -0
- package/dist/components/TestsBar.d.ts.map +1 -0
- package/dist/components/TestsBar.js +296 -0
- package/dist/components/TestsBar.js.map +1 -0
- package/dist/components/TestsCard.d.ts +78 -0
- package/dist/components/TestsCard.d.ts.map +1 -0
- package/dist/components/TestsCard.js +247 -0
- package/dist/components/TestsCard.js.map +1 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/tests-bar-utilities.d.ts +129 -0
- package/dist/components/tests-bar-utilities.d.ts.map +1 -0
- package/dist/components/tests-bar-utilities.js +236 -0
- package/dist/components/tests-bar-utilities.js.map +1 -0
- package/dist/components/tests-card-utilities.d.ts +175 -0
- package/dist/components/tests-card-utilities.d.ts.map +1 -0
- package/dist/components/tests-card-utilities.js +333 -0
- package/dist/components/tests-card-utilities.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +136 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure state + grouping helpers for the {@link TestsBar}.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is a plain function over plain data, so the bar's behaviour
|
|
5
|
+
* (which rows a group runs, how a streamed event moves the run forward, what
|
|
6
|
+
* the collapsed summary says) is unit-testable without rendering anything.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
/** Live output lines retained — enough to read, bounded so a chatty run cannot grow forever. */
|
|
11
|
+
export const MAX_OUTPUT_LINES = 400;
|
|
12
|
+
/** Display order of the kinds: the preview-driven specs lead, unit tests follow. */
|
|
13
|
+
const KIND_ORDER = ['e2e', 'unit'];
|
|
14
|
+
/**
|
|
15
|
+
* Display order of the project directories within a kind: by path, with the
|
|
16
|
+
* workspace root (`.`) last — it is the least specific place a test can live.
|
|
17
|
+
*
|
|
18
|
+
* @param a - One directory.
|
|
19
|
+
* @param b - The other.
|
|
20
|
+
* @returns The sort order.
|
|
21
|
+
*/
|
|
22
|
+
function compareWorkspaces(a, b) {
|
|
23
|
+
if (a === b)
|
|
24
|
+
return 0;
|
|
25
|
+
if (a === '.')
|
|
26
|
+
return 1;
|
|
27
|
+
if (b === '.')
|
|
28
|
+
return -1;
|
|
29
|
+
return a.localeCompare(b);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The heading name for a directory: the host's label when it sent one, else
|
|
33
|
+
* the path itself, and `null` for the root either way.
|
|
34
|
+
*
|
|
35
|
+
* @param item - Any test in the group.
|
|
36
|
+
* @returns The label, or `null` for the workspace root.
|
|
37
|
+
*/
|
|
38
|
+
function labelFor(item) {
|
|
39
|
+
if (item.workspaceLabel !== undefined)
|
|
40
|
+
return item.workspaceLabel;
|
|
41
|
+
return item.workspace === '.' ? null : item.workspace;
|
|
42
|
+
}
|
|
43
|
+
/** A run that has not started. */
|
|
44
|
+
export const EMPTY_RUN_STATE = {
|
|
45
|
+
runId: null,
|
|
46
|
+
running: false,
|
|
47
|
+
queued: [],
|
|
48
|
+
currentId: null,
|
|
49
|
+
output: [],
|
|
50
|
+
results: {},
|
|
51
|
+
outcome: null,
|
|
52
|
+
error: null,
|
|
53
|
+
startedAt: null,
|
|
54
|
+
durationMs: null,
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Group tests for display: by kind (end-to-end first), then by project
|
|
58
|
+
* directory (whatever directories are present — `app`, `my-app/app`,
|
|
59
|
+
* `packages/web`, the root last), with the files sorted inside each group.
|
|
60
|
+
*
|
|
61
|
+
* @param tests - Every discovered test.
|
|
62
|
+
* @returns The groups, in display order. Empty groups are never produced.
|
|
63
|
+
*/
|
|
64
|
+
export function groupTests(tests) {
|
|
65
|
+
const groups = [];
|
|
66
|
+
for (const kind of KIND_ORDER) {
|
|
67
|
+
const workspaces = [
|
|
68
|
+
...new Set(tests.filter((t) => t.kind === kind).map((t) => t.workspace)),
|
|
69
|
+
].sort(compareWorkspaces);
|
|
70
|
+
for (const workspace of workspaces) {
|
|
71
|
+
const items = tests
|
|
72
|
+
.filter((t) => t.kind === kind && t.workspace === workspace)
|
|
73
|
+
.slice()
|
|
74
|
+
.sort((a, b) => a.file.localeCompare(b.file));
|
|
75
|
+
if (items.length > 0)
|
|
76
|
+
groups.push({ kind, workspace, label: labelFor(items[0]), items });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return groups;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* How many tests there are of each kind.
|
|
83
|
+
*
|
|
84
|
+
* @param tests - Every discovered test.
|
|
85
|
+
* @returns The per-kind counts.
|
|
86
|
+
*/
|
|
87
|
+
export function countByKind(tests) {
|
|
88
|
+
return {
|
|
89
|
+
e2e: tests.filter((t) => t.kind === 'e2e').length,
|
|
90
|
+
unit: tests.filter((t) => t.kind === 'unit').length,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The tallies of the last run, over the tests that are still listed. Counted
|
|
95
|
+
* per FILE (one row, one verdict) so the collapsed summary matches the rows.
|
|
96
|
+
*
|
|
97
|
+
* @param tests - The currently listed tests.
|
|
98
|
+
* @param results - The per-id outcomes.
|
|
99
|
+
* @returns Passed/failed/skipped file counts.
|
|
100
|
+
*/
|
|
101
|
+
export function summarizeResults(tests, results) {
|
|
102
|
+
let passed = 0;
|
|
103
|
+
let failed = 0;
|
|
104
|
+
let skipped = 0;
|
|
105
|
+
for (const test of tests) {
|
|
106
|
+
const entry = results[test.id];
|
|
107
|
+
if (!entry)
|
|
108
|
+
continue;
|
|
109
|
+
if (entry.status === 'passed')
|
|
110
|
+
passed += 1;
|
|
111
|
+
else if (entry.status === 'failed')
|
|
112
|
+
failed += 1;
|
|
113
|
+
else
|
|
114
|
+
skipped += 1;
|
|
115
|
+
}
|
|
116
|
+
return { passed, failed, skipped, reported: passed + failed + skipped };
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Fold one streamed event into the run state.
|
|
120
|
+
*
|
|
121
|
+
* Deliberately total: an event for an id the bar no longer lists is recorded
|
|
122
|
+
* anyway (a re-list may be in flight), and an unknown event type leaves the
|
|
123
|
+
* state untouched rather than throwing inside a stream handler.
|
|
124
|
+
*
|
|
125
|
+
* @param state - The current state.
|
|
126
|
+
* @param event - The event just received.
|
|
127
|
+
* @returns The next state (a new object whenever anything changed).
|
|
128
|
+
*/
|
|
129
|
+
export function applyTestRunEvent(state, event) {
|
|
130
|
+
switch (event.type) {
|
|
131
|
+
case 'start': {
|
|
132
|
+
// A new run clears the previous run's verdicts for the ids it covers, so
|
|
133
|
+
// a stale green pill never sits next to a row that is running again.
|
|
134
|
+
const results = { ...state.results };
|
|
135
|
+
for (const id of event.ids)
|
|
136
|
+
delete results[id];
|
|
137
|
+
return {
|
|
138
|
+
...state,
|
|
139
|
+
runId: event.runId,
|
|
140
|
+
running: true,
|
|
141
|
+
queued: [...event.ids],
|
|
142
|
+
currentId: null,
|
|
143
|
+
output: [],
|
|
144
|
+
results,
|
|
145
|
+
outcome: null,
|
|
146
|
+
error: null,
|
|
147
|
+
startedAt: Date.now(),
|
|
148
|
+
durationMs: null,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
case 'output': {
|
|
152
|
+
const output = [...state.output, ...event.chunk.split('\n')];
|
|
153
|
+
return {
|
|
154
|
+
...state,
|
|
155
|
+
currentId: event.id ?? state.currentId,
|
|
156
|
+
output: output.length > MAX_OUTPUT_LINES ? output.slice(-MAX_OUTPUT_LINES) : output,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
case 'result': {
|
|
160
|
+
return {
|
|
161
|
+
...state,
|
|
162
|
+
results: {
|
|
163
|
+
...state.results,
|
|
164
|
+
[event.id]: {
|
|
165
|
+
status: event.status,
|
|
166
|
+
...(event.durationMs != null ? { durationMs: event.durationMs } : {}),
|
|
167
|
+
passed: event.passed ?? 0,
|
|
168
|
+
failed: event.failed ?? 0,
|
|
169
|
+
skipped: event.skipped ?? 0,
|
|
170
|
+
...(event.output ? { output: event.output } : {}),
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
case 'done': {
|
|
176
|
+
return {
|
|
177
|
+
...state,
|
|
178
|
+
running: false,
|
|
179
|
+
currentId: null,
|
|
180
|
+
outcome: event.outcome,
|
|
181
|
+
error: event.error ?? null,
|
|
182
|
+
durationMs: event.durationMs ?? (state.startedAt ? Date.now() - state.startedAt : null),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
default:
|
|
186
|
+
return state;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The state after a run that never produced a `done` event — the host's stream
|
|
191
|
+
* died, or its request failed before the server could answer.
|
|
192
|
+
*
|
|
193
|
+
* @param state - The current state.
|
|
194
|
+
* @param message - What to show in the bar.
|
|
195
|
+
* @returns The next state, no longer running.
|
|
196
|
+
*/
|
|
197
|
+
export function failRun(state, message) {
|
|
198
|
+
return { ...state, running: false, currentId: null, outcome: 'error', error: message };
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Whether a row should render as "running": the run is live and either the host
|
|
202
|
+
* named this row as current, or it is in the queue and has no verdict yet.
|
|
203
|
+
*
|
|
204
|
+
* @param state - The run state.
|
|
205
|
+
* @param id - The row's test id.
|
|
206
|
+
* @returns True when the row is part of the live run and still undecided.
|
|
207
|
+
*/
|
|
208
|
+
export function isRowRunning(state, id) {
|
|
209
|
+
if (!state.running)
|
|
210
|
+
return false;
|
|
211
|
+
if (state.currentId === id)
|
|
212
|
+
return true;
|
|
213
|
+
return state.queued.includes(id) && state.results[id] == null;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* The label for a row: the host's title when it gave one, else the file path.
|
|
217
|
+
*
|
|
218
|
+
* @param item - The test.
|
|
219
|
+
* @returns The label to render.
|
|
220
|
+
*/
|
|
221
|
+
export function testRowLabel(item) {
|
|
222
|
+
return item.title?.trim() || item.file;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Whether a written path is a test file, so the bar can re-list the moment the
|
|
226
|
+
* agent writes a NEW spec instead of only on the next run or reload. Matches
|
|
227
|
+
* the same `*.spec.*` / `*.test.*` shape the host's discovery looks for, so a
|
|
228
|
+
* write that cannot change the list never costs a listing.
|
|
229
|
+
*
|
|
230
|
+
* @param path - The path that changed (absolute or workspace-relative).
|
|
231
|
+
* @returns True when the path is a spec or test file.
|
|
232
|
+
*/
|
|
233
|
+
export function isTestFilePath(path) {
|
|
234
|
+
return /\.(spec|test)\.[cm]?[jt]sx?$/.test(path);
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=tests-bar-utilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tests-bar-utilities.js","sourceRoot":"","sources":["../../src/components/tests-bar-utilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure state + grouping helpers for the {@link TestsCard}.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is a plain function over plain data, so the card's behaviour
|
|
5
|
+
* (which rows a group runs, how a streamed event moves the run forward, what
|
|
6
|
+
* the collapsed summary says) is unit-testable without rendering anything.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import type { TestItem, TestKind, TestRunEvent, TestRunOutcome, TestStatus, TestWorkspace } from '../types.js';
|
|
11
|
+
/** One rendered group of rows: a kind within a project directory. */
|
|
12
|
+
export interface TestGroup {
|
|
13
|
+
kind: TestKind;
|
|
14
|
+
workspace: TestWorkspace;
|
|
15
|
+
/** The directory's name for the heading; `null` for the workspace root. */
|
|
16
|
+
label: string | null;
|
|
17
|
+
items: TestItem[];
|
|
18
|
+
}
|
|
19
|
+
/** What one test file ended as in the last run. */
|
|
20
|
+
export interface TestResultEntry {
|
|
21
|
+
status: TestStatus;
|
|
22
|
+
durationMs?: number;
|
|
23
|
+
passed: number;
|
|
24
|
+
failed: number;
|
|
25
|
+
skipped: number;
|
|
26
|
+
/** The runner's output, kept for a FAILURE so the row can keep showing it. */
|
|
27
|
+
output?: string;
|
|
28
|
+
}
|
|
29
|
+
/** Everything the card knows about the run it is showing. */
|
|
30
|
+
export interface TestsRunState {
|
|
31
|
+
runId: string | null;
|
|
32
|
+
running: boolean;
|
|
33
|
+
/** The ids this run covers, in run order. */
|
|
34
|
+
queued: string[];
|
|
35
|
+
/** The id whose output is streaming right now, when the host says which. */
|
|
36
|
+
currentId: string | null;
|
|
37
|
+
/** The live output lines, newest last, capped at {@link MAX_OUTPUT_LINES}. */
|
|
38
|
+
output: string[];
|
|
39
|
+
/** Per-id outcome from this run (and from earlier runs, until re-run). */
|
|
40
|
+
results: Record<string, TestResultEntry>;
|
|
41
|
+
/** How the run ended, once it has. */
|
|
42
|
+
outcome: TestRunOutcome | null;
|
|
43
|
+
/** A run-level failure message (timeout, transport error) shown in the card. */
|
|
44
|
+
error: string | null;
|
|
45
|
+
startedAt: number | null;
|
|
46
|
+
durationMs: number | null;
|
|
47
|
+
}
|
|
48
|
+
/** Live output lines retained — enough to read, bounded so a chatty run cannot grow forever. */
|
|
49
|
+
export declare const MAX_OUTPUT_LINES = 400;
|
|
50
|
+
/** A run that has not started. */
|
|
51
|
+
export declare const EMPTY_RUN_STATE: TestsRunState;
|
|
52
|
+
/**
|
|
53
|
+
* Group tests for display: by kind (end-to-end first), then by project
|
|
54
|
+
* directory (whatever directories are present — `app`, `my-app/app`,
|
|
55
|
+
* `packages/web`, the root last), with the files sorted inside each group.
|
|
56
|
+
*
|
|
57
|
+
* @param tests - Every discovered test.
|
|
58
|
+
* @returns The groups, in display order. Empty groups are never produced.
|
|
59
|
+
*/
|
|
60
|
+
export declare function groupTests(tests: readonly TestItem[]): TestGroup[];
|
|
61
|
+
/**
|
|
62
|
+
* How many tests there are of each kind.
|
|
63
|
+
*
|
|
64
|
+
* @param tests - Every discovered test.
|
|
65
|
+
* @returns The per-kind counts.
|
|
66
|
+
*/
|
|
67
|
+
export declare function countByKind(tests: readonly TestItem[]): Record<TestKind, number>;
|
|
68
|
+
/**
|
|
69
|
+
* The tallies of the last run, over the tests that are still listed. Counted
|
|
70
|
+
* per FILE (one row, one verdict) so the collapsed summary matches the rows.
|
|
71
|
+
*
|
|
72
|
+
* @param tests - The currently listed tests.
|
|
73
|
+
* @param results - The per-id outcomes.
|
|
74
|
+
* @returns Passed/failed/skipped file counts.
|
|
75
|
+
*/
|
|
76
|
+
export declare function summarizeResults(tests: readonly TestItem[], results: Record<string, TestResultEntry>): {
|
|
77
|
+
passed: number;
|
|
78
|
+
failed: number;
|
|
79
|
+
skipped: number;
|
|
80
|
+
reported: number;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Fold one streamed event into the run state.
|
|
84
|
+
*
|
|
85
|
+
* Deliberately total: an event for an id the card no longer lists is recorded
|
|
86
|
+
* anyway (a re-list may be in flight), and an unknown event type leaves the
|
|
87
|
+
* state untouched rather than throwing inside a stream handler.
|
|
88
|
+
*
|
|
89
|
+
* @param state - The current state.
|
|
90
|
+
* @param event - The event just received.
|
|
91
|
+
* @returns The next state (a new object whenever anything changed).
|
|
92
|
+
*/
|
|
93
|
+
export declare function applyTestRunEvent(state: TestsRunState, event: TestRunEvent): TestsRunState;
|
|
94
|
+
/**
|
|
95
|
+
* The state after a run that never produced a `done` event — the host's stream
|
|
96
|
+
* died, or its request failed before the server could answer.
|
|
97
|
+
*
|
|
98
|
+
* @param state - The current state.
|
|
99
|
+
* @param message - What to show in the card.
|
|
100
|
+
* @returns The next state, no longer running.
|
|
101
|
+
*/
|
|
102
|
+
export declare function failRun(state: TestsRunState, message: string): TestsRunState;
|
|
103
|
+
/**
|
|
104
|
+
* Whether a row should render as "running": the run is live and either the host
|
|
105
|
+
* named this row as current, or it is in the queue and has no verdict yet.
|
|
106
|
+
*
|
|
107
|
+
* @param state - The run state.
|
|
108
|
+
* @param id - The row's test id.
|
|
109
|
+
* @returns True when the row is part of the live run and still undecided.
|
|
110
|
+
*/
|
|
111
|
+
export declare function isRowRunning(state: TestsRunState, id: string): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* The label for a row: the host's title when it gave one, else the file path.
|
|
114
|
+
*
|
|
115
|
+
* @param item - The test.
|
|
116
|
+
* @returns The label to render.
|
|
117
|
+
*/
|
|
118
|
+
export declare function testRowLabel(item: TestItem): string;
|
|
119
|
+
/**
|
|
120
|
+
* Filters tests by a free-text query, matching (case-insensitively) against the
|
|
121
|
+
* file path, the row title, and the project directory. A blank query returns
|
|
122
|
+
* every test in input order — the same contract as `filterScripts`.
|
|
123
|
+
*
|
|
124
|
+
* @param tests - The tests to filter.
|
|
125
|
+
* @param query - The search query.
|
|
126
|
+
* @returns The matching tests, in input order.
|
|
127
|
+
*/
|
|
128
|
+
export declare function filterTests(tests: readonly TestItem[], query: string): TestItem[];
|
|
129
|
+
/**
|
|
130
|
+
* Parses a `/test [query | all]` command (`/tests` is the registered alias).
|
|
131
|
+
*
|
|
132
|
+
* `all` is the one argument that ACTS: it runs everything immediately. Every
|
|
133
|
+
* other argument only filters the list, exactly the way `/scripts <query>` seeds
|
|
134
|
+
* the scripts browser — running ONE test by name is what the per-row Run button
|
|
135
|
+
* is for, and giving the argument a second meaning would make `/test <thing>`
|
|
136
|
+
* sometimes list and sometimes execute.
|
|
137
|
+
*
|
|
138
|
+
* @param input - The raw chat input.
|
|
139
|
+
* @returns `{ query, runAll }` when it is a `/test` command, else `null`.
|
|
140
|
+
*/
|
|
141
|
+
export declare function parseTestCommand(input: string): {
|
|
142
|
+
query: string;
|
|
143
|
+
runAll: boolean;
|
|
144
|
+
} | null;
|
|
145
|
+
/** Output kept per failure when several are batched into one fix message. */
|
|
146
|
+
export declare const MAX_FIX_OUTPUT_CHARS = 2000;
|
|
147
|
+
/** Total output kept across a batched fix message, so one click cannot send a novel. */
|
|
148
|
+
export declare const MAX_FIX_MESSAGE_OUTPUT_CHARS = 12000;
|
|
149
|
+
/** One failing test and the output that explains it. */
|
|
150
|
+
export interface TestFailure {
|
|
151
|
+
item: TestItem;
|
|
152
|
+
output?: string | undefined;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Compose the ONE user message the card's “Fix with Synthase” action sends.
|
|
156
|
+
*
|
|
157
|
+
* It is a real turn the executor answers, so it reads like something a person
|
|
158
|
+
* would type: which test failed, where it lives, what the runner said, and to
|
|
159
|
+
* re-run it. This is a PROMPT, not UI copy — it is not translated, exactly like
|
|
160
|
+
* the auto-fix loop’s own `Fix these issues:` message.
|
|
161
|
+
*
|
|
162
|
+
* @param failures - The failing tests, in the order the card lists them.
|
|
163
|
+
* @returns The message, or `` when there is nothing to fix.
|
|
164
|
+
*/
|
|
165
|
+
export declare function buildTestFixMessage(failures: readonly TestFailure[]): string;
|
|
166
|
+
/**
|
|
167
|
+
* Every listed test whose last verdict was a failure, with its output — what
|
|
168
|
+
* the card's fix actions send.
|
|
169
|
+
*
|
|
170
|
+
* @param tests - The currently listed (and filtered) tests.
|
|
171
|
+
* @param results - The per-id outcomes.
|
|
172
|
+
* @returns The failures, in list order.
|
|
173
|
+
*/
|
|
174
|
+
export declare function failedTests(tests: readonly TestItem[], results: Record<string, TestResultEntry>): TestFailure[];
|
|
175
|
+
//# sourceMappingURL=tests-card-utilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tests-card-utilities.d.ts","sourceRoot":"","sources":["../../src/components/tests-card-utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,UAAU,EACV,aAAa,EACd,MAAM,aAAa,CAAA;AAEpB,qEAAqE;AACrE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,QAAQ,CAAA;IACd,SAAS,EAAE,aAAa,CAAA;IACxB,2EAA2E;IAC3E,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,QAAQ,EAAE,CAAA;CAClB;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,UAAU,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,EAAE,OAAO,CAAA;IAChB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACxC,sCAAsC;IACtC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAA;IAC9B,gFAAgF;IAChF,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,gGAAgG;AAChG,eAAO,MAAM,gBAAgB,MAAM,CAAA;AAgCnC,kCAAkC;AAClC,eAAO,MAAM,eAAe,EAAE,aAW7B,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,EAAE,CAelE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAKhF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,QAAQ,EAAE,EAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GACvC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAYvE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,GAAG,aAAa,CA0D1F;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAE5E;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAItE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAEnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CASjF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAMzF;AAED,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,OAAQ,CAAA;AAEzC,wFAAwF;AACxF,eAAO,MAAM,4BAA4B,QAAS,CAAA;AAgBlD,wDAAwD;AACxD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC5B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,CA2B5E;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,QAAQ,EAAE,EAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GACvC,WAAW,EAAE,CAQf"}
|