ccqa 0.1.6 → 0.3.3

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.
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "ccqa",
3
+ "version": "0.3.3",
4
+ "type": "module",
5
+ "description": "Browser test recorder powered by Claude Code and agent-browser",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/shibukazu/ccqa.git"
9
+ },
10
+ "homepage": "https://github.com/shibukazu/ccqa#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/shibukazu/ccqa/issues"
13
+ },
14
+ "bin": {
15
+ "ccqa": "./dist/bin/ccqa.mjs"
16
+ },
17
+ "exports": {
18
+ "./test-helpers": {
19
+ "types": "./dist/runtime/test-helpers.d.mts",
20
+ "import": "./dist/runtime/test-helpers.mjs"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist/"
25
+ ],
26
+ "dependencies": {
27
+ "@anthropic-ai/claude-agent-sdk": "^0.2.87",
28
+ "@anthropic-ai/claude-code": "^2.1.87",
29
+ "commander": "^14.0.3",
30
+ "gray-matter": "^4.0.3",
31
+ "zod": "^4.3.6"
32
+ },
33
+ "peerDependencies": {
34
+ "agent-browser": "*",
35
+ "vitest": ">=2.0.0"
36
+ },
37
+ "peerDependenciesMeta": {
38
+ "agent-browser": {
39
+ "optional": false
40
+ },
41
+ "vitest": {
42
+ "optional": false
43
+ }
44
+ },
45
+ "engines": {
46
+ "node": ">=20"
47
+ }
48
+ }
@@ -0,0 +1,22 @@
1
+ //#region src/runtime/test-helpers.d.ts
2
+ declare function ab(...args: string[]): void;
3
+ /** Wait for element/text with an explicit timeout so long-running async ops don't hang. */
4
+ declare function abWait(selector: string, timeoutMs?: number): void;
5
+ /** Assert stable text is visible on page (via wait --text). */
6
+ declare function abAssertTextVisible(text: string, timeoutMs?: number): void;
7
+ /** Assert element is visible (via wait). */
8
+ declare function abAssertVisible(selector: string, timeoutMs?: number): void;
9
+ /** Assert element is NOT visible (via wait --state hidden or --fn for text). */
10
+ declare function abAssertNotVisible(selector: string, timeoutMs?: number): void;
11
+ /** Assert URL contains a pattern (via get url). */
12
+ declare function abAssertUrl(pattern: string): void;
13
+ /** Assert element is enabled (via is enabled). */
14
+ declare function abAssertEnabled(selector: string): void;
15
+ /** Assert element is disabled (via is enabled). */
16
+ declare function abAssertDisabled(selector: string): void;
17
+ /** Assert checkbox is checked (via is checked). */
18
+ declare function abAssertChecked(selector: string): void;
19
+ /** Assert checkbox is unchecked (via is checked). */
20
+ declare function abAssertUnchecked(selector: string): void;
21
+ //#endregion
22
+ export { ab, abAssertChecked, abAssertDisabled, abAssertEnabled, abAssertNotVisible, abAssertTextVisible, abAssertUnchecked, abAssertUrl, abAssertVisible, abWait };
@@ -0,0 +1,144 @@
1
+ import { createRequire } from "node:module";
2
+ import { spawnSync } from "node:child_process";
3
+ //#region src/runtime/test-helpers.ts
4
+ const AB = createRequire(import.meta.url).resolve("agent-browser/bin/agent-browser.js");
5
+ function spawnAB(args) {
6
+ const result = spawnSync(AB, args, { stdio: "pipe" });
7
+ return {
8
+ status: result.status,
9
+ stdout: result.stdout?.toString() ?? "",
10
+ stderr: result.stderr?.toString() ?? ""
11
+ };
12
+ }
13
+ function logStep(action, args) {
14
+ const pretty = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
15
+ process.stdout.write(` ▶ ${action.padEnd(14)} ${pretty}\n`);
16
+ }
17
+ function fail(summary, result) {
18
+ process.stdout.write(` ✗ ${summary}\n`);
19
+ const details = [result.stdout, result.stderr].map((s) => s.trim()).filter(Boolean).join("\n");
20
+ if (details) for (const line of details.split("\n")) process.stdout.write(` ${line}\n`);
21
+ throw new Error(summary);
22
+ }
23
+ function ab(...args) {
24
+ const [command = "", ...rest] = args;
25
+ logStep(command, rest);
26
+ const result = spawnAB(args);
27
+ if (result.status !== 0) fail(`agent-browser ${command} failed (exit ${result.status})`, result);
28
+ }
29
+ /** Wait for element/text with an explicit timeout so long-running async ops don't hang. */
30
+ function abWait(selector, timeoutMs = 18e4) {
31
+ logStep("wait", [selector]);
32
+ const result = spawnAB(selector.startsWith("text=") ? [
33
+ "wait",
34
+ "--text",
35
+ selector.slice(5),
36
+ "--timeout",
37
+ String(timeoutMs)
38
+ ] : [
39
+ "wait",
40
+ selector,
41
+ "--timeout",
42
+ String(timeoutMs)
43
+ ]);
44
+ if (result.status !== 0) fail(`wait failed: ${selector}`, result);
45
+ }
46
+ /** Assert stable text is visible on page (via wait --text). */
47
+ function abAssertTextVisible(text, timeoutMs = 3e4) {
48
+ logStep("assert.text", [text]);
49
+ const result = spawnAB([
50
+ "wait",
51
+ "--text",
52
+ text,
53
+ "--timeout",
54
+ String(timeoutMs)
55
+ ]);
56
+ if (result.status !== 0) fail(`Assertion failed: text ${JSON.stringify(text)} not found within ${timeoutMs}ms`, result);
57
+ }
58
+ /** Assert element is visible (via wait). */
59
+ function abAssertVisible(selector, timeoutMs = 3e4) {
60
+ logStep("assert.visible", [selector]);
61
+ const result = spawnAB([
62
+ "wait",
63
+ selector,
64
+ "--timeout",
65
+ String(timeoutMs)
66
+ ]);
67
+ if (result.status !== 0) fail(`Assertion failed: ${JSON.stringify(selector)} not visible within ${timeoutMs}ms`, result);
68
+ }
69
+ /** Assert element is NOT visible (via wait --state hidden or --fn for text). */
70
+ function abAssertNotVisible(selector, timeoutMs = 3e4) {
71
+ logStep("assert.hidden", [selector]);
72
+ const result = spawnAB(selector.startsWith("text=") ? [
73
+ "wait",
74
+ "--fn",
75
+ `!document.body.innerText.includes(${JSON.stringify(selector.slice(5))})`,
76
+ "--timeout",
77
+ String(timeoutMs)
78
+ ] : [
79
+ "wait",
80
+ selector,
81
+ "--state",
82
+ "hidden",
83
+ "--timeout",
84
+ String(timeoutMs)
85
+ ]);
86
+ if (result.status !== 0) fail(`Assertion failed: ${JSON.stringify(selector)} still visible after ${timeoutMs}ms`, result);
87
+ }
88
+ /** Assert URL contains a pattern (via get url). */
89
+ function abAssertUrl(pattern) {
90
+ logStep("assert.url", [pattern]);
91
+ const result = spawnAB(["get", "url"]);
92
+ const url = result.stdout.trim();
93
+ if (!url.includes(pattern)) fail(`Assertion failed: URL ${JSON.stringify(url)} does not contain ${JSON.stringify(pattern)}`, result);
94
+ }
95
+ /** Assert element is enabled (via is enabled). */
96
+ function abAssertEnabled(selector) {
97
+ logStep("assert.enabled", [selector]);
98
+ const result = spawnAB([
99
+ "is",
100
+ "enabled",
101
+ selector
102
+ ]);
103
+ if (result.status !== 0) fail(`Assertion failed: element ${JSON.stringify(selector)} not found`, result);
104
+ const value = result.stdout.trim();
105
+ if (value !== "true") fail(`Assertion failed: ${JSON.stringify(selector)} is not enabled (got: ${value})`, result);
106
+ }
107
+ /** Assert element is disabled (via is enabled). */
108
+ function abAssertDisabled(selector) {
109
+ logStep("assert.disabled", [selector]);
110
+ const result = spawnAB([
111
+ "is",
112
+ "enabled",
113
+ selector
114
+ ]);
115
+ if (result.status !== 0) fail(`Assertion failed: element ${JSON.stringify(selector)} not found`, result);
116
+ const value = result.stdout.trim();
117
+ if (value !== "false") fail(`Assertion failed: ${JSON.stringify(selector)} is not disabled (got: ${value})`, result);
118
+ }
119
+ /** Assert checkbox is checked (via is checked). */
120
+ function abAssertChecked(selector) {
121
+ logStep("assert.checked", [selector]);
122
+ const result = spawnAB([
123
+ "is",
124
+ "checked",
125
+ selector
126
+ ]);
127
+ if (result.status !== 0) fail(`Assertion failed: element ${JSON.stringify(selector)} not found`, result);
128
+ const value = result.stdout.trim();
129
+ if (value !== "true") fail(`Assertion failed: ${JSON.stringify(selector)} is not checked (got: ${value})`, result);
130
+ }
131
+ /** Assert checkbox is unchecked (via is checked). */
132
+ function abAssertUnchecked(selector) {
133
+ logStep("assert.unchecked", [selector]);
134
+ const result = spawnAB([
135
+ "is",
136
+ "checked",
137
+ selector
138
+ ]);
139
+ if (result.status !== 0) fail(`Assertion failed: element ${JSON.stringify(selector)} not found`, result);
140
+ const value = result.stdout.trim();
141
+ if (value !== "false") fail(`Assertion failed: ${JSON.stringify(selector)} is not unchecked (got: ${value})`, result);
142
+ }
143
+ //#endregion
144
+ export { ab, abAssertChecked, abAssertDisabled, abAssertEnabled, abAssertNotVisible, abAssertTextVisible, abAssertUnchecked, abAssertUrl, abAssertVisible, abWait };