form-tester 0.3.3 → 0.3.5

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.
Files changed (2) hide show
  1. package/form-tester.js +48 -32
  2. package/package.json +1 -1
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.3";
9
+ const LOCAL_VERSION = "0.3.5";
10
10
  const RECOMMENDED_PERSON = "Uromantisk Direktør";
11
11
 
12
12
  const PERSONAS = [
@@ -272,7 +272,11 @@ function isPlaywrightCliAvailable() {
272
272
 
273
273
  function runCommand(command, args, options = {}) {
274
274
  return new Promise((resolve) => {
275
- const child = spawn(command, args, { stdio: "inherit", ...options });
275
+ const child = spawn(command, args, {
276
+ stdio: "inherit",
277
+ shell: process.platform === "win32",
278
+ ...options,
279
+ });
276
280
  child.on("error", (err) => {
277
281
  console.error(`Failed to launch ${command}: ${err.message}`);
278
282
  resolve(1);
@@ -284,9 +288,9 @@ function runCommand(command, args, options = {}) {
284
288
  function runPlaywrightCli(args) {
285
289
  return new Promise((resolve) => {
286
290
  const spec = getPlaywrightCommandSpec();
287
- const child = spawn(spec.command, [...spec.args, ...args], {
288
- stdio: "inherit",
289
- });
291
+ const spawnOpts = { stdio: "inherit" };
292
+ if (spec.shell) spawnOpts.shell = true;
293
+ const child = spawn(spec.command, [...spec.args, ...args], spawnOpts);
290
294
  child.on("error", (err) => {
291
295
  console.error(`Failed to launch ${spec.command}: ${err.message}`);
292
296
  resolve(1);
@@ -298,10 +302,12 @@ function runPlaywrightCli(args) {
298
302
  function runPlaywrightCliCapture(args) {
299
303
  return new Promise((resolve) => {
300
304
  const spec = getPlaywrightCommandSpec();
305
+ const captureOpts = { stdio: ["ignore", "pipe", "pipe"] };
306
+ if (spec.shell) captureOpts.shell = true;
301
307
  const child = spawn(
302
308
  spec.command,
303
309
  [...spec.args, ...args],
304
- { stdio: ["ignore", "pipe", "pipe"] },
310
+ captureOpts,
305
311
  );
306
312
  let stdout = "";
307
313
  let stderr = "";
@@ -328,6 +334,7 @@ function getPlaywrightCommandSpec() {
328
334
  const command = getPlaywrightCommand();
329
335
  const lower = command.toLowerCase();
330
336
  if (process.platform === "win32" && (lower.endsWith(".cmd") || lower.endsWith(".ps1"))) {
337
+ // Try to resolve the actual .js entry point to avoid shell/spawn issues
331
338
  const nodeDir = path.dirname(command);
332
339
  const cliPath = path.join(
333
340
  nodeDir,
@@ -337,16 +344,12 @@ function getPlaywrightCommandSpec() {
337
344
  "playwright-cli.js",
338
345
  );
339
346
  if (fs.existsSync(cliPath)) {
340
- return { command: process.execPath, args: [cliPath] };
347
+ return { command: process.execPath, args: [cliPath], shell: false };
341
348
  }
349
+ // Fallback: run via node process.execPath with the .cmd/.ps1 content
350
+ return { command, args: [], shell: true };
342
351
  }
343
- if (lower.endsWith(".ps1")) {
344
- return {
345
- command: "powershell",
346
- args: ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", command],
347
- };
348
- }
349
- return { command, args: [] };
352
+ return { command, args: [], shell: false };
350
353
  }
351
354
 
352
355
  function findRepoRoot(startDir) {
@@ -947,36 +950,39 @@ function copyDirSync(src, dest) {
947
950
  }
948
951
  }
949
952
 
950
- function install(targetDir) {
953
+ function install(targetDir, isGlobal) {
951
954
  const pkgDir = __dirname;
952
955
  const skillsSrc = path.join(pkgDir, ".claude", "skills");
953
956
  const copilotSrc = path.join(pkgDir, ".github", "copilot-instructions.md");
954
957
  const configSrc = path.join(pkgDir, "form-tester.config.example.json");
955
958
 
956
959
  // Copy Claude Code skills
957
- const skillsDest = path.join(targetDir, ".claude", "skills");
960
+ const skillsDest = isGlobal
961
+ ? path.join(targetDir, "skills")
962
+ : path.join(targetDir, ".claude", "skills");
958
963
  for (const skill of ["form-tester", "playwright-cli"]) {
959
964
  const src = path.join(skillsSrc, skill);
960
965
  if (fs.existsSync(src)) {
961
966
  const dest = path.join(skillsDest, skill);
962
967
  copyDirSync(src, dest);
963
- console.log(` Installed .claude/skills/${skill}/`);
968
+ console.log(` Installed ${isGlobal ? "~/.claude" : ".claude"}/skills/${skill}/`);
964
969
  }
965
970
  }
966
971
 
967
- // Copy Copilot instructions
968
- if (fs.existsSync(copilotSrc)) {
969
- const copilotDest = path.join(targetDir, ".github", "copilot-instructions.md");
970
- fs.mkdirSync(path.dirname(copilotDest), { recursive: true });
971
- fs.copyFileSync(copilotSrc, copilotDest);
972
- console.log(" Installed .github/copilot-instructions.md");
973
- }
972
+ // Project-only files (skip for global install)
973
+ if (!isGlobal) {
974
+ if (fs.existsSync(copilotSrc)) {
975
+ const copilotDest = path.join(targetDir, ".github", "copilot-instructions.md");
976
+ fs.mkdirSync(path.dirname(copilotDest), { recursive: true });
977
+ fs.copyFileSync(copilotSrc, copilotDest);
978
+ console.log(" Installed .github/copilot-instructions.md");
979
+ }
974
980
 
975
- // Copy config example
976
- if (fs.existsSync(configSrc)) {
977
- const configDest = path.join(targetDir, "form-tester.config.example.json");
978
- fs.copyFileSync(configSrc, configDest);
979
- console.log(" Installed form-tester.config.example.json");
981
+ if (fs.existsSync(configSrc)) {
982
+ const configDest = path.join(targetDir, "form-tester.config.example.json");
983
+ fs.copyFileSync(configSrc, configDest);
984
+ console.log(" Installed form-tester.config.example.json");
985
+ }
980
986
  }
981
987
 
982
988
  // Install playwright-cli globally if not already available
@@ -1009,9 +1015,19 @@ async function main() {
1009
1015
  const args = process.argv.slice(2);
1010
1016
 
1011
1017
  if (args[0] === "install") {
1012
- const targetDir = args[1] ? path.resolve(args[1]) : process.cwd();
1013
- console.log(`Installing form-tester skills to ${targetDir} ...\n`);
1014
- install(targetDir);
1018
+ const isGlobal = args.includes("--global") || args.includes("-g");
1019
+ const remaining = args.slice(1).filter((a) => a !== "--global" && a !== "-g");
1020
+ let targetDir;
1021
+ if (isGlobal) {
1022
+ const home = process.env.HOME || process.env.USERPROFILE;
1023
+ targetDir = path.join(home, ".claude");
1024
+ // Global installs skills directly into ~/.claude/skills/
1025
+ console.log(`Installing form-tester skills globally to ${targetDir} ...\n`);
1026
+ } else {
1027
+ targetDir = remaining[0] ? path.resolve(remaining[0]) : process.cwd();
1028
+ console.log(`Installing form-tester skills to ${targetDir} ...\n`);
1029
+ }
1030
+ install(targetDir, isGlobal);
1015
1031
  process.exit(0);
1016
1032
  }
1017
1033
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "form-tester",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
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": {