ccqa 1.54.0 → 1.56.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 +5 -4
- package/dist/bin/ccqa.mjs +983 -1069
- package/dist/cases/contract.cjs +0 -0
- package/dist/cases/contract.d.cts +122 -0
- package/dist/cases/contract.d.mts +122 -0
- package/dist/cases/contract.mjs +1 -0
- package/dist/hub-client/index.d.cts +2 -2
- package/dist/hub-client/index.d.mts +2 -2
- package/dist/package.json +14 -1
- package/package.json +14 -1
|
File without changes
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
//#region src/cases/contract.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* What a test case is, and how ccqa is handed one.
|
|
4
|
+
*
|
|
5
|
+
* ccqa reads its own `spec.yaml` and nothing else. Every other way of writing
|
|
6
|
+
* a test case — a team's markdown, a spreadsheet export, rows in a tracker —
|
|
7
|
+
* is read by a module that project owns and points `targets.<id>.cases` at.
|
|
8
|
+
* This file is the whole contract between the two, and the only part of ccqa a
|
|
9
|
+
* reader module sees.
|
|
10
|
+
*
|
|
11
|
+
* Published as the `ccqa/case-source` subpath, and **types only**: a reader
|
|
12
|
+
* imports nothing at runtime, so `// @ts-check` plus a JSDoc
|
|
13
|
+
* `@type {import("ccqa/case-source").CaseSourceFactory}` is the whole
|
|
14
|
+
* integration, and ccqa's own dependencies never reach the consumer's build.
|
|
15
|
+
* (The gate that refuses `ccqa/*` imports inside an emitted test does not
|
|
16
|
+
* apply here — a reader module is not a test.)
|
|
17
|
+
*
|
|
18
|
+
* What ccqa decides, not the reader: step numbering, where the case's working
|
|
19
|
+
* files live, and where its recording goes. A reader that assigned them would
|
|
20
|
+
* be answering for a directory it cannot see.
|
|
21
|
+
*/
|
|
22
|
+
/** One step of a case, as the document that states it wrote it. */
|
|
23
|
+
interface CaseStep {
|
|
24
|
+
/** What to do. */
|
|
25
|
+
instruction: string;
|
|
26
|
+
/**
|
|
27
|
+
* What this step must make true. Omit it when the case states its
|
|
28
|
+
* expectations once for the whole flow rather than per step — placing them
|
|
29
|
+
* is then the recorder's reading, not the reader's.
|
|
30
|
+
*/
|
|
31
|
+
expected?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* One test case, as a source answers for it.
|
|
35
|
+
*
|
|
36
|
+
* Read strictly: an unknown key is refused rather than ignored, so a typo in a
|
|
37
|
+
* reader is reported where it was made instead of quietly costing a field.
|
|
38
|
+
*/
|
|
39
|
+
interface Case {
|
|
40
|
+
/**
|
|
41
|
+
* Path-shaped, `/`-separated, no extension — `todo/add_item`. No leading
|
|
42
|
+
* `/`, no `..`, no backslashes. Unique within the source and stable for the
|
|
43
|
+
* life of the case: ccqa files the case's recording and evidence under it,
|
|
44
|
+
* and it is what `{case}` expands to in the target's `testPath`.
|
|
45
|
+
*/
|
|
46
|
+
id: string;
|
|
47
|
+
/** Absolute path of the file that states the case. */
|
|
48
|
+
path: string;
|
|
49
|
+
/** That file verbatim. The audit and the failure classifier read it as written. */
|
|
50
|
+
text: string;
|
|
51
|
+
title: string;
|
|
52
|
+
/**
|
|
53
|
+
* `live` drives the case through the browser agent on every run;
|
|
54
|
+
* `deterministic` records it once and compiles a test.
|
|
55
|
+
*
|
|
56
|
+
* Two values, no spellings. A source that reads "manual" or "wip" out of its
|
|
57
|
+
* own documents decides for itself what that means — reading an unrecognised
|
|
58
|
+
* word as "record and generate" is how a case gets automated that nobody
|
|
59
|
+
* meant to automate.
|
|
60
|
+
*/
|
|
61
|
+
mode: "deterministic" | "live";
|
|
62
|
+
/** What to do, in order. A case with no steps describes nothing to record. */
|
|
63
|
+
steps: CaseStep[];
|
|
64
|
+
/** What to undo afterwards, whatever the outcome. Emitted into `afterEach`. */
|
|
65
|
+
cleanup?: CaseStep[];
|
|
66
|
+
/**
|
|
67
|
+
* What the case says must be true, unattached to any step. Which step
|
|
68
|
+
* delivers which is a reading of the flow, so ccqa's recorder makes it.
|
|
69
|
+
*/
|
|
70
|
+
expectations?: string[];
|
|
71
|
+
/**
|
|
72
|
+
* What the cleanup itself must make true. Kept apart from `expectations`,
|
|
73
|
+
* which are about the flow: these are decided where the undo runs, and
|
|
74
|
+
* asserting them among the case's own steps would check them too early.
|
|
75
|
+
*/
|
|
76
|
+
cleanupExpectations?: string[];
|
|
77
|
+
/**
|
|
78
|
+
* Sections ccqa does not interpret, handed to the recorder as context. A
|
|
79
|
+
* precondition belongs here: it says which account to sign in as and what
|
|
80
|
+
* must already exist, which is what whoever runs the case needs to read.
|
|
81
|
+
*/
|
|
82
|
+
context?: Array<{
|
|
83
|
+
heading: string;
|
|
84
|
+
body: string;
|
|
85
|
+
}>;
|
|
86
|
+
/**
|
|
87
|
+
* Values the target's `header` template and `titleTags.field` refer to, by
|
|
88
|
+
* whatever names this source gives them. ccqa passes them through and never
|
|
89
|
+
* reads one itself.
|
|
90
|
+
*/
|
|
91
|
+
fields?: Record<string, string>;
|
|
92
|
+
/** In the source, but opted out of runs and audits. */
|
|
93
|
+
disabled?: boolean;
|
|
94
|
+
}
|
|
95
|
+
/** Where a project's test cases come from. */
|
|
96
|
+
interface CaseSource {
|
|
97
|
+
/**
|
|
98
|
+
* Every case id this source holds. This is what a sweep audits and what
|
|
99
|
+
* `ccqa run` expands "all cases" to, so return only what you can load: a
|
|
100
|
+
* README sitting beside the cases is not one. ccqa sorts and de-duplicates.
|
|
101
|
+
*/
|
|
102
|
+
list(): Promise<string[]> | string[];
|
|
103
|
+
/**
|
|
104
|
+
* One case, by its id or by the path a CLI argument named — both spellings
|
|
105
|
+
* reach the same case, and the returned `id` is the authoritative one.
|
|
106
|
+
*
|
|
107
|
+
* Throw when the case cannot be read; ccqa reports what you threw and never
|
|
108
|
+
* reads a failure as an empty answer.
|
|
109
|
+
*/
|
|
110
|
+
load(ref: string): Promise<Case> | Case;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The module's default export: a function of the project root.
|
|
114
|
+
*
|
|
115
|
+
* `cwd` is the root ccqa resolved (`--cwd`, else the working directory), so a
|
|
116
|
+
* reader resolves its own paths against it rather than against `process.cwd()`.
|
|
117
|
+
*/
|
|
118
|
+
type CaseSourceFactory = (ctx: {
|
|
119
|
+
cwd: string;
|
|
120
|
+
}) => CaseSource | Promise<CaseSource>;
|
|
121
|
+
//#endregion
|
|
122
|
+
export { Case, CaseSource, CaseSourceFactory, CaseStep };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
//#region src/cases/contract.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* What a test case is, and how ccqa is handed one.
|
|
4
|
+
*
|
|
5
|
+
* ccqa reads its own `spec.yaml` and nothing else. Every other way of writing
|
|
6
|
+
* a test case — a team's markdown, a spreadsheet export, rows in a tracker —
|
|
7
|
+
* is read by a module that project owns and points `targets.<id>.cases` at.
|
|
8
|
+
* This file is the whole contract between the two, and the only part of ccqa a
|
|
9
|
+
* reader module sees.
|
|
10
|
+
*
|
|
11
|
+
* Published as the `ccqa/case-source` subpath, and **types only**: a reader
|
|
12
|
+
* imports nothing at runtime, so `// @ts-check` plus a JSDoc
|
|
13
|
+
* `@type {import("ccqa/case-source").CaseSourceFactory}` is the whole
|
|
14
|
+
* integration, and ccqa's own dependencies never reach the consumer's build.
|
|
15
|
+
* (The gate that refuses `ccqa/*` imports inside an emitted test does not
|
|
16
|
+
* apply here — a reader module is not a test.)
|
|
17
|
+
*
|
|
18
|
+
* What ccqa decides, not the reader: step numbering, where the case's working
|
|
19
|
+
* files live, and where its recording goes. A reader that assigned them would
|
|
20
|
+
* be answering for a directory it cannot see.
|
|
21
|
+
*/
|
|
22
|
+
/** One step of a case, as the document that states it wrote it. */
|
|
23
|
+
interface CaseStep {
|
|
24
|
+
/** What to do. */
|
|
25
|
+
instruction: string;
|
|
26
|
+
/**
|
|
27
|
+
* What this step must make true. Omit it when the case states its
|
|
28
|
+
* expectations once for the whole flow rather than per step — placing them
|
|
29
|
+
* is then the recorder's reading, not the reader's.
|
|
30
|
+
*/
|
|
31
|
+
expected?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* One test case, as a source answers for it.
|
|
35
|
+
*
|
|
36
|
+
* Read strictly: an unknown key is refused rather than ignored, so a typo in a
|
|
37
|
+
* reader is reported where it was made instead of quietly costing a field.
|
|
38
|
+
*/
|
|
39
|
+
interface Case {
|
|
40
|
+
/**
|
|
41
|
+
* Path-shaped, `/`-separated, no extension — `todo/add_item`. No leading
|
|
42
|
+
* `/`, no `..`, no backslashes. Unique within the source and stable for the
|
|
43
|
+
* life of the case: ccqa files the case's recording and evidence under it,
|
|
44
|
+
* and it is what `{case}` expands to in the target's `testPath`.
|
|
45
|
+
*/
|
|
46
|
+
id: string;
|
|
47
|
+
/** Absolute path of the file that states the case. */
|
|
48
|
+
path: string;
|
|
49
|
+
/** That file verbatim. The audit and the failure classifier read it as written. */
|
|
50
|
+
text: string;
|
|
51
|
+
title: string;
|
|
52
|
+
/**
|
|
53
|
+
* `live` drives the case through the browser agent on every run;
|
|
54
|
+
* `deterministic` records it once and compiles a test.
|
|
55
|
+
*
|
|
56
|
+
* Two values, no spellings. A source that reads "manual" or "wip" out of its
|
|
57
|
+
* own documents decides for itself what that means — reading an unrecognised
|
|
58
|
+
* word as "record and generate" is how a case gets automated that nobody
|
|
59
|
+
* meant to automate.
|
|
60
|
+
*/
|
|
61
|
+
mode: "deterministic" | "live";
|
|
62
|
+
/** What to do, in order. A case with no steps describes nothing to record. */
|
|
63
|
+
steps: CaseStep[];
|
|
64
|
+
/** What to undo afterwards, whatever the outcome. Emitted into `afterEach`. */
|
|
65
|
+
cleanup?: CaseStep[];
|
|
66
|
+
/**
|
|
67
|
+
* What the case says must be true, unattached to any step. Which step
|
|
68
|
+
* delivers which is a reading of the flow, so ccqa's recorder makes it.
|
|
69
|
+
*/
|
|
70
|
+
expectations?: string[];
|
|
71
|
+
/**
|
|
72
|
+
* What the cleanup itself must make true. Kept apart from `expectations`,
|
|
73
|
+
* which are about the flow: these are decided where the undo runs, and
|
|
74
|
+
* asserting them among the case's own steps would check them too early.
|
|
75
|
+
*/
|
|
76
|
+
cleanupExpectations?: string[];
|
|
77
|
+
/**
|
|
78
|
+
* Sections ccqa does not interpret, handed to the recorder as context. A
|
|
79
|
+
* precondition belongs here: it says which account to sign in as and what
|
|
80
|
+
* must already exist, which is what whoever runs the case needs to read.
|
|
81
|
+
*/
|
|
82
|
+
context?: Array<{
|
|
83
|
+
heading: string;
|
|
84
|
+
body: string;
|
|
85
|
+
}>;
|
|
86
|
+
/**
|
|
87
|
+
* Values the target's `header` template and `titleTags.field` refer to, by
|
|
88
|
+
* whatever names this source gives them. ccqa passes them through and never
|
|
89
|
+
* reads one itself.
|
|
90
|
+
*/
|
|
91
|
+
fields?: Record<string, string>;
|
|
92
|
+
/** In the source, but opted out of runs and audits. */
|
|
93
|
+
disabled?: boolean;
|
|
94
|
+
}
|
|
95
|
+
/** Where a project's test cases come from. */
|
|
96
|
+
interface CaseSource {
|
|
97
|
+
/**
|
|
98
|
+
* Every case id this source holds. This is what a sweep audits and what
|
|
99
|
+
* `ccqa run` expands "all cases" to, so return only what you can load: a
|
|
100
|
+
* README sitting beside the cases is not one. ccqa sorts and de-duplicates.
|
|
101
|
+
*/
|
|
102
|
+
list(): Promise<string[]> | string[];
|
|
103
|
+
/**
|
|
104
|
+
* One case, by its id or by the path a CLI argument named — both spellings
|
|
105
|
+
* reach the same case, and the returned `id` is the authoritative one.
|
|
106
|
+
*
|
|
107
|
+
* Throw when the case cannot be read; ccqa reports what you threw and never
|
|
108
|
+
* reads a failure as an empty answer.
|
|
109
|
+
*/
|
|
110
|
+
load(ref: string): Promise<Case> | Case;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The module's default export: a function of the project root.
|
|
114
|
+
*
|
|
115
|
+
* `cwd` is the root ccqa resolved (`--cwd`, else the working directory), so a
|
|
116
|
+
* reader resolves its own paths against it rather than against `process.cwd()`.
|
|
117
|
+
*/
|
|
118
|
+
type CaseSourceFactory = (ctx: {
|
|
119
|
+
cwd: string;
|
|
120
|
+
}) => CaseSource | Promise<CaseSource>;
|
|
121
|
+
//#endregion
|
|
122
|
+
export { Case, CaseSource, CaseSourceFactory, CaseStep };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -652,8 +652,8 @@ declare const ReportSpecResultSchema: z.ZodObject<{
|
|
|
652
652
|
title: z.ZodNullable<z.ZodString>;
|
|
653
653
|
target: z.ZodOptional<z.ZodString>;
|
|
654
654
|
mode: z.ZodOptional<z.ZodEnum<{
|
|
655
|
-
live: "live";
|
|
656
655
|
deterministic: "deterministic";
|
|
656
|
+
live: "live";
|
|
657
657
|
}>>;
|
|
658
658
|
status: z.ZodEnum<{
|
|
659
659
|
passed: "passed";
|
|
@@ -874,8 +874,8 @@ declare const RunReportDataSchema: z.ZodObject<{
|
|
|
874
874
|
title: z.ZodNullable<z.ZodString>;
|
|
875
875
|
target: z.ZodOptional<z.ZodString>;
|
|
876
876
|
mode: z.ZodOptional<z.ZodEnum<{
|
|
877
|
-
live: "live";
|
|
878
877
|
deterministic: "deterministic";
|
|
878
|
+
live: "live";
|
|
879
879
|
}>>;
|
|
880
880
|
status: z.ZodEnum<{
|
|
881
881
|
passed: "passed";
|
|
@@ -652,8 +652,8 @@ declare const ReportSpecResultSchema: z.ZodObject<{
|
|
|
652
652
|
title: z.ZodNullable<z.ZodString>;
|
|
653
653
|
target: z.ZodOptional<z.ZodString>;
|
|
654
654
|
mode: z.ZodOptional<z.ZodEnum<{
|
|
655
|
-
live: "live";
|
|
656
655
|
deterministic: "deterministic";
|
|
656
|
+
live: "live";
|
|
657
657
|
}>>;
|
|
658
658
|
status: z.ZodEnum<{
|
|
659
659
|
passed: "passed";
|
|
@@ -874,8 +874,8 @@ declare const RunReportDataSchema: z.ZodObject<{
|
|
|
874
874
|
title: z.ZodNullable<z.ZodString>;
|
|
875
875
|
target: z.ZodOptional<z.ZodString>;
|
|
876
876
|
mode: z.ZodOptional<z.ZodEnum<{
|
|
877
|
-
live: "live";
|
|
878
877
|
deterministic: "deterministic";
|
|
878
|
+
live: "live";
|
|
879
879
|
}>>;
|
|
880
880
|
status: z.ZodEnum<{
|
|
881
881
|
passed: "passed";
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccqa",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.56.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Browser test recorder powered by Claude Code and agent-browser",
|
|
6
6
|
"repository": {
|
|
@@ -54,6 +54,16 @@
|
|
|
54
54
|
"types": "./dist/runtime/judge.d.cts",
|
|
55
55
|
"default": "./dist/runtime/judge.cjs"
|
|
56
56
|
}
|
|
57
|
+
},
|
|
58
|
+
"./case-source": {
|
|
59
|
+
"import": {
|
|
60
|
+
"types": "./dist/cases/contract.d.mts",
|
|
61
|
+
"default": "./dist/cases/contract.mjs"
|
|
62
|
+
},
|
|
63
|
+
"require": {
|
|
64
|
+
"types": "./dist/cases/contract.d.cts",
|
|
65
|
+
"default": "./dist/cases/contract.cjs"
|
|
66
|
+
}
|
|
57
67
|
}
|
|
58
68
|
},
|
|
59
69
|
"typesVersions": {
|
|
@@ -69,6 +79,9 @@
|
|
|
69
79
|
],
|
|
70
80
|
"judge": [
|
|
71
81
|
"dist/runtime/judge.d.mts"
|
|
82
|
+
],
|
|
83
|
+
"case-source": [
|
|
84
|
+
"dist/cases/contract.d.mts"
|
|
72
85
|
]
|
|
73
86
|
}
|
|
74
87
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccqa",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.56.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Browser test recorder powered by Claude Code and agent-browser",
|
|
6
6
|
"repository": {
|
|
@@ -54,6 +54,16 @@
|
|
|
54
54
|
"types": "./dist/runtime/judge.d.cts",
|
|
55
55
|
"default": "./dist/runtime/judge.cjs"
|
|
56
56
|
}
|
|
57
|
+
},
|
|
58
|
+
"./case-source": {
|
|
59
|
+
"import": {
|
|
60
|
+
"types": "./dist/cases/contract.d.mts",
|
|
61
|
+
"default": "./dist/cases/contract.mjs"
|
|
62
|
+
},
|
|
63
|
+
"require": {
|
|
64
|
+
"types": "./dist/cases/contract.d.cts",
|
|
65
|
+
"default": "./dist/cases/contract.cjs"
|
|
66
|
+
}
|
|
57
67
|
}
|
|
58
68
|
},
|
|
59
69
|
"typesVersions": {
|
|
@@ -69,6 +79,9 @@
|
|
|
69
79
|
],
|
|
70
80
|
"judge": [
|
|
71
81
|
"dist/runtime/judge.d.mts"
|
|
82
|
+
],
|
|
83
|
+
"case-source": [
|
|
84
|
+
"dist/cases/contract.d.mts"
|
|
72
85
|
]
|
|
73
86
|
}
|
|
74
87
|
},
|