form-tester 0.7.3 → 0.8.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.
|
@@ -69,22 +69,27 @@ Dokumenter verification (only when modal confirms storage):
|
|
|
69
69
|
1. Navigate to `/dokumenter?pnr={PNR}` and select the same person used during form fill.
|
|
70
70
|
2. The document list loads sorted newest first. The first entry should match the form title.
|
|
71
71
|
3. Click "Se detaljer" on the first document, then click "Åpne dokumentet".
|
|
72
|
-
4.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
72
|
+
4. After clicking "Åpne dokumentet", the document may open in a dialog, a new tab, or inline. FIRST determine the format before capturing:
|
|
73
|
+
|
|
74
|
+
Step A — Detect format:
|
|
75
|
+
Run `form-tester exec snapshot` and examine the result.
|
|
76
|
+
- If you see an iframe/embed/object with a src containing `.pdf`, `blob:`, or a PDF viewer → it's a PDF.
|
|
77
|
+
- If you see rendered HTML content (headings, paragraphs, form data) → it's HTML.
|
|
78
|
+
- If `--full-page` screenshot times out → it's almost certainly a PDF viewer. Do NOT retry the screenshot. Switch to PDF download.
|
|
79
|
+
|
|
80
|
+
Step B — PDF documents (viewer in dialog/modal/iframe/new tab):
|
|
81
|
+
Do NOT screenshot PDFs — it will timeout or produce garbage. Download the file:
|
|
82
|
+
1. Extract PDF URL from the iframe/embed/object:
|
|
83
|
+
`form-tester exec eval "document.querySelector('iframe')?.src || document.querySelector('embed')?.src || document.querySelector('object')?.data"`
|
|
84
|
+
2. If the result is a URL, download it with run-code:
|
|
85
|
+
`form-tester exec run-code "async page => { const url = await page.evaluate(() => document.querySelector('iframe')?.src || document.querySelector('embed')?.src || document.querySelector('object')?.data); if (url) { const resp = await page.request.get(url); require('fs').writeFileSync('$OUTPUT_DIR/document.pdf', await resp.body()); } }"`
|
|
86
|
+
3. Or if the PDF viewer has a download button, click it.
|
|
87
|
+
4. Record in test_results.txt: document type PDF, downloaded to document.pdf.
|
|
88
|
+
|
|
89
|
+
Step C — HTML documents:
|
|
90
|
+
Take a FULL-PAGE screenshot (`form-tester exec screenshot --filename "$OUTPUT_DIR/document_screenshot.png" --full-page`).
|
|
91
|
+
Also save raw HTML: `form-tester exec eval "document.documentElement.outerHTML"` → save to document.html.
|
|
92
|
+
|
|
93
|
+
Step D — XML/other: Note type in test_results.txt, skip capture.
|
|
89
94
|
|
|
90
95
|
5. Include the document verification results in test_results.txt (document title, whether it matched the form h1, document type: HTML/PDF/XML).
|
|
@@ -82,13 +82,14 @@ After submission, read the modal text:
|
|
|
82
82
|
- If it mentions Dokumenter storage -> navigate to `/dokumenter?pnr={PNR}`, verify the document appears.
|
|
83
83
|
- If it does NOT mention Dokumenter -> skip verification, note in test_results.txt.
|
|
84
84
|
|
|
85
|
-
Document capture
|
|
85
|
+
Document capture — FIRST detect the format by running `form-tester exec snapshot`:
|
|
86
86
|
|
|
87
|
-
**PDF documents** (
|
|
88
|
-
1.
|
|
89
|
-
2.
|
|
90
|
-
3.
|
|
87
|
+
**PDF documents** (iframe/embed with .pdf or blob: URL, or screenshot times out): Do NOT screenshot PDFs. Download instead:
|
|
88
|
+
1. Extract URL: `form-tester exec eval "document.querySelector('iframe')?.src || document.querySelector('embed')?.src || document.querySelector('object')?.data"`
|
|
89
|
+
2. Download: `form-tester exec run-code "async page => { const url = await page.evaluate(() => document.querySelector('iframe')?.src || document.querySelector('embed')?.src || document.querySelector('object')?.data); if (url) { const resp = await page.request.get(url); require('fs').writeFileSync('OUTPUT_DIR/document.pdf', await resp.body()); } }"`
|
|
90
|
+
3. Or click the download button in the PDF viewer if available.
|
|
91
|
+
4. If `--full-page` screenshot times out, it's a PDF — switch to download, don't retry screenshot.
|
|
91
92
|
|
|
92
|
-
**HTML documents**:
|
|
93
|
+
**HTML documents**: `form-tester exec screenshot --filename "..." --full-page`. Also save raw HTML.
|
|
93
94
|
|
|
94
95
|
**XML/other**: note the type in test_results.txt and skip capture.
|
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.
|
|
9
|
+
const LOCAL_VERSION = "0.8.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
|
|
@@ -466,18 +466,26 @@ function clearConsole() {
|
|
|
466
466
|
function printHelp() {
|
|
467
467
|
console.log(
|
|
468
468
|
[
|
|
469
|
-
"
|
|
470
|
-
"
|
|
471
|
-
"
|
|
472
|
-
"
|
|
469
|
+
"",
|
|
470
|
+
"Subcommands (run directly):",
|
|
471
|
+
" form-tester install [--global] Install skill files into project or ~/.claude/skills/",
|
|
472
|
+
" form-tester test <url> --auto Non-interactive test (for AI agents)",
|
|
473
|
+
" form-tester test <url> --human Interactive test with prompts",
|
|
474
|
+
" form-tester exec <command> [args] Run playwright-cli command (recorded)",
|
|
475
|
+
" form-tester replay <recording.json> Replay a recorded test run",
|
|
476
|
+
"",
|
|
477
|
+
"Interactive commands:",
|
|
478
|
+
" /test {url} Open form URL and start test",
|
|
479
|
+
" /save {label} Save snapshot + screenshot to output folder",
|
|
473
480
|
" /people Scan visible person list and prompt selection",
|
|
474
481
|
" /persona List available personas",
|
|
475
|
-
" /
|
|
476
|
-
" /
|
|
482
|
+
" /recording Show active recording status",
|
|
483
|
+
" /setup Install Playwright CLI + skills if missing",
|
|
484
|
+
" /update Update Playwright CLI and skills",
|
|
485
|
+
" /version Show version",
|
|
477
486
|
" /clear Clear the console",
|
|
478
487
|
" /help Show this help",
|
|
479
|
-
" /
|
|
480
|
-
" /quit Exit the app",
|
|
488
|
+
" /quit Exit",
|
|
481
489
|
].join("\n"),
|
|
482
490
|
);
|
|
483
491
|
}
|
|
@@ -955,12 +963,10 @@ async function handleTest(url, config) {
|
|
|
955
963
|
"/dokumenter?pnr={PNR}",
|
|
956
964
|
);
|
|
957
965
|
|
|
958
|
-
//
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
console.log(`Replay with: form-tester replay "${recordingPath}"`);
|
|
963
|
-
}
|
|
966
|
+
// Don't finalize recording — exec commands will keep appending.
|
|
967
|
+
console.log(`Recording active: ${config.activeRecording}`);
|
|
968
|
+
console.log(`Use 'form-tester exec' for all playwright-cli commands to record them.`);
|
|
969
|
+
console.log(`Recording finalizes on 'form-tester exec close'.`);
|
|
964
970
|
}
|
|
965
971
|
|
|
966
972
|
async function handleTestAuto(url, config, flags) {
|
|
@@ -1073,12 +1079,11 @@ async function handleTestAuto(url, config, flags) {
|
|
|
1073
1079
|
printNextSteps(outputDir, dokumenterUrl || "/dokumenter?pnr={PNR}");
|
|
1074
1080
|
}
|
|
1075
1081
|
|
|
1076
|
-
//
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
}
|
|
1082
|
+
// Don't finalize recording here — `form-tester exec` commands will keep appending.
|
|
1083
|
+
// Recording is finalized when `form-tester exec close` is called.
|
|
1084
|
+
log(`Recording active: ${config.activeRecording}`);
|
|
1085
|
+
log(`Use 'form-tester exec' for all playwright-cli commands to record them.`);
|
|
1086
|
+
log(`Recording finalizes on 'form-tester exec close'.`);
|
|
1082
1087
|
}
|
|
1083
1088
|
|
|
1084
1089
|
async function handleReplay(filePath) {
|
|
@@ -1140,6 +1145,18 @@ async function handleCommand(line, config) {
|
|
|
1140
1145
|
await saveArtifacts(config, label);
|
|
1141
1146
|
break;
|
|
1142
1147
|
}
|
|
1148
|
+
case "/recording": {
|
|
1149
|
+
const rec = config.activeRecording;
|
|
1150
|
+
if (rec && fs.existsSync(rec)) {
|
|
1151
|
+
const data = JSON.parse(fs.readFileSync(rec, "utf8"));
|
|
1152
|
+
console.log(`Active recording: ${rec}`);
|
|
1153
|
+
console.log(`Commands recorded: ${data.commandCount}`);
|
|
1154
|
+
console.log(`Started: ${data.startedAt}`);
|
|
1155
|
+
} else {
|
|
1156
|
+
console.log("No active recording. Start a test with /test to begin recording.");
|
|
1157
|
+
}
|
|
1158
|
+
break;
|
|
1159
|
+
}
|
|
1143
1160
|
case "/clear":
|
|
1144
1161
|
case "/cls":
|
|
1145
1162
|
clearConsole();
|
package/package.json
CHANGED