form-tester 0.3.5 → 0.4.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.
@@ -1,13 +1,24 @@
1
1
  # Form Tester Skill Instructions
2
2
 
3
- Setup (run once):
3
+ Install (user runs once):
4
4
  ```
5
- npx form-tester install
5
+ npm install -g form-tester
6
+ ```
7
+
8
+ Install skill files:
9
+ ```
10
+ form-tester install
6
11
  ```
7
12
 
8
13
  Run the CLI:
9
14
  ```
10
- npx form-tester
15
+ form-tester
16
+ ```
17
+
18
+ Non-interactive mode (best for AI agents):
19
+ ```
20
+ form-tester test <url> --auto
21
+ form-tester test <url> --auto --pnr 12345 --persona ung-mann
11
22
  ```
12
23
 
13
24
  Commands:
@@ -23,7 +34,7 @@ Commands:
23
34
  ```
24
35
 
25
36
  Notes:
26
- - New users: place this skill under .claude/skills/form-tester/ in your repo, then run /skills to scan/reload (or /restart).
37
+ - New users: run `npm install -g form-tester` then `form-tester install` in your project.
27
38
  - Provide a full /skjemautfyller URL. If `pnr` is missing, the CLI will prompt.
28
39
  - The CLI opens the form with Playwright CLI, saves an initial snapshot + screenshot, and prints next-step commands.
29
40
  - Use `/save {label}` to capture additional snapshots + screenshots into the same output folder.
@@ -56,4 +67,3 @@ Dokumenter verification (only when modal confirms storage):
56
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.
57
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.
58
69
  7. Include the document verification results in test_results.txt (document title, whether it matched the form h1, document type: HTML/PDF/XML).
59
-
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: form-tester
3
3
  description: Runs the form-tester CLI to test /skjemautfyller forms via Playwright CLI and exposes playwright-cli commands.
4
- allowed-tools: Bash(powershell:*), Bash(playwright-cli:*), Bash(npx form-tester:*)
4
+ allowed-tools: Bash(powershell:*), Bash(playwright-cli:*), Bash(form-tester:*)
5
5
  ---
6
6
 
7
7
  # Form Tester CLI
@@ -9,10 +9,23 @@ allowed-tools: Bash(powershell:*), Bash(playwright-cli:*), Bash(npx form-tester:
9
9
  ## Quick start
10
10
 
11
11
  ```bash
12
- npx form-tester install # one-time setup
13
- npx form-tester # run the CLI
12
+ # One-time install (user runs this manually):
13
+ npm install -g form-tester
14
+
15
+ # Install skill files into project:
16
+ form-tester install
17
+ form-tester install --global # or install to ~/.claude/skills/
18
+
19
+ # Non-interactive mode (no prompts, best for AI agents):
20
+ form-tester test <url> --auto
21
+ form-tester test <url> --auto --pnr 12345 --persona ung-mann --scenario "test validation"
22
+
23
+ # Interactive CLI:
24
+ form-tester
14
25
  ```
15
26
 
27
+ Persona IDs: `ung-mann`, `gravid-kvinne`, `eldre-kvinne`, `kronisk-syk-mann`. Defaults to "noen" (neutral answers) if omitted.
28
+
16
29
  ## Commands
17
30
 
18
31
  ```bash
@@ -37,4 +50,3 @@ Use `/people` to rescan the visible person list and get a numbered selection pro
37
50
  ## Playwright CLI
38
51
 
39
52
  You can also run `playwright-cli` commands directly when needed.
40
-
@@ -1,23 +1,28 @@
1
1
  # Form Tester — Copilot Instructions
2
2
 
3
- You have access to a form-testing CLI tool (`form-tester.js`) that automates testing of /skjemautfyller forms using Playwright CLI.
3
+ You have access to a form-testing CLI tool (`form-tester`) that automates testing of /skjemautfyller forms using Playwright CLI.
4
4
 
5
5
  ## Setup
6
6
 
7
+ User must install globally first:
7
8
  ```bash
8
- npx form-tester install
9
+ npm install -g form-tester
10
+ form-tester install
9
11
  ```
10
12
 
11
13
  ## Running the CLI
12
14
 
13
15
  ```bash
14
- # macOS/Linux
15
- node form-tester.js
16
+ # Interactive
17
+ form-tester
16
18
 
17
- # Windows (PowerShell)
18
- node .\form-tester.js
19
+ # Non-interactive (best for AI agents)
20
+ form-tester test <url> --auto
21
+ form-tester test <url> --auto --pnr 12345 --persona ung-mann --scenario "test validation"
19
22
  ```
20
23
 
24
+ Persona IDs: `ung-mann`, `gravid-kvinne`, `eldre-kvinne`, `kronisk-syk-mann`. Defaults to "noen" if omitted.
25
+
21
26
  ## Commands
22
27
 
23
28
  | Command | Description |
@@ -58,10 +63,10 @@ When `/test` is triggered:
58
63
  - Provide a full /skjemautfyller URL. If `pnr` is missing, the CLI will prompt.
59
64
  - All screenshots MUST use `--full-page` to capture the entire page.
60
65
  - Use `/save {label}` to capture additional snapshots into the output folder.
61
- - If an error modal appears on submit, open DevTools Network, retry once, and capture the Correlation ID header.
66
+ - If an error modal appears on submit, open DevTools -> Network, retry once, and capture the Correlation ID header.
62
67
 
63
68
  ## Post-Submit Verification
64
69
 
65
70
  After submission, read the modal text:
66
- - If it mentions Dokumenter storage navigate to `/dokumenter?pnr={PNR}`, verify the document appears, and capture it (screenshot for HTML, download for PDF).
67
- - If it does NOT mention Dokumenter skip verification, note in test_results.txt.
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 does NOT mention Dokumenter -> skip verification, note in test_results.txt.
package/README.md CHANGED
@@ -2,23 +2,25 @@
2
2
 
3
3
  AI-powered testing skill for `/skjemautfyller` forms using [Playwright CLI](https://www.npmjs.com/package/@playwright/cli). Works with **Claude Code** and **GitHub Copilot**.
4
4
 
5
- ## Quick Install
5
+ ## Install
6
6
 
7
7
  ```bash
8
- npx form-tester install
8
+ npm install -g form-tester
9
9
  ```
10
10
 
11
- This installs skill files into your project:
11
+ Then in your project:
12
+
13
+ ```bash
14
+ form-tester install # project-level (commits to repo)
15
+ form-tester install --global # personal (~/.claude/skills/)
16
+ ```
17
+
18
+ This installs:
12
19
  - `.claude/skills/form-tester/` — Claude Code skill
13
20
  - `.claude/skills/playwright-cli/` — Playwright CLI skill
14
21
  - `.github/copilot-instructions.md` — GitHub Copilot instructions
15
22
  - `form-tester.config.example.json` — Config template
16
-
17
- ## Prerequisites
18
-
19
- - Node.js 18+
20
-
21
- Playwright CLI is included as a dependency — no separate install needed.
23
+ - `playwright-cli` globally (if not already installed)
22
24
 
23
25
  ## Configuration
24
26
 
@@ -30,27 +32,30 @@ Edit `form-tester.config.json` and set your `pnr`.
30
32
 
31
33
  ## Usage
32
34
 
33
- ### Claude Code
34
-
35
- The skill is automatically detected when you open the project in Claude Code. Use the `/form-tester` skill or run:
35
+ ### Non-interactive (recommended for AI agents)
36
36
 
37
37
  ```bash
38
- npx form-tester
38
+ form-tester test <url> --auto
39
+ form-tester test <url> --auto --pnr 12345 --persona ung-mann --scenario "test validation"
39
40
  ```
40
41
 
41
- ### GitHub Copilot
42
-
43
- Copilot reads instructions from `.github/copilot-instructions.md` automatically. Open the project in VS Code with Copilot enabled.
42
+ Persona IDs: `ung-mann`, `gravid-kvinne`, `eldre-kvinne`, `kronisk-syk-mann`
44
43
 
45
- ### Standalone CLI
44
+ ### Interactive CLI
46
45
 
47
46
  ```bash
48
- npx form-tester
47
+ form-tester
49
48
  ```
50
49
 
51
50
  Commands: `/setup`, `/update`, `/version`, `/people`, `/test {url}`, `/save {label}`, `/clear`, `/quit`
52
51
 
53
- Use `--help` for the full command list.
52
+ ### Claude Code
53
+
54
+ The skill is automatically detected when you open the project. Use the `/form-tester` skill.
55
+
56
+ ### GitHub Copilot
57
+
58
+ Copilot reads instructions from `.github/copilot-instructions.md` automatically.
54
59
 
55
60
  ## Test Output
56
61
 
@@ -59,6 +64,12 @@ Test runs are saved to `output/{form-id}/{timestamp}/` with:
59
64
  - Screenshots (PNG, full-page)
60
65
  - `test_results.txt`
61
66
 
67
+ ## Update
68
+
69
+ ```bash
70
+ npm update -g form-tester
71
+ ```
72
+
62
73
  ## Development
63
74
 
64
75
  ```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(__dirname, "form-tester.config.json");
8
8
  const OUTPUT_BASE = path.resolve(__dirname, "output");
9
- const LOCAL_VERSION = "0.3.5";
9
+ const LOCAL_VERSION = "0.4.1";
10
10
  const RECOMMENDED_PERSON = "Uromantisk Direktør";
11
11
 
12
12
  const PERSONAS = [
@@ -878,6 +878,91 @@ async function handleTest(url, config) {
878
878
  );
879
879
  }
880
880
 
881
+ async function handleTestAuto(url, config, flags) {
882
+ // Resolve PNR
883
+ const pnr = flags.pnr || config.pnr;
884
+ if (!pnr) {
885
+ console.error("No PNR available. Pass --pnr <value> or set it in form-tester.config.json");
886
+ process.exit(1);
887
+ }
888
+ const fullUrl = extractPnrFromUrl(url) ? url : setPnrOnUrl(url, pnr);
889
+ config.pnr = pnr;
890
+ saveConfig(config);
891
+
892
+ // Resolve persona
893
+ let personaChoice;
894
+ const personaId = flags.persona;
895
+ if (personaId) {
896
+ const found = getPersonaById(personaId);
897
+ if (found) {
898
+ console.log(`Persona: ${found.name} — ${found.description}`);
899
+ personaChoice = { type: "preset", persona: found };
900
+ } else {
901
+ console.log(`Unknown persona "${personaId}", using Noen.`);
902
+ personaChoice = { type: "noen", persona: null };
903
+ }
904
+ } else {
905
+ console.log("Persona: Noen — nøytrale svar (auto)");
906
+ personaChoice = { type: "noen", persona: null };
907
+ }
908
+
909
+ // Resolve scenario
910
+ const scenarioChoice = flags.scenario
911
+ ? { type: "custom", description: flags.scenario }
912
+ : { type: "default", description: "Standard test" };
913
+ console.log(`Scenario: ${scenarioChoice.description}`);
914
+
915
+ // Create output directory
916
+ const formId = sanitizeSegment(extractFormId(fullUrl));
917
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
918
+ const outputDir = path.join(OUTPUT_BASE, formId, timestamp);
919
+ fs.mkdirSync(outputDir, { recursive: true });
920
+
921
+ config.lastTestUrl = fullUrl;
922
+ config.lastRunDir = outputDir;
923
+ saveConfig(config);
924
+
925
+ // Save persona and scenario
926
+ if (personaChoice.type === "preset") {
927
+ fs.writeFileSync(path.join(outputDir, "persona.json"), JSON.stringify(personaChoice.persona, null, 2));
928
+ } else {
929
+ fs.writeFileSync(path.join(outputDir, "persona.json"), JSON.stringify(
930
+ { id: "noen", name: "Noen", description: "Nøytrale svar", traits: {} }, null, 2,
931
+ ));
932
+ }
933
+ fs.writeFileSync(path.join(outputDir, "scenario.json"), JSON.stringify(scenarioChoice, null, 2));
934
+
935
+ // Open and snapshot
936
+ console.log("Opening form with Playwright CLI...");
937
+ await runPlaywrightCli(["open", fullUrl]);
938
+ await runPlaywrightCli(["snapshot", "--filename", path.join(outputDir, "page_open.yml")]);
939
+ await runPlaywrightCli(["screenshot", "--filename", path.join(outputDir, "page_open.png")]);
940
+
941
+ // Auto-select person (try recommended, then first available)
942
+ let options = extractPersonsFromSnapshotFile(path.join(outputDir, "page_open.yml"));
943
+ if (!options.length) {
944
+ for (let attempt = 0; attempt < 3; attempt++) {
945
+ await sleep(1500);
946
+ options = await fetchPersonOptions();
947
+ if (options.length) break;
948
+ }
949
+ }
950
+ if (options.length) {
951
+ options = prioritizeRecommended(options, RECOMMENDED_PERSON);
952
+ const chosen = options[0];
953
+ console.log(`Auto-selected person: ${chosen}`);
954
+ config.lastPerson = chosen;
955
+ saveConfig(config);
956
+ }
957
+
958
+ const dokumenterUrl = resolveDokumenterUrl(config);
959
+ console.log(`Output folder: ${outputDir}`);
960
+ if (dokumenterUrl) {
961
+ console.log(`Dokumenter URL: ${dokumenterUrl}`);
962
+ }
963
+ printNextSteps(outputDir, dokumenterUrl || "/dokumenter?pnr={PNR}");
964
+ }
965
+
881
966
  async function handleCommand(line, config) {
882
967
  const trimmed = line.trim();
883
968
  if (!trimmed) return;
@@ -1008,7 +1093,7 @@ function install(targetDir, isGlobal) {
1008
1093
  console.log("\nDone! Next steps:");
1009
1094
  console.log(" 1. cp form-tester.config.example.json form-tester.config.json");
1010
1095
  console.log(' 2. Edit form-tester.config.json and set your "pnr"');
1011
- console.log(" 3. Run: npx form-tester");
1096
+ console.log(" 3. Run: form-tester");
1012
1097
  }
1013
1098
 
1014
1099
  async function main() {
@@ -1031,6 +1116,20 @@ async function main() {
1031
1116
  process.exit(0);
1032
1117
  }
1033
1118
 
1119
+ if (args[0] === "test" && args.includes("--auto")) {
1120
+ const config = loadConfig();
1121
+ const url = args.find((a) => a.startsWith("http"));
1122
+ if (!url) {
1123
+ console.error("Usage: form-tester test <url> --auto [--pnr <pnr>] [--persona <id>] [--scenario <text>]");
1124
+ process.exit(1);
1125
+ }
1126
+ const pnrFlag = args[args.indexOf("--pnr") + 1];
1127
+ const personaFlag = args[args.indexOf("--persona") + 1];
1128
+ const scenarioFlag = args[args.indexOf("--scenario") + 1];
1129
+ await handleTestAuto(url, config, { pnr: pnrFlag, persona: personaFlag, scenario: scenarioFlag });
1130
+ process.exit(0);
1131
+ }
1132
+
1034
1133
  const config = loadConfig();
1035
1134
  await handleVersionMismatch(config);
1036
1135
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "form-tester",
3
- "version": "0.3.5",
3
+ "version": "0.4.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": {