form-tester 0.2.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.
- package/.claude/skills/playwright-cli/SKILL.md +278 -0
- package/.claude/skills/playwright-cli/references/request-mocking.md +87 -0
- package/.claude/skills/playwright-cli/references/running-code.md +232 -0
- package/.claude/skills/playwright-cli/references/session-management.md +169 -0
- package/.claude/skills/playwright-cli/references/storage-state.md +275 -0
- package/.claude/skills/playwright-cli/references/test-generation.md +88 -0
- package/.claude/skills/playwright-cli/references/tracing.md +139 -0
- package/.claude/skills/playwright-cli/references/video-recording.md +43 -0
- package/README.md +75 -0
- package/form-tester.config.example.json +3 -0
- package/form-tester.js +984 -0
- package/package.json +26 -0
- package/tests/form-tester.test.js +120 -0
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "form-tester",
|
|
3
|
+
"version": "0.2.3",
|
|
4
|
+
"description": "AI-powered form testing skill for /skjemautfyller forms using Playwright CLI. Works with Claude Code and GitHub Copilot.",
|
|
5
|
+
"main": "form-tester.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"form-tester": "./form-tester.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "node --test tests/form-tester.test.js",
|
|
11
|
+
"setup": "npm install -g @playwright/cli@latest && playwright-cli install --skills"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"form-testing",
|
|
15
|
+
"playwright",
|
|
16
|
+
"claude-code",
|
|
17
|
+
"copilot",
|
|
18
|
+
"skill",
|
|
19
|
+
"skjemautfyller"
|
|
20
|
+
],
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/ruberino/form-tester"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT"
|
|
26
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
const test = require("node:test");
|
|
2
|
+
const assert = require("node:assert/strict");
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
extractFormId,
|
|
6
|
+
extractPnrFromUrl,
|
|
7
|
+
setPnrOnUrl,
|
|
8
|
+
ensurePnrInUrl,
|
|
9
|
+
sanitizeSegment,
|
|
10
|
+
resolveDokumenterUrl,
|
|
11
|
+
prioritizeRecommended,
|
|
12
|
+
parsePersonList,
|
|
13
|
+
getPersonas,
|
|
14
|
+
getPersonaById,
|
|
15
|
+
formatPersonaList,
|
|
16
|
+
promptScenario,
|
|
17
|
+
} = require("../form-tester");
|
|
18
|
+
|
|
19
|
+
test("extractFormId returns form id from skjemautfyller URL", () => {
|
|
20
|
+
const url =
|
|
21
|
+
"https://example.no/skjemautfyller/HV-SOS-1?pnr=24908196046";
|
|
22
|
+
assert.equal(extractFormId(url), "HV-SOS-1");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("extractPnrFromUrl reads pnr query parameter", () => {
|
|
26
|
+
const url = "https://example.no/skjemautfyller/HV-SOS-1?pnr=123";
|
|
27
|
+
assert.equal(extractPnrFromUrl(url), "123");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("setPnrOnUrl adds pnr when missing", () => {
|
|
31
|
+
const url = "https://example.no/skjemautfyller/HV-SOS-1";
|
|
32
|
+
const updated = setPnrOnUrl(url, "555");
|
|
33
|
+
assert.match(updated, /pnr=555/);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("ensurePnrInUrl prompts when pnr missing", async () => {
|
|
37
|
+
const config = { pnr: "" };
|
|
38
|
+
const ask = async () => "999";
|
|
39
|
+
const result = await ensurePnrInUrl(
|
|
40
|
+
"https://example.no/skjemautfyller/HV-SOS-1",
|
|
41
|
+
config,
|
|
42
|
+
ask,
|
|
43
|
+
);
|
|
44
|
+
assert.match(result.url, /pnr=999/);
|
|
45
|
+
assert.equal(result.pnr, "999");
|
|
46
|
+
assert.equal(config.pnr, "999");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("sanitizeSegment removes invalid path characters", () => {
|
|
50
|
+
assert.equal(sanitizeSegment('HV:SOS*1'), "HVSOS1");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("resolveDokumenterUrl expands PNR template", () => {
|
|
54
|
+
const config = {
|
|
55
|
+
dokumenterUrlTemplate: "/dokumenter?pnr={PNR}",
|
|
56
|
+
pnr: "777",
|
|
57
|
+
};
|
|
58
|
+
assert.equal(resolveDokumenterUrl(config), "/dokumenter?pnr=777");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("prioritizeRecommended moves recommended to first position", () => {
|
|
62
|
+
const list = ["Alpha", "Uromantisk Direktør", "Beta"];
|
|
63
|
+
const result = prioritizeRecommended(list, "Uromantisk Direktør");
|
|
64
|
+
assert.deepEqual(result, ["Uromantisk Direktør", "Alpha", "Beta"]);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("parsePersonList parses JSON output and dedupes", () => {
|
|
68
|
+
const output =
|
|
69
|
+
'["Uromantisk Direktør","Alpha","Uromantisk Direktør","Beta"]';
|
|
70
|
+
const result = parsePersonList(output);
|
|
71
|
+
assert.deepEqual(result, ["Uromantisk Direktør", "Alpha", "Beta"]);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("parsePersonList extracts list from Result block", () => {
|
|
75
|
+
const output = [
|
|
76
|
+
"### Result",
|
|
77
|
+
'["Person A","Person B"]',
|
|
78
|
+
"### Page",
|
|
79
|
+
"- Page Title: Example",
|
|
80
|
+
].join("\n");
|
|
81
|
+
const result = parsePersonList(output);
|
|
82
|
+
assert.deepEqual(result, ["Person A", "Person B"]);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("getPersonas returns 4 personas", () => {
|
|
86
|
+
const personas = getPersonas();
|
|
87
|
+
assert.equal(personas.length, 4);
|
|
88
|
+
assert.ok(personas.every((p) => p.id && p.name && p.description && p.traits));
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("getPersonaById returns correct persona", () => {
|
|
92
|
+
const persona = getPersonaById("ung-mann");
|
|
93
|
+
assert.equal(persona.name, "Ung mann");
|
|
94
|
+
assert.equal(persona.traits.gender, "Mann");
|
|
95
|
+
assert.equal(persona.traits.age, 25);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("getPersonaById returns null for unknown id", () => {
|
|
99
|
+
assert.equal(getPersonaById("nonexistent"), null);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("formatPersonaList includes all personas plus noen and custom", () => {
|
|
103
|
+
const list = formatPersonaList();
|
|
104
|
+
assert.ok(list.includes("Ung mann"));
|
|
105
|
+
assert.ok(list.includes("Gravid kvinne"));
|
|
106
|
+
assert.ok(list.includes("Eldre kvinne"));
|
|
107
|
+
assert.ok(list.includes("Kronisk syk mann"));
|
|
108
|
+
assert.ok(list.includes("Noen"));
|
|
109
|
+
assert.ok(list.includes("Lag egen"));
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("each persona has a unique id", () => {
|
|
113
|
+
const personas = getPersonas();
|
|
114
|
+
const ids = personas.map((p) => p.id);
|
|
115
|
+
assert.equal(new Set(ids).size, ids.length);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("promptScenario is exported as a function", () => {
|
|
119
|
+
assert.equal(typeof promptScenario, "function");
|
|
120
|
+
});
|