form-tester 0.4.3 → 0.5.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.
@@ -45,6 +45,7 @@ Notes:
45
45
  - Use `--help` or `-h` to print the command list without starting the prompt.
46
46
  - Playwright CLI commands are available from this skill when needed.
47
47
  - IMPORTANT: All screenshots taken during a test run MUST use `--full-page` to capture the entire page, not just the viewport. This applies to every screenshot command: `playwright-cli screenshot --filename "..." --full-page`
48
+ - IMPORTANT: Take a full-page screenshot EVERY TIME the page changes. This includes: after clicking any action button (Neste, Forrige, Send inn, etc.), after a step/page transition, after form validation errors appear, after modals open, and after submission. Name screenshots descriptively (e.g., step1_filled.png, step2_before_submit.png, submit_result.png).
48
49
 
49
50
  Test flow (when /test is triggered):
50
51
  IMPORTANT: Each prompt below MUST be asked as a separate message to the user. Wait for the user's response before proceeding to the next step. Do NOT combine multiple prompts into one message.
@@ -63,7 +64,8 @@ Dokumenter verification (only when modal confirms storage):
63
64
  1. Navigate to `/dokumenter?pnr={PNR}` and select the same person used during form fill.
64
65
  2. The document list loads sorted newest first. The first entry should match the form title.
65
66
  3. Click "Se detaljer" on the first document, then click "Åpne dokumentet".
66
- 4. If the document opens in a new tab as HTML: switch to that tab, take a full-page screenshot (`--full-page`), save snapshot and raw HTML.
67
- 5. If the document opens as a PDF viewer: download the PDF instead of screenshotting. Use `playwright-cli pdf --filename "$OUTPUT_DIR/document.pdf"` or save it via the download.
68
- 6. If the document does NOT open (XML format, no new tab, or other): note the document type in test_results.txt and skip the screenshot/download.
69
- 7. Include the document verification results in test_results.txt (document title, whether it matched the form h1, document type: HTML/PDF/XML).
67
+ 4. IMPORTANT - document capture depends on format:
68
+ - PDF documents: DOWNLOAD the file. Use `playwright-cli pdf --filename "$OUTPUT_DIR/document.pdf"` or save via browser download. Do NOT screenshot PDFs.
69
+ - HTML documents: Take a FULL-PAGE screenshot of the ENTIRE document (`playwright-cli screenshot --filename "$OUTPUT_DIR/document_screenshot.png" --full-page`). HTML documents cannot be downloaded as files, so the full-page screenshot is the primary artifact. Also save the snapshot and raw HTML.
70
+ - XML/other formats: Note the document type in test_results.txt and skip capture.
71
+ 5. Include the document verification results in test_results.txt (document title, whether it matched the form h1, document type: HTML/PDF/XML).
@@ -62,11 +62,17 @@ When `/test` is triggered:
62
62
 
63
63
  - Provide a full /skjemautfyller URL. If `pnr` is missing, the CLI will prompt.
64
64
  - All screenshots MUST use `--full-page` to capture the entire page.
65
+ - Take a full-page screenshot EVERY TIME the page changes: after clicking action buttons (Neste, Forrige, Send inn), after step/page transitions, after validation errors, after modals, and after submission.
65
66
  - Use `/save {label}` to capture additional snapshots into the output folder.
66
67
  - If an error modal appears on submit, open DevTools -> Network, retry once, and capture the Correlation ID header.
67
68
 
68
69
  ## Post-Submit Verification
69
70
 
70
71
  After submission, read the modal text:
71
- - If it mentions Dokumenter storage -> navigate to `/dokumenter?pnr={PNR}`, verify the document appears, and capture it (screenshot for HTML, download for PDF).
72
+ - If it mentions Dokumenter storage -> navigate to `/dokumenter?pnr={PNR}`, verify the document appears.
72
73
  - If it does NOT mention Dokumenter -> skip verification, note in test_results.txt.
74
+
75
+ Document capture depends on format:
76
+ - **PDF documents**: download the file (`playwright-cli pdf --filename "..." `). Do NOT screenshot PDFs.
77
+ - **HTML documents**: take a full-page screenshot of the ENTIRE document (`playwright-cli screenshot --filename "..." --full-page`). HTML documents cannot be downloaded, so the screenshot is the primary artifact.
78
+ - **XML/other**: note the type in test_results.txt and skip capture.
package/README.md CHANGED
@@ -69,6 +69,42 @@ If Copilot doesn't recognize the skill:
69
69
  1. Make sure `.claude/skills/form-tester/` exists in your project (run `form-tester install`)
70
70
  2. Run `/skills` in the Copilot CLI to reload skills, or restart the session
71
71
 
72
+ ## Skip permission prompts
73
+
74
+ By default, AI agents will ask permission for every shell command. To run without interruptions, pre-allow the relevant tools.
75
+
76
+ ### Claude Code
77
+
78
+ Add to your project's `.claude/settings.local.json` (or global `~/.claude/settings.json`):
79
+
80
+ ```json
81
+ {
82
+ "permissions": {
83
+ "allow": [
84
+ "Skill(form-tester)",
85
+ "Bash(form-tester:*)",
86
+ "Bash(playwright-cli:*)"
87
+ ]
88
+ }
89
+ }
90
+ ```
91
+
92
+ Or use the Claude Code CLI:
93
+ ```bash
94
+ claude config add permissions.allow "Skill(form-tester)"
95
+ claude config add permissions.allow "Bash(form-tester:*)"
96
+ claude config add permissions.allow "Bash(playwright-cli:*)"
97
+ ```
98
+
99
+ ### GitHub Copilot
100
+
101
+ In Copilot CLI, use auto-approve mode:
102
+ ```bash
103
+ copilot --auto-approve
104
+ ```
105
+
106
+ Or approve the tool categories when first prompted and select "Always allow".
107
+
72
108
  ## Test Output
73
109
 
74
110
  Test runs are saved to `output/{form-id}/{timestamp}/` with:
@@ -76,6 +112,13 @@ Test runs are saved to `output/{form-id}/{timestamp}/` with:
76
112
  - Screenshots (PNG, full-page)
77
113
  - `test_results.txt`
78
114
 
115
+ ### Dokumenter verification
116
+
117
+ After form submission, some forms store a copy in Dokumenter. The document type determines how to capture it:
118
+
119
+ - **PDF documents** — download the file directly (`playwright-cli pdf` or via browser download)
120
+ - **HTML documents** — take a full-page screenshot of the entire document (`playwright-cli screenshot --filename "..." --full-page`). HTML documents cannot be downloaded as-is, so the screenshot is the primary artifact.
121
+
79
122
  ## Update
80
123
 
81
124
  ```bash
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.4.3";
9
+ const LOCAL_VERSION = "0.5.1";
10
10
  const RECOMMENDED_PERSON = "Uromantisk Direktør";
11
11
 
12
12
  const PERSONAS = [
@@ -880,15 +880,20 @@ async function handleTest(url, config) {
880
880
  }
881
881
 
882
882
  async function handleTestAuto(url, config, flags) {
883
- // Resolve PNR
884
- const pnr = flags.pnr || config.pnr;
883
+ const v = flags.verbosity || "normal";
884
+ const log = (msg) => { if (v !== "silent") console.log(msg); };
885
+ const verbose = (msg) => { if (v === "verbose") console.log(msg); };
886
+
887
+ // Resolve PNR — check URL first, then flag, then config
888
+ const pnr = extractPnrFromUrl(url) || flags.pnr || config.pnr;
885
889
  if (!pnr) {
886
- console.error("No PNR available. Pass --pnr <value> or set it in form-tester.config.json");
890
+ console.error("No PNR available. Pass --pnr <value>, include pnr= in the URL, or set it in form-tester.config.json");
887
891
  process.exit(1);
888
892
  }
889
893
  const fullUrl = extractPnrFromUrl(url) ? url : setPnrOnUrl(url, pnr);
890
894
  config.pnr = pnr;
891
895
  saveConfig(config);
896
+ verbose(`URL: ${fullUrl}`);
892
897
 
893
898
  // Resolve persona
894
899
  let personaChoice;
@@ -896,14 +901,14 @@ async function handleTestAuto(url, config, flags) {
896
901
  if (personaId) {
897
902
  const found = getPersonaById(personaId);
898
903
  if (found) {
899
- console.log(`Persona: ${found.name} — ${found.description}`);
904
+ log(`Persona: ${found.name} — ${found.description}`);
900
905
  personaChoice = { type: "preset", persona: found };
901
906
  } else {
902
- console.log(`Unknown persona "${personaId}", using Noen.`);
907
+ log(`Unknown persona "${personaId}", using Noen.`);
903
908
  personaChoice = { type: "noen", persona: null };
904
909
  }
905
910
  } else {
906
- console.log("Persona: Noen — nøytrale svar (auto)");
911
+ log("Persona: Noen — nøytrale svar (auto)");
907
912
  personaChoice = { type: "noen", persona: null };
908
913
  }
909
914
 
@@ -911,7 +916,7 @@ async function handleTestAuto(url, config, flags) {
911
916
  const scenarioChoice = flags.scenario
912
917
  ? { type: "custom", description: flags.scenario }
913
918
  : { type: "default", description: "Standard test" };
914
- console.log(`Scenario: ${scenarioChoice.description}`);
919
+ log(`Scenario: ${scenarioChoice.description}`);
915
920
 
916
921
  // Create output directory
917
922
  const formId = sanitizeSegment(extractFormId(fullUrl));
@@ -934,16 +939,17 @@ async function handleTestAuto(url, config, flags) {
934
939
  fs.writeFileSync(path.join(outputDir, "scenario.json"), JSON.stringify(scenarioChoice, null, 2));
935
940
 
936
941
  // Open and take initial full-page screenshot
937
- console.log("Opening form with Playwright CLI...");
942
+ log("Opening form with Playwright CLI...");
938
943
  await runPlaywrightCli(["open", fullUrl]);
939
944
  await runPlaywrightCli(["snapshot", "--filename", path.join(outputDir, "page_open.yml")]);
940
945
  await runPlaywrightCli(["screenshot", "--filename", path.join(outputDir, "page_open.png"), "--full-page"]);
941
- console.log("Saved: page_open.yml + page_open.png (full-page)");
946
+ log("Saved: page_open.yml + page_open.png (full-page)");
942
947
 
943
948
  // Auto-select person (try recommended, then first available)
944
949
  let options = extractPersonsFromSnapshotFile(path.join(outputDir, "page_open.yml"));
945
950
  if (!options.length) {
946
951
  for (let attempt = 0; attempt < 3; attempt++) {
952
+ verbose(`Scanning for person options (attempt ${attempt + 1})...`);
947
953
  await sleep(1500);
948
954
  options = await fetchPersonOptions();
949
955
  if (options.length) break;
@@ -952,7 +958,7 @@ async function handleTestAuto(url, config, flags) {
952
958
  if (options.length) {
953
959
  options = prioritizeRecommended(options, RECOMMENDED_PERSON);
954
960
  const chosen = options[0];
955
- console.log(`Auto-selected person: ${chosen}`);
961
+ log(`Auto-selected person: ${chosen}`);
956
962
  config.lastPerson = chosen;
957
963
  saveConfig(config);
958
964
  }
@@ -960,18 +966,23 @@ async function handleTestAuto(url, config, flags) {
960
966
  // Take form loaded screenshot after person selection
961
967
  await runPlaywrightCli(["snapshot", "--filename", path.join(outputDir, "form_loaded.yml")]);
962
968
  await runPlaywrightCli(["screenshot", "--filename", path.join(outputDir, "form_loaded.png"), "--full-page"]);
963
- console.log("Saved: form_loaded.yml + form_loaded.png (full-page)");
969
+ log("Saved: form_loaded.yml + form_loaded.png (full-page)");
964
970
 
965
971
  const dokumenterUrl = resolveDokumenterUrl(config);
966
- console.log(`\nOutput folder: ${outputDir}`);
967
- if (dokumenterUrl) {
968
- console.log(`Dokumenter URL: ${dokumenterUrl}`);
972
+
973
+ // Always print output folder (even in silent mode)
974
+ console.log(`Output folder: ${outputDir}`);
975
+
976
+ if (v !== "silent") {
977
+ if (dokumenterUrl) {
978
+ console.log(`Dokumenter URL: ${dokumenterUrl}`);
979
+ }
980
+ console.log("");
981
+ console.log("IMPORTANT: All screenshots MUST use --full-page to capture the entire page.");
982
+ console.log("Example: playwright-cli screenshot --filename \"path/to/file.png\" --full-page");
983
+ console.log("");
984
+ printNextSteps(outputDir, dokumenterUrl || "/dokumenter?pnr={PNR}");
969
985
  }
970
- console.log("");
971
- console.log("IMPORTANT: All screenshots MUST use --full-page to capture the entire page.");
972
- console.log("Example: playwright-cli screenshot --filename \"path/to/file.png\" --full-page");
973
- console.log("");
974
- printNextSteps(outputDir, dokumenterUrl || "/dokumenter?pnr={PNR}");
975
986
  }
976
987
 
977
988
  async function handleCommand(line, config) {
@@ -1131,13 +1142,17 @@ async function main() {
1131
1142
  const config = loadConfig();
1132
1143
  const url = args.find((a) => a.startsWith("http"));
1133
1144
  if (!url) {
1134
- console.error("Usage: form-tester test <url> --auto [--pnr <pnr>] [--persona <id>] [--scenario <text>]");
1145
+ console.error("Usage: form-tester test <url> --auto [--pnr <pnr>] [--persona <id>] [--scenario <text>] [--silent|--verbose]");
1135
1146
  process.exit(1);
1136
1147
  }
1137
- const pnrFlag = args[args.indexOf("--pnr") + 1];
1138
- const personaFlag = args[args.indexOf("--persona") + 1];
1139
- const scenarioFlag = args[args.indexOf("--scenario") + 1];
1140
- await handleTestAuto(url, config, { pnr: pnrFlag, persona: personaFlag, scenario: scenarioFlag });
1148
+ const flagVal = (flag) => args.includes(flag) ? args[args.indexOf(flag) + 1] : undefined;
1149
+ const verbosity = args.includes("--silent") ? "silent" : args.includes("--verbose") ? "verbose" : "normal";
1150
+ await handleTestAuto(url, config, {
1151
+ pnr: flagVal("--pnr"),
1152
+ persona: flagVal("--persona"),
1153
+ scenario: flagVal("--scenario"),
1154
+ verbosity,
1155
+ });
1141
1156
  process.exit(0);
1142
1157
  }
1143
1158
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "form-tester",
3
- "version": "0.4.3",
3
+ "version": "0.5.1",
4
4
  "description": "AI-powered form testing skill for /skjemautfyller forms using Playwright CLI. Works with Claude Code and GitHub Copilot.",
5
5
  "main": "form-tester.js",
6
6
  "bin": {