form-tester 0.7.0 → 0.7.1
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.
|
@@ -20,7 +20,10 @@ form-tester install --global # or install to ~/.claude/skills/
|
|
|
20
20
|
form-tester test <url> --auto
|
|
21
21
|
form-tester test <url> --auto --pnr 12345 --persona ung-mann --scenario "test validation"
|
|
22
22
|
|
|
23
|
-
# Interactive
|
|
23
|
+
# Interactive mode (prompts for persona, scenario, etc.):
|
|
24
|
+
form-tester test <url> --human
|
|
25
|
+
|
|
26
|
+
# Full interactive CLI:
|
|
24
27
|
form-tester
|
|
25
28
|
```
|
|
26
29
|
|
package/form-tester.js
CHANGED
|
@@ -6,7 +6,7 @@ const { spawn, execSync } = require("child_process");
|
|
|
6
6
|
|
|
7
7
|
const CONFIG_PATH = path.join(process.cwd(), "form-tester.config.json");
|
|
8
8
|
const OUTPUT_BASE = path.resolve(process.cwd(), "output");
|
|
9
|
-
const LOCAL_VERSION = "0.7.
|
|
9
|
+
const LOCAL_VERSION = "0.7.1";
|
|
10
10
|
const RECOMMENDED_PERSON = "Uromantisk Direktør";
|
|
11
11
|
|
|
12
12
|
// Recording — persisted to disk so `form-tester exec` can append across processes
|
|
@@ -1300,6 +1300,17 @@ async function main() {
|
|
|
1300
1300
|
process.exit(0);
|
|
1301
1301
|
}
|
|
1302
1302
|
|
|
1303
|
+
if (args[0] === "test" && args.includes("--human")) {
|
|
1304
|
+
const config = loadConfig();
|
|
1305
|
+
const url = args.find((a) => a.startsWith("http"));
|
|
1306
|
+
if (!url) {
|
|
1307
|
+
console.error("Usage: form-tester test <url> --human");
|
|
1308
|
+
process.exit(1);
|
|
1309
|
+
}
|
|
1310
|
+
await handleTest(url, config);
|
|
1311
|
+
process.exit(0);
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1303
1314
|
if (args[0] === "test" && args.includes("--auto")) {
|
|
1304
1315
|
const config = loadConfig();
|
|
1305
1316
|
const url = args.find((a) => a.startsWith("http"));
|
|
@@ -1362,5 +1373,8 @@ module.exports = {
|
|
|
1362
1373
|
getPersonaById,
|
|
1363
1374
|
formatPersonaList,
|
|
1364
1375
|
promptScenario,
|
|
1376
|
+
startRecording,
|
|
1377
|
+
appendToRecording,
|
|
1378
|
+
finalizeRecording,
|
|
1365
1379
|
};
|
|
1366
1380
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
const test = require("node:test");
|
|
2
2
|
const assert = require("node:assert/strict");
|
|
3
3
|
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
const os = require("node:os");
|
|
7
|
+
|
|
4
8
|
const {
|
|
5
9
|
extractFormId,
|
|
6
10
|
extractPnrFromUrl,
|
|
@@ -14,6 +18,9 @@ const {
|
|
|
14
18
|
getPersonaById,
|
|
15
19
|
formatPersonaList,
|
|
16
20
|
promptScenario,
|
|
21
|
+
startRecording,
|
|
22
|
+
appendToRecording,
|
|
23
|
+
finalizeRecording,
|
|
17
24
|
} = require("../form-tester");
|
|
18
25
|
|
|
19
26
|
test("extractFormId returns form id from skjemautfyller URL", () => {
|
|
@@ -118,3 +125,58 @@ test("each persona has a unique id", () => {
|
|
|
118
125
|
test("promptScenario is exported as a function", () => {
|
|
119
126
|
assert.equal(typeof promptScenario, "function");
|
|
120
127
|
});
|
|
128
|
+
|
|
129
|
+
// --- Recording tests ---
|
|
130
|
+
|
|
131
|
+
function makeTmpDir() {
|
|
132
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), "form-tester-test-"));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
test("startRecording creates recording.json with empty commands", () => {
|
|
136
|
+
const dir = makeTmpDir();
|
|
137
|
+
const filePath = startRecording(dir);
|
|
138
|
+
assert.equal(filePath, path.join(dir, "recording.json"));
|
|
139
|
+
const data = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
140
|
+
assert.equal(data.commandCount, 0);
|
|
141
|
+
assert.deepEqual(data.commands, []);
|
|
142
|
+
assert.ok(data.startedAt);
|
|
143
|
+
assert.equal(data.completedAt, null);
|
|
144
|
+
fs.rmSync(dir, { recursive: true });
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("appendToRecording adds commands to recording file", () => {
|
|
148
|
+
const dir = makeTmpDir();
|
|
149
|
+
const filePath = startRecording(dir);
|
|
150
|
+
appendToRecording(filePath, ["open", "https://example.com"]);
|
|
151
|
+
appendToRecording(filePath, ["fill", "e1", "hello"]);
|
|
152
|
+
appendToRecording(filePath, ["click", "e3"]);
|
|
153
|
+
const data = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
154
|
+
assert.equal(data.commandCount, 3);
|
|
155
|
+
assert.deepEqual(data.commands[0].args, ["open", "https://example.com"]);
|
|
156
|
+
assert.deepEqual(data.commands[1].args, ["fill", "e1", "hello"]);
|
|
157
|
+
assert.deepEqual(data.commands[2].args, ["click", "e3"]);
|
|
158
|
+
assert.ok(data.commands[0].timestamp);
|
|
159
|
+
fs.rmSync(dir, { recursive: true });
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test("finalizeRecording sets completedAt timestamp", () => {
|
|
163
|
+
const dir = makeTmpDir();
|
|
164
|
+
const filePath = startRecording(dir);
|
|
165
|
+
appendToRecording(filePath, ["snapshot"]);
|
|
166
|
+
const result = finalizeRecording(filePath);
|
|
167
|
+
assert.equal(result, filePath);
|
|
168
|
+
const data = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
169
|
+
assert.ok(data.completedAt);
|
|
170
|
+
assert.equal(data.commandCount, 1);
|
|
171
|
+
fs.rmSync(dir, { recursive: true });
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("finalizeRecording returns null for missing file", () => {
|
|
175
|
+
assert.equal(finalizeRecording("/nonexistent/recording.json"), null);
|
|
176
|
+
assert.equal(finalizeRecording(null), null);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test("appendToRecording is resilient to missing file", () => {
|
|
180
|
+
// Should not throw
|
|
181
|
+
appendToRecording("/nonexistent/recording.json", ["click", "e1"]);
|
|
182
|
+
});
|