browsecraft 0.5.0 → 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.
package/dist/cli.cjs CHANGED
@@ -23,6 +23,9 @@ async function main() {
23
23
  case "test":
24
24
  await runTests(args.slice(1));
25
25
  break;
26
+ case "bdd":
27
+ await runTests(["--bdd", ...args.slice(1)]);
28
+ break;
26
29
  case "init":
27
30
  await initProject();
28
31
  break;
@@ -30,7 +33,9 @@ async function main() {
30
33
  await setupIde();
31
34
  break;
32
35
  default:
33
- if (command && (command.endsWith(".ts") || command.endsWith(".js"))) {
36
+ if (command?.endsWith(".feature")) {
37
+ await runTests(["--bdd", ...args]);
38
+ } else if (command?.endsWith(".ts") || command?.endsWith(".js")) {
34
39
  await runTests(args);
35
40
  } else {
36
41
  console.error(`Unknown command: ${command}`);
@@ -266,7 +271,13 @@ async function runBddTests(config, userConfig, flags, filePatterns) {
266
271
  console.log(` ${prefix}Step not defined. Add it to your step definitions.`);
267
272
  }
268
273
  },
269
- onScenarioEnd: () => {
274
+ onScenarioEnd: (result) => {
275
+ if (result.hookError) {
276
+ console.log(` ${prefix}\x1B[31m\u2717 ${result.hookError.message}\x1B[0m`);
277
+ }
278
+ if (result.status === "failed" && !result.hookError && result.steps.length === 0) {
279
+ console.log(` ${prefix}\x1B[31m\u2717 Scenario failed with no steps executed\x1B[0m`);
280
+ }
270
281
  }
271
282
  });
272
283
  let allFeatures2 = [];
@@ -366,7 +377,25 @@ async function runBddTests(config, userConfig, flags, filePatterns) {
366
377
  }
367
378
  console.log("");
368
379
  if (scenarios.failed > 0) {
369
- console.log(" \x1B[31mSome scenarios failed.\x1B[0m\n");
380
+ console.log(" \x1B[31mFailed scenarios:\x1B[0m");
381
+ for (const feat of allFeatures) {
382
+ for (const scen of feat.scenarios) {
383
+ if (scen.status !== "failed") continue;
384
+ console.log(` \x1B[31m\u2717\x1B[0m ${feat.name} \u2192 ${scen.name}`);
385
+ if (scen.hookError) {
386
+ console.log(` Error: ${scen.hookError.message}`);
387
+ }
388
+ for (const st of scen.steps) {
389
+ if (st.status === "failed" && st.error) {
390
+ console.log(` ${st.keyword.trim()} ${st.text}: ${st.error.message}`);
391
+ }
392
+ if (st.status === "undefined") {
393
+ console.log(` ${st.keyword.trim()} ${st.text}: \x1B[33mStep not defined\x1B[0m`);
394
+ }
395
+ }
396
+ }
397
+ }
398
+ console.log("");
370
399
  } else if (steps.undefined > 0) {
371
400
  console.log(" \x1B[33mSome steps are undefined.\x1B[0m\n");
372
401
  } else {
@@ -736,12 +765,14 @@ function printHelp() {
736
765
 
737
766
  Usage:
738
767
  browsecraft test [files...] [options]
768
+ browsecraft bdd [features...] [options]
739
769
  browsecraft test --bdd [features...] [options]
740
770
  browsecraft init
741
771
  browsecraft setup-ide
742
772
 
743
773
  Commands:
744
774
  test Run browser tests
775
+ bdd Run BDD feature files (shorthand for test --bdd)
745
776
  test --bdd Run BDD feature files (Gherkin)
746
777
  init Create a new project with example config and test
747
778
  setup-ide Configure VS Code for Cucumber step discovery
@@ -764,9 +795,11 @@ function printHelp() {
764
795
  -v, --version Show version
765
796
 
766
797
  BDD Examples:
767
- browsecraft test --bdd # All features, 1 browser
768
- browsecraft test --bdd features/login.feature # Single feature
769
- browsecraft test --bdd features/login.feature:15 # Specific scenario by line
798
+ browsecraft bdd # All features, 1 browser
799
+ browsecraft bdd features/login.feature # Single feature
800
+ browsecraft bdd features/login.feature:15 # Specific scenario by line
801
+ browsecraft bdd --headed # Watch it run
802
+ browsecraft test --bdd features/login.feature # Equivalent long form
770
803
  browsecraft test --bdd --scenario "Valid login" # Specific scenario by name
771
804
  browsecraft test --bdd --tag "@smoke" # Tag filter
772
805
  browsecraft test --bdd --grep "checkout" # Name filter
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"names":["resolveConfig","TestRunner","testRegistry","pathToFileURL","Browser","runTest","resolve","existsSync","readFileSync","relative","allFeatures","join","readdirSync","statSync","writeFileSync","mkdirSync"],"mappings":";;;;;;;;;AAoBA,IAAM,OAAA,GAAU,OAAA;AAEhB,eAAe,IAAA,GAAO;AACrB,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA;AAEjC,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG;AACxE,IAAA,SAAA,EAAU;AACV,IAAA;AAAA,EACD;AAEA,EAAA,IAAI,KAAK,QAAA,CAAS,WAAW,KAAK,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG;AACtD,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,aAAA,EAAgB,OAAO,CAAA,CAAE,CAAA;AACrC,IAAA;AAAA,EACD;AAEA,EAAA,MAAM,OAAA,GAAU,KAAK,CAAC,CAAA;AAEtB,EAAA,QAAQ,OAAA;AAAS,IAChB,KAAK,MAAA;AACJ,MAAA,MAAM,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AAC5B,MAAA;AAAA,IACD,KAAK,MAAA;AACJ,MAAA,MAAM,WAAA,EAAY;AAClB,MAAA;AAAA,IACD,KAAK,WAAA;AACJ,MAAA,MAAM,QAAA,EAAS;AACf,MAAA;AAAA,IACD;AAEC,MAAA,IAAI,OAAA,KAAY,QAAQ,QAAA,CAAS,KAAK,KAAK,OAAA,CAAQ,QAAA,CAAS,KAAK,CAAA,CAAA,EAAI;AACpE,QAAA,MAAM,SAAS,IAAI,CAAA;AAAA,MACpB,CAAA,MAAO;AACN,QAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,iBAAA,EAAoB,OAAO,CAAA,CAAE,CAAA;AAC3C,QAAA,OAAA,CAAQ,MAAM,iDAAiD,CAAA;AAC/D,QAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,MACf;AAAA;AAEH;AAMA,eAAe,SAAS,IAAA,EAAgB;AAEvC,EAAA,MAAM,KAAA,GAAQ,WAAW,IAAI,CAAA;AAC7B,EAAA,MAAM,YAAA,GAAe,KAAK,MAAA,CAAO,CAAC,MAAM,CAAC,CAAA,CAAE,UAAA,CAAW,IAAI,CAAC,CAAA;AAG3D,EAAA,MAAM,UAAA,GAAa,MAAM,UAAA,EAAW;AACpC,EAAA,MAAM,MAAA,GAASA,gCAAc,UAAU,CAAA;AAGvC,EAAA,IAAI,KAAA,CAAM,MAAA,IAAU,KAAA,CAAM,QAAA,KAAa,KAAA,EAAO;AAC7C,IAAA,MAAA,CAAO,QAAA,GAAW,KAAA;AAAA,EACnB;AACA,EAAA,IAAI,MAAM,OAAA,EAAS;AAClB,IAAA,MAAA,CAAO,UAAU,KAAA,CAAM,OAAA;AAAA,EACxB;AACA,EAAA,IAAI,KAAA,CAAM,YAAY,MAAA,EAAW;AAChC,IAAA,MAAA,CAAO,UAAU,KAAA,CAAM,OAAA;AAAA,EACxB;AACA,EAAA,IAAI,KAAA,CAAM,YAAY,MAAA,EAAW;AAChC,IAAA,MAAA,CAAO,UAAU,KAAA,CAAM,OAAA;AAAA,EACxB;AACA,EAAA,IAAI,KAAA,CAAM,YAAY,MAAA,EAAW;AAChC,IAAA,MAAA,CAAO,UAAU,KAAA,CAAM,OAAA;AAAA,EACxB;AACA,EAAA,IAAI,MAAM,KAAA,EAAO;AAChB,IAAA,MAAA,CAAO,KAAA,GAAQ,IAAA;AAAA,EAChB;AAGA,EAAA,IAAI,MAAM,GAAA,EAAK;AACd,IAAA,MAAM,WAAA,CAAY,MAAA,EAAQ,UAAA,EAAY,KAAA,EAAO,YAAY,CAAA;AACzD,IAAA;AAAA,EACD;AAGA,EAAA,MAAM,aAAA,GAA+B;AAAA,IACpC,MAAA;AAAA,IACA,KAAA,EAAO,YAAA,CAAa,MAAA,GAAS,CAAA,GAAI,YAAA,GAAe,MAAA;AAAA,IAChD,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,MAAM,KAAA,CAAM;AAAA,GACb;AAGA,EAAA,MAAM,MAAA,GAAS,IAAIC,4BAAA,CAAW,aAAa,CAAA;AAG3C,EAAA,MAAM,QAAA,GAAW,OAAO,IAAA,KAA0C;AACjE,IAAA,MAAM,WAAWC,8BAAA,CAAa,MAAA;AAG9B,IAAA,IAAI,KAAK,QAAA,CAAS,KAAK,KAAK,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAClD,MAAA,MAAM,sBAAA,EAAuB;AAAA,IAC9B;AAEA,IAAA,MAAM,OAAA,GAAUC,iBAAA,CAAc,IAAI,CAAA,CAAE,IAAA;AACpC,IAAA,MAAM,OAAO,OAAA,CAAA;AACb,IAAA,OAAOD,+BAAa,KAAA,CAAM,QAAQ,CAAA,CAAE,GAAA,CAAI,CAAC,EAAA,MAAQ;AAAA,MAChD,OAAO,EAAA,CAAG,KAAA;AAAA,MACV,WAAW,EAAA,CAAG,SAAA;AAAA,MACd,MAAM,EAAA,CAAG,IAAA;AAAA,MACT,MAAM,EAAA,CAAG,IAAA;AAAA,MACT,SAAS,EAAA,CAAG,OAAA;AAAA,MACZ,IAAI,EAAA,CAAG;AAAA,KACR,CAAE,CAAA;AAAA,EACH,CAAA;AAGA,EAAA,IAAI,aAAA;AAEJ,EAAA,IAAI;AACH,IAAA,aAAA,GAAgB,MAAME,0BAAQ,MAAA,CAAO;AAAA,MACpC,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,gBAAgB,MAAA,CAAO,cAAA;AAAA,MACvB,OAAO,MAAA,CAAO,KAAA;AAAA,MACd,SAAS,MAAA,CAAO;AAAA,KAChB,CAAA;AAAA,EACF,SAAS,GAAA,EAAK;AACb,IAAA,OAAA,CAAQ,KAAA,CAAM,6BAA6B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAC7F,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EACf;AAGA,EAAA,MAAM,WAAA,GAAc,OAAO,IAAA,KAAuB;AACjD,IAAA,OAAOC,yBAAA,CAAQ,MAA6B,aAAa,CAAA;AAAA,EAC1D,CAAA;AAEA,EAAA,IAAI;AACH,IAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,GAAA,CAAI,UAAU,WAAW,CAAA;AACvD,IAAA,MAAM,aAAA,CAAc,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAC1C,IAAA,OAAA,CAAQ,KAAK,QAAQ,CAAA;AAAA,EACtB,SAAS,GAAA,EAAK;AACb,IAAA,MAAM,aAAA,EAAe,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAC3C,IAAA,MAAM,GAAA;AAAA,EACP;AACD;AAgBA,eAAe,WAAA,CACd,MAAA,EACA,UAAA,EACA,KAAA,EACA,YAAA,EACgB;AAChB,EAAA,MAAM,SAAA,GAAa,MAAM,OAAO,iBAAiB,CAAA;AACjD,EAAA,MAAM,EAAE,YAAA,EAAc,WAAA,EAAa,oBAAA,EAAsB,KAAA,EAAO,gBAAe,GAAI,SAAA;AACnF,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,EAAI;AAGxB,EAAA,MAAM,SAAA,GAAY,UAAA,EAAY,GAAA,IAAO,EAAC;AACtC,EAAA,MAAM,eAAA,GAAkB,UAAU,QAAA,IAAY,uBAAA;AAC9C,EAAA,MAAM,YAAA,GAAe,UAAU,KAAA,IAAS,4BAAA;AACxC,EAAA,MAAM,eAAA,GAAkB,UAAU,YAAA,KAAiB,KAAA;AAGnD,EAAA,MAAM,eAAyB,KAAA,EAAO,OAAA,GACnC,MAAM,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,MAAM,CAAA,GAC3C,OAAO,QAAA,IAAY,CAAC,OAAO,OAAO,CAAA;AAGtC,EAAA,MAAM,UAAU,KAAA,EAAO,OAAA,KAAY,YAAA,CAAa,MAAA,GAAS,IAAI,CAAA,GAAI,CAAA,CAAA;AAGjE,EAAA,MAAM,QAAA,GAAY,KAAA,EAAO,QAAA,IAAY,MAAA,CAAO,QAAA,IAAY,YAAA;AAMxD,EAAA,MAAM,SAAA,GAAY,KAAA,EAAO,GAAA,IAAO,SAAA,CAAU,SAAA;AAG1C,EAAA,MAAM,WAAA,GAAc,KAAA,EAAO,QAAA,IAAY,KAAA,EAAO,QAAQ,SAAA,CAAU,IAAA;AAGhE,EAAA,MAAM,QAAA,GAAW,OAAO,IAAA,IAAQ,KAAA;AAIhC,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAsB;AAC9C,EAAA,IAAI,YAAA;AAEJ,EAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,MAAA,GAAS,CAAA,EAAG;AAE5C,IAAA,MAAM,gBAA0B,EAAC;AACjC,IAAA,KAAA,MAAW,WAAW,YAAA,EAAc;AACnC,MAAA,MAAM,CAAC,QAAA,EAAU,QAAQ,CAAA,GAAI,OAAA,CAAQ,MAAM,GAAG,CAAA;AAC9C,MAAA,MAAM,OAAA,GAAUC,YAAA,CAAQ,GAAA,EAAK,QAAS,CAAA;AACtC,MAAA,IAAI,CAACC,aAAA,CAAW,OAAO,CAAA,EAAG;AAE1B,MAAA,IAAI,CAAC,aAAA,CAAc,QAAA,CAAS,OAAO,CAAA,EAAG;AACrC,QAAA,aAAA,CAAc,KAAK,OAAO,CAAA;AAAA,MAC3B;AACA,MAAA,IAAI,QAAA,EAAU;AACb,QAAA,MAAM,OAAA,GAAU,MAAA,CAAO,QAAA,CAAS,QAAA,EAAU,EAAE,CAAA;AAC5C,QAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,EAAG;AAC3B,UAAA,MAAM,QAAA,GAAW,WAAA,CAAY,GAAA,CAAI,OAAO,KAAK,EAAC;AAC9C,UAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AACrB,UAAA,WAAA,CAAY,GAAA,CAAI,SAAS,QAAQ,CAAA;AAAA,QAClC;AAAA,MACD;AAAA,IACD;AACA,IAAA,YAAA,GAAe,aAAA;AACf,IAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAC9B,MAAA,OAAA,CAAQ,MAAM,wCAAwC,CAAA;AACtD,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IACf;AAAA,EACD,CAAA,MAAO;AACN,IAAA,YAAA,GAAe,aAAA,CAAc,GAAA,EAAK,eAAA,EAAiB,CAAC,UAAU,CAAC,CAAA;AAAA,EAChE;AAEA,EAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAC9B,IAAA,OAAA,CAAQ,IAAI,gCAAgC,CAAA;AAC5C,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,mBAAA,EAAsB,eAAe,CAAA,CAAE,CAAA;AACnD,IAAA,OAAA,CAAQ,IAAI,4EAA4E,CAAA;AACxF,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EACf;AAGA,EAAA,IAAI,eAAA,EAAiB;AACpB,IAAA,oBAAA,EAAqB;AAAA,EACtB;AAEA,EAAA,MAAM,SAAA,GAAY,cAAc,GAAA,EAAK,YAAA,EAAc,CAAC,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,MAAM,CAAC,CAAA;AACjF,EAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AACjC,IAAA,IAAI,SAAS,QAAA,CAAS,KAAK,KAAK,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA,EAAG;AAC1D,MAAA,MAAM,sBAAA,EAAuB;AAAA,IAC9B;AACA,IAAA,MAAM,OAAA,GAAUJ,iBAAA,CAAc,QAAQ,CAAA,CAAE,IAAA;AACxC,IAAA,MAAM,OAAO,OAAA,CAAA;AAAA,EACd;AAGA,EAAA,KAAA,CAAM,OAAO,EAAE,KAAA,EAAM,KAAM;AAC1B,IAAA,MAAM,CAAA,GAAI,KAAA;AACV,IAAA,IAAI,GAAG,QAAA,EAAU;AAChB,MAAA,MAAM,CAAA,CAAE,QAAA,CAAS,KAAA,EAAM,CAAE,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACxC;AAAA,EACD,CAAC,CAAA;AAGD,EAAA,MAAM,SAAA,GAAY,YAAA,CAAa,GAAA,CAAI,CAAC,IAAA,KAAS;AAC5C,IAAA,MAAM,MAAA,GAASK,eAAA,CAAa,IAAA,EAAM,OAAO,CAAA;AACzC,IAAA,OAAO,YAAA,CAAa,MAAA,EAAQC,aAAA,CAAS,GAAA,EAAK,IAAI,CAAC,CAAA;AAAA,EAChD,CAAC,CAAA;AAGD,EAAA,MAAM,aACL,WAAA,CAAY,IAAA,GAAO,IAChB,CAAC,QAAA,EAA0C,OAAiB,GAAA,KAAiB;AAC7E,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,WAAA,EAAa;AACxC,MAAA,MAAM,OAAA,GAAUA,aAAA,CAAS,GAAA,EAAK,IAAI,CAAA;AAClC,MAAA,IAAI,GAAA,KAAQ,OAAA,IAAW,GAAA,KAAQ,IAAA,EAAM;AACpC,QAAA,OAAO,KAAA,CAAM,QAAA,CAAS,QAAA,CAAS,IAAI,CAAA;AAAA,MACpC;AAAA,IACD;AACA,IAAA,OAAO,IAAA;AAAA,EACR,CAAA,GACC,MAAA;AAGJ,EAAA,MAAM,cAAA,GAAiB,aAAa,MAAA,GAAS,CAAA;AAC7C,EAAA,MAAM,aAAa,OAAA,GAAU,CAAA;AAG7B,EAAA,MAAM,KAAA,GAAkB;AAAA,IACvB,CAAA,EAAG,aAAa,MAAM,CAAA,aAAA,EAAgB,aAAa,MAAA,GAAS,CAAA,GAAI,MAAM,EAAE,CAAA;AAAA,GACzE;AACA,EAAA,IAAI,cAAA,QAAsB,IAAA,CAAK,CAAA,GAAA,EAAM,aAAa,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAC9D,EAAA,IAAI,UAAA,EAAY,KAAA,CAAM,IAAA,CAAK,CAAA,CAAA,EAAI,OAAO,CAAA,SAAA,CAAW,CAAA;AACjD,EAAA,IAAI,SAAA,EAAW,KAAA,CAAM,IAAA,CAAK,CAAA,OAAA,EAAU,SAAS,CAAA,CAAA,CAAG,CAAA;AAChD,EAAA,IAAI,WAAA,EAAa,KAAA,CAAM,IAAA,CAAK,CAAA,OAAA,EAAU,WAAW,CAAA,CAAA,CAAG,CAAA;AACpD,EAAA,IAAI,WAAA,CAAY,OAAO,CAAA,EAAG;AACzB,IAAA,MAAM,YAAY,CAAC,GAAG,WAAA,CAAY,OAAA,EAAS,CAAA,CAAE,GAAA;AAAA,MAC5C,CAAC,CAAC,CAAA,EAAG,EAAE,MAAM,CAAA,EAAGA,aAAA,CAAS,GAAA,EAAK,CAAC,CAAC,CAAA,CAAA,EAAI,EAAA,CAAG,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,KACjD;AACA,IAAA,KAAA,CAAM,KAAK,CAAA,QAAA,EAAW,SAAA,CAAU,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,EAC7C;AAEA,EAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,4BAAA,EAAiC,KAAA,CAAM,IAAA,CAAK,GAAG,CAAC;AAAA,CAAI,CAAA;AAEhE,EAAA,IAAI,cAAA,EAAgB;AACnB,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,YAAA,EAAe,QAAQ,CAAA,CAAE,CAAA;AACrC,IAAA,OAAA,CAAQ,GAAA;AAAA,MACP,eAAe,YAAA,CAAa,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,EAAE,KAAA,CAAM,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,KAC1F;AACA,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAAA,EACf;AAWA,EAAA,MAAM,YAAA,GAAe,OACpB,WAAA,EACA,IAAA,EACA,MAAA,KACoF;AACpF,IAAA,MAAM,OAAA,GAAU,MAAML,yBAAA,CAAQ,MAAA,CAAO;AAAA,MACpC,OAAA,EAAS,WAAA;AAAA,MACT,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,gBAAgB,MAAA,CAAO,cAAA;AAAA,MACvB,OAAO,MAAA,CAAO,KAAA;AAAA,MACd,SAAS,MAAA,CAAO;AAAA,KAChB,CAAA;AAED,IAAA,MAAM,cAAA,GAAiB,CAAC,SAAA,KACvB,IAAI,WAAA,CAAY;AAAA,MACf,aAAa,MAAA,CAAO,OAAA;AAAA,MACpB,WAAW,SAAA,IAAa,MAAA;AAAA,MACxB,MAAM,WAAA,IAAe,MAAA;AAAA,MACrB,gBAAgB,UAAA,IAAc,MAAA;AAAA,MAC9B,QAAA;AAAA,MACA,cAAc,YAAY;AACzB,QAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,UAAA,EAAW;AACzC,QAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,OAAA,EAAQ;AACnC,QAAA,OAAO;AAAA,UACN,IAAA;AAAA,UACA,OAAA;AAAA,UACA,KAAK,EAAC;AAAA,UACN,QAAQ,MAAM;AAAA,UAAC,CAAA;AAAA,UACf,GAAA,EAAK,CAAC,GAAA,KAAgB,OAAA,CAAQ,IAAI,CAAA,MAAA,EAAS,MAAM,CAAA,EAAG,GAAG,CAAA,CAAE,CAAA;AAAA,UACzD,QAAA,EAAU;AAAA,SACX;AAAA,MACD,CAAA;AAAA,MACA,cAAA,EAAgB,CAAC,OAAA,KAAY;AAC5B,QAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,EAAA,EAAO,MAAM,CAAA,SAAA,EAAY,OAAA,CAAQ,IAAI,CAAA,CAAE,CAAA;AAAA,MACpD,CAAA;AAAA,MACA,eAAA,EAAiB,CAAC,QAAA,KAAa;AAC9B,QAAA,OAAA,CAAQ,IAAI,CAAA,IAAA,EAAO,MAAM,CAAA,UAAA,EAAa,QAAA,CAAS,IAAI,CAAA,CAAE,CAAA;AAAA,MACtD,CAAA;AAAA,MACA,SAAA,EAAW,CAAC,MAAA,KAAW;AACtB,QAAA,MAAM,OACL,MAAA,CAAO,MAAA,KAAW,QAAA,GACf,kBAAA,GACA,OAAO,MAAA,KAAW,QAAA,GACjB,kBAAA,GACA,MAAA,CAAO,WAAW,WAAA,GACjB,kBAAA,GACA,MAAA,CAAO,MAAA,KAAW,YACjB,kBAAA,GACA,kBAAA;AACP,QAAA,OAAA,CAAQ,GAAA;AAAA,UACP,CAAA,MAAA,EAAS,MAAM,CAAA,EAAG,IAAI,IAAI,MAAA,CAAO,OAAA,CAAQ,IAAA,EAAM,CAAA,CAAA,EAAI,MAAA,CAAO,IAAI,CAAA,EAAA,EAAK,OAAO,QAAQ,CAAA,GAAA;AAAA,SACnF;AACA,QAAA,IAAI,MAAA,CAAO,MAAA,KAAW,QAAA,IAAY,MAAA,CAAO,KAAA,EAAO;AAC/C,UAAA,OAAA,CAAQ,IAAI,CAAA,QAAA,EAAW,MAAM,GAAG,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,QACvD;AACA,QAAA,IAAI,MAAA,CAAO,WAAW,WAAA,EAAa;AAClC,UAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,QAAA,EAAW,MAAM,CAAA,kDAAA,CAAoD,CAAA;AAAA,QAClF;AAAA,MACD,CAAA;AAAA,MACA,eAAe,MAAM;AAAA,MAAC;AAAA,KACtB,CAAA;AAEF,IAAA,IAAIM,eAAmC,EAAC;AACxC,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,EAAI;AAEvB,IAAA,IAAI,OAAA,GAAU,CAAA,IAAK,IAAA,CAAK,MAAA,GAAS,CAAA,EAAG;AAEnC,MAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,IAAA,EAAM,OAAO,CAAA;AAC5C,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAA;AAAA,QAC7B,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AACrB,UAAA,MAAM,IAAA,GAAO,eAAoB,CAAA;AACjC,UAAA,OAAO,IAAA,CAAK,IAAI,KAAK,CAAA;AAAA,QACtB,CAAC;AAAA,OACF;AACA,MAAAA,eAAc,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AAAA,IAChD,CAAA,MAAO;AAEN,MAAA,MAAM,IAAA,GAAO,eAAmB,CAAA;AAChC,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AAClC,MAAAA,eAAc,MAAA,CAAO,QAAA;AAAA,IACtB;AAEA,IAAA,OAAO,EAAE,UAAUA,YAAAA,EAAa,QAAA,EAAU,KAAK,GAAA,EAAI,GAAI,OAAO,OAAA,EAAQ;AAAA,EACvE,CAAA;AAGA,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,IAAI,cAAmC,EAAC;AACxC,EAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,EAAA,MAAM,oBAID,EAAC;AAEN,EAAA,IAAI;AACH,IAAA,IAAI,CAAC,cAAA,EAAgB;AAEpB,MAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAU,OAAA,EAAQ,GAAI,MAAM,YAAA,CAAa,YAAA,CAAa,CAAC,CAAA,EAAI,SAAA,EAAW,EAAE,CAAA;AAC1F,MAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AACrB,MAAA,WAAA,GAAc,QAAA;AACd,MAAA,aAAA,GAAgB,QAAA;AAChB,MAAA,iBAAA,CAAkB,IAAA,CAAK,EAAE,WAAA,EAAa,YAAA,CAAa,CAAC,CAAA,EAAI,QAAA,EAAU,UAAU,CAAA;AAAA,IAC7E,CAAA,MAAA,IAAW,aAAa,YAAA,EAAc;AAErC,MAAA,KAAA,MAAW,SAAS,YAAA,EAAc;AACjC,QAAA,MAAM,MAAA,GAAS,YAAY,KAAK,CAAA,SAAA,CAAA;AAChC,QAAA,MAAM,EAAE,UAAU,QAAA,EAAU,OAAA,KAAY,MAAM,YAAA,CAAa,KAAA,EAAO,SAAA,EAAW,MAAM,CAAA;AACnF,QAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AACrB,QAAA,WAAA,CAAY,IAAA,CAAK,GAAG,QAAQ,CAAA;AAC5B,QAAA,aAAA,IAAiB,QAAA;AACjB,QAAA,iBAAA,CAAkB,KAAK,EAAE,WAAA,EAAa,KAAA,EAAO,QAAA,EAAU,UAAU,CAAA;AAAA,MAClE;AAAA,IACD,CAAA,MAAO;AAGN,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAA;AAAA,QAC7B,YAAA,CAAa,GAAA,CAAI,CAAC,KAAA,KAAU;AAC3B,UAAA,MAAM,MAAA,GAAS,YAAY,KAAK,CAAA,SAAA,CAAA;AAChC,UAAA,OAAO,YAAA,CAAa,KAAA,EAAO,SAAA,EAAW,MAAM,CAAA;AAAA,QAC7C,CAAC;AAAA,OACF;AACA,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,QAAQ,CAAA,EAAA,EAAK;AACxC,QAAA,MAAM,CAAA,GAAI,QAAQ,CAAC,CAAA;AACnB,QAAA,QAAA,CAAS,IAAA,CAAK,EAAE,OAAO,CAAA;AACvB,QAAA,WAAA,CAAY,IAAA,CAAK,GAAG,CAAA,CAAE,QAAQ,CAAA;AAC9B,QAAA,iBAAA,CAAkB,IAAA,CAAK;AAAA,UACtB,WAAA,EAAa,aAAa,CAAC,CAAA;AAAA,UAC3B,UAAU,CAAA,CAAE,QAAA;AAAA,UACZ,UAAU,CAAA,CAAE;AAAA,SACZ,CAAA;AAAA,MACF;AACA,MAAA,aAAA,GAAgB,IAAA,CAAK,IAAI,GAAG,OAAA,CAAQ,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,CAAC,CAAA;AAAA,IAC3D;AAGA,IAAA,MAAM,OAAA,GAAU,eAAe,WAAW,CAAA;AAC1C,IAAA,OAAA,CAAQ,IAAI,oOAA2C,CAAA;AAGvD,IAAA,IAAI,cAAA,EAAgB;AACnB,MAAA,KAAA,MAAW,MAAM,iBAAA,EAAmB;AACnC,QAAA,MAAM,SAAA,GAAY,cAAA,CAAe,EAAA,CAAG,QAAQ,CAAA;AAC5C,QAAA,MAAM,OAAA,GAAU,EAAA,CAAG,WAAA,CAAY,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,EAAA,CAAG,WAAA,CAAY,KAAA,CAAM,CAAC,CAAA;AAC/E,QAAA,MAAM,UAAoB,EAAC;AAC3B,QAAA,IAAI,SAAA,CAAU,UAAU,MAAA,GAAS,CAAA;AAChC,UAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,QAAA,EAAW,SAAA,CAAU,SAAA,CAAU,MAAM,CAAA,cAAA,CAAgB,CAAA;AACnE,QAAA,IAAI,SAAA,CAAU,UAAU,MAAA,GAAS,CAAA;AAChC,UAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,QAAA,EAAW,SAAA,CAAU,SAAA,CAAU,MAAM,CAAA,cAAA,CAAgB,CAAA;AACnE,QAAA,IAAI,SAAA,CAAU,UAAU,OAAA,GAAU,CAAA;AACjC,UAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,QAAA,EAAW,SAAA,CAAU,SAAA,CAAU,OAAO,CAAA,eAAA,CAAiB,CAAA;AACrE,QAAA,OAAA,CAAQ,GAAA;AAAA,UACP,CAAA,EAAA,EAAK,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAC,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,EAAA,EAAK,SAAA,CAAU,SAAA,CAAU,KAAK,CAAA,aAAA,EAAgB,EAAA,CAAG,QAAA,GAAW,GAAA,GAAO,CAAA,EAAG,EAAA,CAAG,QAAQ,CAAA,EAAA,CAAA,GAAO,CAAA,EAAA,CAAI,EAAA,CAAG,QAAA,GAAW,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,SAC3K;AAAA,MACD;AACA,MAAA,OAAA,CAAQ,IAAI,kOAAyC,CAAA;AAAA,IACtD;AAEA,IAAA,MAAM,EAAE,SAAA,EAAW,KAAA,EAAM,GAAI,OAAA;AAE7B,IAAA,MAAM,gBAA0B,EAAC;AACjC,IAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG,aAAA,CAAc,KAAK,CAAA,QAAA,EAAW,SAAA,CAAU,MAAM,CAAA,cAAA,CAAgB,CAAA;AACxF,IAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG,aAAA,CAAc,KAAK,CAAA,QAAA,EAAW,SAAA,CAAU,MAAM,CAAA,cAAA,CAAgB,CAAA;AACxF,IAAA,IAAI,SAAA,CAAU,UAAU,CAAA,EAAG,aAAA,CAAc,KAAK,CAAA,QAAA,EAAW,SAAA,CAAU,OAAO,CAAA,eAAA,CAAiB,CAAA;AAC3F,IAAA,IAAI,SAAA,CAAU,UAAU,CAAA,EAAG,aAAA,CAAc,KAAK,CAAA,QAAA,EAAW,SAAA,CAAU,OAAO,CAAA,eAAA,CAAiB,CAAA;AAE3F,IAAA,MAAM,YAAsB,EAAC;AAC7B,IAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG,SAAA,CAAU,KAAK,CAAA,QAAA,EAAW,KAAA,CAAM,MAAM,CAAA,cAAA,CAAgB,CAAA;AAC5E,IAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG,SAAA,CAAU,KAAK,CAAA,QAAA,EAAW,KAAA,CAAM,MAAM,CAAA,cAAA,CAAgB,CAAA;AAC5E,IAAA,IAAI,KAAA,CAAM,YAAY,CAAA,EAAG,SAAA,CAAU,KAAK,CAAA,QAAA,EAAW,KAAA,CAAM,SAAS,CAAA,iBAAA,CAAmB,CAAA;AACrF,IAAA,IAAI,KAAA,CAAM,UAAU,CAAA,EAAG,SAAA,CAAU,KAAK,CAAA,QAAA,EAAW,KAAA,CAAM,OAAO,CAAA,eAAA,CAAiB,CAAA;AAE/E,IAAA,OAAA,CAAQ,GAAA,CAAI,gBAAgB,aAAA,CAAc,IAAA,CAAK,IAAI,CAAC,CAAA,EAAA,EAAK,SAAA,CAAU,KAAK,CAAA,OAAA,CAAS,CAAA;AACjF,IAAA,OAAA,CAAQ,GAAA,CAAI,gBAAgB,SAAA,CAAU,IAAA,CAAK,IAAI,CAAC,CAAA,EAAA,EAAK,KAAA,CAAM,KAAK,CAAA,OAAA,CAAS,CAAA;AACzE,IAAA,OAAA,CAAQ,GAAA;AAAA,MACP,CAAA,aAAA,EAAgB,aAAA,GAAgB,GAAA,GAAO,CAAA,EAAG,aAAa,CAAA,EAAA,CAAA,GAAO,CAAA,EAAA,CAAI,aAAA,GAAgB,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,KACtG;AACA,IAAA,IAAI,cAAA,EAAgB;AACnB,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,aAAA,EAAgB,QAAQ,CAAA,CAAE,CAAA;AAAA,IACvC;AACA,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAEd,IAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACzB,MAAA,OAAA,CAAQ,IAAI,2CAA2C,CAAA;AAAA,IACxD,CAAA,MAAA,IAAW,KAAA,CAAM,SAAA,GAAY,CAAA,EAAG;AAC/B,MAAA,OAAA,CAAQ,IAAI,8CAA8C,CAAA;AAAA,IAC3D,CAAA,MAAO;AACN,MAAA,OAAA,CAAQ,IAAI,0CAA0C,CAAA;AAAA,IACvD;AAGA,IAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACzB,MAAA,MAAM,CAAA,CAAE,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IAC/B;AAEA,IAAA,OAAA,CAAQ,IAAA,CAAK,UAAU,MAAA,GAAS,CAAA,IAAK,MAAM,SAAA,GAAY,CAAA,GAAI,IAAI,CAAC,CAAA;AAAA,EACjE,SAAS,GAAA,EAAK;AACb,IAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACzB,MAAA,MAAM,CAAA,CAAE,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IAC/B;AACA,IAAA,OAAA,CAAQ,KAAA,CAAM,wBAAwB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AACxF,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EACf;AACD;AAMA,SAAS,eAAA,CAAmB,OAAY,CAAA,EAAkB;AACzD,EAAA,MAAM,SAAgB,EAAC;AACvB,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,SAAS,CAAC,CAAA;AACvC,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,MAAA,EAAQ,KAAK,IAAA,EAAM;AAC5C,IAAA,MAAA,CAAO,KAAK,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,CAAA,GAAI,IAAI,CAAC,CAAA;AAAA,EACrC;AACA,EAAA,OAAO,MAAA;AACR;AAMA,SAAS,aAAA,CAAc,OAAA,EAAiB,OAAA,EAAiB,UAAA,EAAgC;AACxF,EAAA,MAAM,QAAkB,EAAC;AAGzB,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA;AACnC,EAAA,IAAI,OAAA,GAAU,OAAA;AACd,EAAA,KAAA,MAAW,QAAQ,SAAA,EAAW;AAC7B,IAAA,IAAI,KAAK,QAAA,CAAS,GAAG,KAAK,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAAG;AAC9C,IAAA,OAAA,GAAUC,SAAA,CAAK,SAAS,IAAI,CAAA;AAAA,EAC7B;AAEA,EAAA,IAAI,CAACJ,aAAA,CAAW,OAAO,CAAA,EAAG,OAAO,KAAA;AAEjC,EAAA,MAAM,OAAA,GAAU,CAAC,GAAA,KAAsB;AACtC,IAAA,MAAM,IAAA,mBAAO,IAAI,GAAA,CAAI,CAAC,cAAA,EAAgB,QAAQ,cAAA,EAAgB,MAAA,EAAQ,UAAA,EAAY,QAAQ,CAAC,CAAA;AAC3F,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACH,MAAA,OAAA,GAAUK,eAAY,GAAG,CAAA;AAAA,IAC1B,CAAA,CAAA,MAAQ;AACP,MAAA;AAAA,IACD;AACA,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC5B,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,EAAG;AACrB,MAAA,MAAM,QAAA,GAAWD,SAAA,CAAK,GAAA,EAAK,KAAK,CAAA;AAChC,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI;AACH,QAAA,IAAA,GAAOE,YAAS,QAAQ,CAAA;AAAA,MACzB,CAAA,CAAA,MAAQ;AACP,QAAA;AAAA,MACD;AACA,MAAA,IAAI,IAAA,CAAK,aAAY,EAAG;AACvB,QAAA,OAAA,CAAQ,QAAQ,CAAA;AAAA,MACjB,CAAA,MAAA,IAAW,IAAA,CAAK,MAAA,EAAO,EAAG;AACzB,QAAA,IAAI,UAAA,CAAW,KAAK,CAAC,GAAA,KAAQ,MAAM,QAAA,CAAS,GAAG,CAAC,CAAA,EAAG;AAClD,UAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,QACpB;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAA;AAEA,EAAA,OAAA,CAAQ,OAAO,CAAA;AACf,EAAA,OAAO,MAAM,IAAA,EAAK;AACnB;AAMA,eAAe,WAAA,GAAc;AAC5B,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,EAAI;AAExB,EAAA,OAAA,CAAQ,IAAI,mCAAmC,CAAA;AAG/C,EAAA,MAAM,UAAA,GAAaF,SAAA,CAAK,GAAA,EAAK,uBAAuB,CAAA;AACpD,EAAA,IAAI,CAACJ,aAAA,CAAW,UAAU,CAAA,EAAG;AAC5B,IAAAO,gBAAA;AAAA,MACC,UAAA;AAAA,MACA,CAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,KAmBD;AACA,IAAA,OAAA,CAAQ,IAAI,iCAAiC,CAAA;AAAA,EAC9C,CAAA,MAAO;AACN,IAAA,OAAA,CAAQ,IAAI,kDAAkD,CAAA;AAAA,EAC/D;AAGA,EAAA,MAAM,QAAA,GAAWH,SAAA,CAAK,GAAA,EAAK,OAAO,CAAA;AAClC,EAAA,IAAI,CAACJ,aAAA,CAAW,QAAQ,CAAA,EAAG;AAC1B,IAAAQ,YAAA,CAAU,QAAA,EAAU,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AAAA,EACxC;AAEA,EAAA,MAAM,WAAA,GAAcJ,SAAA,CAAK,QAAA,EAAU,iBAAiB,CAAA;AACpD,EAAA,IAAI,CAACJ,aAAA,CAAW,WAAW,CAAA,EAAG;AAC7B,IAAAO,gBAAA;AAAA,MACC,WAAA;AAAA,MACA,CAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAaD;AACA,IAAA,OAAA,CAAQ,IAAI,iCAAiC,CAAA;AAAA,EAC9C,CAAA,MAAO;AACN,IAAA,OAAA,CAAQ,IAAI,kDAAkD,CAAA;AAAA,EAC/D;AAGA,EAAA,MAAM,aAAA,GAAgBH,SAAA,CAAK,GAAA,EAAK,YAAY,CAAA;AAC5C,EAAA,IAAIJ,aAAA,CAAW,aAAa,CAAA,EAAG;AAC9B,IAAA,MAAM,OAAA,GAAU,MAAM,OAAO,IAAS,CAAA,CAAE,IAAA,CAAK,CAAC,EAAA,KAAO,EAAA,CAAG,YAAA,CAAa,aAAA,EAAe,OAAO,CAAC,CAAA;AAC5F,IAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,cAAc,CAAA,EAAG;AACtC,MAAAO,gBAAA,CAAc,aAAA,EAAe,CAAA,EAAG,OAAA,CAAQ,OAAA,EAAS;;AAAA;AAAA;AAAA,CAAoC,CAAA;AACrF,MAAA,OAAA,CAAQ,IAAI,sBAAsB,CAAA;AAAA,IACnC;AAAA,EACD;AAEA,EAAA,OAAA,CAAQ,IAAI,4CAA4C,CAAA;AACxD,EAAA,OAAA,CAAQ,IAAI,4BAA4B,CAAA;AACzC;AAMA,eAAe,QAAA,GAAW;AACzB,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,EAAI;AAExB,EAAA,OAAA,CAAQ,IAAI,oCAA+B,CAAA;AAC3C,EAAA,OAAA,CAAQ,IAAI,gEAAgE,CAAA;AAG5E,EAAA,MAAM,QAAA,GAAWP,cAAWI,SAAA,CAAK,GAAA,EAAK,OAAO,CAAC,CAAA,GAC3C,UACAJ,aAAA,CAAWI,SAAA,CAAK,KAAK,kBAAkB,CAAC,IACvC,kBAAA,GACAJ,aAAA,CAAWI,UAAK,GAAA,EAAK,kBAAkB,CAAC,CAAA,GACvC,kBAAA,GACA,OAAA;AAGL,EAAA,MAAM,WAAA,GAAcJ,aAAA,CAAWI,SAAA,CAAK,GAAA,EAAK,UAAU,CAAC,CAAA,GACjD,UAAA,GACAJ,aAAA,CAAWI,SAAA,CAAK,GAAA,EAAK,eAAe,CAAC,IACpC,eAAA,GACA,UAAA;AAGJ,EAAA,IAAI,QAAA,GAAW,4CAAA;AACf,EAAA,IAAI;AACH,IAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,OAAO,QAAa,CAAA;AACpD,IAAA,MAAM,WAAA,GAAc,aAAA,CAAcA,SAAA,CAAK,GAAA,EAAK,cAAc,CAAC,CAAA;AAC3D,IAAA,MAAM,UAAA,GAAa,WAAA,CAAY,OAAA,CAAQ,8BAA8B,CAAA;AACrE,IAAA,MAAM,MAAA,GAASA,SAAA,CAAK,UAAA,EAAY,IAAI,CAAA;AACpC,IAAA,MAAM,OAAA,GAAUF,aAAA,CAAS,GAAA,EAAKE,SAAA,CAAK,MAAA,EAAQ,MAAA,EAAQ,UAAU,CAAC,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AAClF,IAAA,IAAIJ,cAAWI,SAAA,CAAK,MAAA,EAAQ,MAAA,EAAQ,UAAU,CAAC,CAAA,EAAG;AACjD,MAAA,QAAA,GAAW,OAAA;AAAA,IACZ;AAAA,EACD,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,MAAM,SAAA,GAAYA,SAAA,CAAK,GAAA,EAAK,SAAS,CAAA;AACrC,EAAA,IAAI,CAACJ,aAAA,CAAW,SAAS,CAAA,EAAG;AAC3B,IAAAQ,YAAA,CAAU,SAAA,EAAW,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AACxC,IAAA,OAAA,CAAQ,IAAI,mCAAmC,CAAA;AAAA,EAChD;AAGA,EAAA,MAAM,YAAA,GAAeJ,SAAA,CAAK,SAAA,EAAW,eAAe,CAAA;AACpD,EAAA,MAAM,gBAAA,GAA4C;AAAA,IACjD,4BAAA,EAA8B,CAAC,CAAA,EAAG,QAAQ,YAAY,CAAA,EAAG,QAAQ,YAAY,QAAQ,CAAA;AAAA,IACrF,8CAAA,EAAgD,IAAA;AAAA,IAChD,8CAAA,EAAgD,IAAA;AAAA,IAChD,eAAA,EAAiB,CAAC,CAAA,EAAG,QAAQ,YAAY,CAAA,EAAG,QAAQ,YAAY,QAAQ,CAAA;AAAA,IACxE,mBAAA,EAAqB,CAAC,CAAA,EAAG,WAAW,CAAA,aAAA,CAAe;AAAA,GACpD;AAEA,EAAA,IAAIJ,aAAA,CAAW,YAAY,CAAA,EAAG;AAC7B,IAAA,IAAI;AACH,MAAA,MAAM,WAAW,IAAA,CAAK,KAAA,CAAMC,eAAA,CAAa,YAAA,EAAc,OAAO,CAAC,CAAA;AAC/D,MAAA,IAAI,OAAA,GAAU,KAAA;AACd,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,gBAAgB,CAAA,EAAG;AAC5D,QAAA,IAAI,EAAE,OAAO,QAAA,CAAA,EAAW;AACvB,UAAA,QAAA,CAAS,GAAG,CAAA,GAAI,KAAA;AAChB,UAAA,OAAA,GAAU,IAAA;AAAA,QACX;AAAA,MACD;AACA,MAAA,IAAI,OAAA,EAAS;AACZ,QAAAM,gBAAA,CAAc,cAAc,CAAA,EAAG,IAAA,CAAK,UAAU,QAAA,EAAU,IAAA,EAAM,CAAC,CAAC;AAAA,CAAA,EAAM,OAAO,CAAA;AAC7E,QAAA,OAAA,CAAQ,IAAI,gDAAgD,CAAA;AAAA,MAC7D,CAAA,MAAO;AACN,QAAA,OAAA,CAAQ,GAAA;AAAA,UACP;AAAA,SACD;AAAA,MACD;AAAA,IACD,CAAA,CAAA,MAAQ;AACP,MAAAA,gBAAA,CAAc,cAAc,CAAA,EAAG,IAAA,CAAK,UAAU,gBAAA,EAAkB,IAAA,EAAM,CAAC,CAAC;AAAA,CAAA,EAAM,OAAO,CAAA;AACrF,MAAA,OAAA,CAAQ,IAAI,gDAAgD,CAAA;AAAA,IAC7D;AAAA,EACD,CAAA,MAAO;AACN,IAAAA,gBAAA,CAAc,cAAc,CAAA,EAAG,IAAA,CAAK,UAAU,gBAAA,EAAkB,IAAA,EAAM,CAAC,CAAC;AAAA,CAAA,EAAM,OAAO,CAAA;AACrF,IAAA,OAAA,CAAQ,IAAI,gDAAgD,CAAA;AAAA,EAC7D;AAGA,EAAA,MAAM,cAAA,GAAiBH,SAAA,CAAK,SAAA,EAAW,iBAAiB,CAAA;AACxD,EAAA,MAAM,qBAAA,GAAwB;AAAA,IAC7B,kCAAA;AAAA,IACA;AAAA,GACD;AAEA,EAAA,IAAIJ,aAAA,CAAW,cAAc,CAAA,EAAG;AAC/B,IAAA,IAAI;AACH,MAAA,MAAM,WAAW,IAAA,CAAK,KAAA,CAAMC,eAAA,CAAa,cAAA,EAAgB,OAAO,CAAC,CAAA;AACjE,MAAA,MAAM,IAAA,GAAiB,QAAA,CAAS,eAAA,IAAmB,EAAC;AACpD,MAAA,IAAI,OAAA,GAAU,KAAA;AACd,MAAA,KAAA,MAAW,OAAO,qBAAA,EAAuB;AACxC,QAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAAG;AACxB,UAAA,IAAA,CAAK,KAAK,GAAG,CAAA;AACb,UAAA,OAAA,GAAU,IAAA;AAAA,QACX;AAAA,MACD;AACA,MAAA,IAAI,OAAA,EAAS;AACZ,QAAA,QAAA,CAAS,eAAA,GAAkB,IAAA;AAC3B,QAAAM,gBAAA,CAAc,gBAAgB,CAAA,EAAG,IAAA,CAAK,UAAU,QAAA,EAAU,IAAA,EAAM,CAAC,CAAC;AAAA,CAAA,EAAM,OAAO,CAAA;AAC/E,QAAA,OAAA,CAAQ,IAAI,kDAAkD,CAAA;AAAA,MAC/D,CAAA,MAAO;AACN,QAAA,OAAA,CAAQ,GAAA;AAAA,UACP;AAAA,SACD;AAAA,MACD;AAAA,IACD,CAAA,CAAA,MAAQ;AACP,MAAAA,gBAAA;AAAA,QACC,cAAA;AAAA,QACA,CAAA,EAAG,KAAK,SAAA,CAAU,EAAE,iBAAiB,qBAAA,EAAsB,EAAG,IAAA,EAAM,CAAC,CAAC;AAAA,CAAA;AAAA,QACtE;AAAA,OACD;AACA,MAAA,OAAA,CAAQ,IAAI,kDAAkD,CAAA;AAAA,IAC/D;AAAA,EACD,CAAA,MAAO;AACN,IAAAA,gBAAA;AAAA,MACC,cAAA;AAAA,MACA,CAAA,EAAG,KAAK,SAAA,CAAU,EAAE,iBAAiB,qBAAA,EAAsB,EAAG,IAAA,EAAM,CAAC,CAAC;AAAA,CAAA;AAAA,MACtE;AAAA,KACD;AACA,IAAA,OAAA,CAAQ,IAAI,kDAAkD,CAAA;AAAA,EAC/D;AAEA,EAAA,OAAA,CAAQ,IAAI,yEAAyE,CAAA;AACrF,EAAA,OAAA,CAAQ,IAAI,oBAAoB,CAAA;AAChC,EAAA,OAAA,CAAQ,IAAI,0EAAqE,CAAA;AACjF,EAAA,OAAA,CAAQ,IAAI,wFAAmF,CAAA;AAC/F,EAAA,OAAA,CAAQ,IAAI,yFAAoF,CAAA;AAChG,EAAA,OAAA,CAAQ,IAAI,0EAAqE,CAAA;AACjF,EAAA,OAAA,CAAQ,IAAI,uEAAkE,CAAA;AAC9E,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,OAAA,CAAQ,IAAI,sEAAsE,CAAA;AAClF,EAAA,OAAA,CAAQ,GAAA,EAAI;AACb;AAMA,eAAe,UAAA,GAA8C;AAC5D,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,EAAI;AACxB,EAAA,MAAM,UAAA,GAAa;AAAA,IAClB,uBAAA;AAAA,IACA,uBAAA;AAAA,IACA,wBAAA;AAAA,IACA;AAAA,GACD;AAEA,EAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC9B,IAAA,MAAM,UAAA,GAAaR,YAAA,CAAQ,GAAA,EAAK,IAAI,CAAA;AACpC,IAAA,IAAIC,aAAA,CAAW,UAAU,CAAA,EAAG;AAC3B,MAAA,IAAI;AAEH,QAAA,IAAI,KAAK,QAAA,CAAS,KAAK,KAAK,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAClD,UAAA,MAAM,sBAAA,EAAuB;AAAA,QAC9B;AACA,QAAA,MAAM,OAAA,GAAUJ,iBAAA,CAAc,UAAU,CAAA,CAAE,IAAA;AAC1C,QAAA,MAAM,GAAA,GAAM,MAAM,OAAO,OAAA,CAAA;AACzB,QAAA,OAAO,IAAI,OAAA,IAAW,GAAA;AAAA,MACvB,CAAA,CAAA,MAAQ;AAEP,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,wBAAA,EAA2B,IAAI,CAAA,iBAAA,CAAmB,CAAA;AAAA,MAChE;AAAA,IACD;AAAA,EACD;AAEA,EAAA,OAAO,MAAA;AACR;AAMA,IAAI,kBAAA,GAAqB,KAAA;AASzB,eAAe,sBAAA,GAAwC;AACtD,EAAA,IAAI,kBAAA,EAAoB;AAIxB,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA;AAC1C,EAAA,IACC,QAAA,CAAS,QAAA,CAAS,KAAK,CAAA,IACvB,SAAS,QAAA,CAAS,SAAS,CAAA,IAC3B,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,IAC1B,OAAA,CAAQ,SAAS,GAAA,EAChB;AACD,IAAA,kBAAA,GAAqB,IAAA;AACrB,IAAA;AAAA,EACD;AAIA,EAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,OAAO,QAAa,CAAA;AACpD,EAAA,MAAM,WAAA,GAAc,cAAcA,iBAAA,CAAcG,YAAA,CAAQ,QAAQ,GAAA,EAAI,EAAG,cAAc,CAAC,CAAC,CAAA;AAIvF,EAAA,IAAI;AACH,IAAA,MAAM,UAAA,GAAa,WAAA,CAAY,OAAA,CAAQ,aAAa,CAAA;AACpD,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,OAAOH,iBAAA,CAAc,UAAU,CAAA,CAAE,IAAA,CAAA;AAC5D,IAAA,IAAI,OAAO,aAAa,UAAA,EAAY;AACnC,MAAA,QAAA,EAAS;AACT,MAAA,kBAAA,GAAqB,IAAA;AACrB,MAAA;AAAA,IACD;AAAA,EACD,CAAA,CAAA,MAAQ;AAAA,EAER;AAIA,EAAA,KAAA,MAAW,MAAA,IAAU,CAAC,SAAA,EAAW,aAAa,CAAA,EAAG;AAChD,IAAA,IAAI;AACH,MAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,OAAO,QAAa,CAAA;AAC/C,MAAA,IAAI,OAAO,aAAa,UAAA,EAAY;AAEnC,QAAA,QAAA,CAAS,MAAA,EAAQA,kBAAcG,YAAA,CAAQ,OAAA,CAAQ,KAAI,EAAG,GAAG,CAAC,CAAC,CAAA;AAC3D,QAAA,kBAAA,GAAqB,IAAA;AACrB,QAAA;AAAA,MACD;AAAA,IACD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACD;AAGA,EAAA,OAAA,CAAQ,KAAA;AAAA,IACP;AAAA,GAKD;AACA,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AACf;AAyBA,SAAS,WAAW,IAAA,EAA0B;AAC7C,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,GAAA,GAAM,KAAK,CAAC,CAAA;AAClB,IAAA,QAAQ,GAAA;AAAK,MACZ,KAAK,UAAA;AACJ,QAAA,KAAA,CAAM,MAAA,GAAS,IAAA;AACf,QAAA;AAAA,MACD,KAAK,YAAA;AACJ,QAAA,KAAA,CAAM,QAAA,GAAW,IAAA;AACjB,QAAA;AAAA,MACD,KAAK,SAAA;AACJ,QAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AACd,QAAA;AAAA,MACD,KAAK,OAAA;AACJ,QAAA,KAAA,CAAM,GAAA,GAAM,IAAA;AACZ,QAAA;AAAA,MACD,KAAK,QAAA;AACJ,QAAA,KAAA,CAAM,IAAA,GAAO,IAAA;AACb,QAAA;AAAA,MACD,KAAK,WAAA;AACJ,QAAA,KAAA,CAAM,OAAA,GAAU,IAAA,CAAK,EAAE,CAAC,CAAA;AACxB,QAAA;AAAA,MACD,KAAK,WAAA;AACJ,QAAA,KAAA,CAAM,OAAA,GAAU,OAAO,QAAA,CAAS,IAAA,CAAK,EAAE,CAAC,CAAA,IAAK,KAAK,EAAE,CAAA;AACpD,QAAA;AAAA,MACD,KAAK,WAAA;AACJ,QAAA,KAAA,CAAM,OAAA,GAAU,OAAO,QAAA,CAAS,IAAA,CAAK,EAAE,CAAC,CAAA,IAAK,SAAS,EAAE,CAAA;AACxD,QAAA;AAAA,MACD,KAAK,WAAA;AACJ,QAAA,KAAA,CAAM,OAAA,GAAU,OAAO,QAAA,CAAS,IAAA,CAAK,EAAE,CAAC,CAAA,IAAK,KAAK,EAAE,CAAA;AACpD,QAAA;AAAA,MACD,KAAK,QAAA;AAAA,MACL,KAAK,IAAA;AACJ,QAAA,KAAA,CAAM,IAAA,GAAO,IAAA,CAAK,EAAE,CAAC,CAAA;AACrB,QAAA;AAAA,MACD,KAAK,OAAA;AAAA,MACL,KAAK,QAAA;AACJ,QAAA,KAAA,CAAM,GAAA,GAAM,IAAA,CAAK,EAAE,CAAC,CAAA;AACpB,QAAA;AAAA,MACD,KAAK,YAAA;AACJ,QAAA,KAAA,CAAM,QAAA,GAAW,IAAA,CAAK,EAAE,CAAC,CAAA;AACzB,QAAA;AAAA,MACD,KAAK,YAAA;AACJ,QAAA,KAAA,CAAM,QAAA,GAAW,IAAA,CAAK,EAAE,CAAC,CAAA;AACzB,QAAA;AAAA;AACF,EACD;AAEA,EAAA,OAAO,KAAA;AACR;AAMA,SAAS,SAAA,GAAY;AACpB,EAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,eAAA,EACI,OAAO,CAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAiDvB,CAAA;AACD;AAMA,IAAA,EAAK,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AACrB,EAAA,OAAA,CAAQ,KAAA,CAAM,cAAA,EAAgB,GAAA,CAAI,OAAO,CAAA;AACzC,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AACf,CAAC,CAAA","file":"cli.cjs","sourcesContent":["#!/usr/bin/env node\n// ============================================================================\n// Browsecraft - CLI\n// The command-line interface for running tests and initializing projects.\n//\n// npx browsecraft test # Run all tests\n// npx browsecraft test login.test.ts # Run specific file\n// npx browsecraft init # Scaffold a new project\n// npx browsecraft --help # Show help\n// ============================================================================\n\nimport { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';\nimport { join, relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { BrowserName } from 'browsecraft-bidi';\nimport { type RunnableTest, type RunnerOptions, TestRunner } from 'browsecraft-runner';\nimport { Browser } from './browser.js';\nimport { type UserConfig, resolveConfig } from './config.js';\nimport { type TestCase, runAfterAllHooks, runTest, testRegistry } from './test.js';\n\nconst VERSION = '0.3.0';\n\nasync function main() {\n\tconst args = process.argv.slice(2);\n\n\tif (args.length === 0 || args.includes('--help') || args.includes('-h')) {\n\t\tprintHelp();\n\t\treturn;\n\t}\n\n\tif (args.includes('--version') || args.includes('-v')) {\n\t\tconsole.log(`browsecraft v${VERSION}`);\n\t\treturn;\n\t}\n\n\tconst command = args[0];\n\n\tswitch (command) {\n\t\tcase 'test':\n\t\t\tawait runTests(args.slice(1));\n\t\t\tbreak;\n\t\tcase 'init':\n\t\t\tawait initProject();\n\t\t\tbreak;\n\t\tcase 'setup-ide':\n\t\t\tawait setupIde();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t// If no command, assume it's a file path to test\n\t\t\tif (command && (command.endsWith('.ts') || command.endsWith('.js'))) {\n\t\t\t\tawait runTests(args);\n\t\t\t} else {\n\t\t\t\tconsole.error(`Unknown command: ${command}`);\n\t\t\t\tconsole.error('Run \"browsecraft --help\" for usage information.');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Test Command\n// ---------------------------------------------------------------------------\n\nasync function runTests(args: string[]) {\n\t// Parse CLI flags\n\tconst flags = parseFlags(args);\n\tconst filePatterns = args.filter((a) => !a.startsWith('--'));\n\n\t// Load config file if it exists\n\tconst userConfig = await loadConfig();\n\tconst config = resolveConfig(userConfig);\n\n\t// Apply CLI overrides\n\tif (flags.headed || flags.headless === false) {\n\t\tconfig.headless = false;\n\t}\n\tif (flags.browser) {\n\t\tconfig.browser = flags.browser as BrowserName;\n\t}\n\tif (flags.workers !== undefined) {\n\t\tconfig.workers = flags.workers;\n\t}\n\tif (flags.timeout !== undefined) {\n\t\tconfig.timeout = flags.timeout;\n\t}\n\tif (flags.retries !== undefined) {\n\t\tconfig.retries = flags.retries;\n\t}\n\tif (flags.debug) {\n\t\tconfig.debug = true;\n\t}\n\n\t// BDD mode: run .feature files with step definitions\n\tif (flags.bdd) {\n\t\tawait runBddTests(config, userConfig, flags, filePatterns);\n\t\treturn;\n\t}\n\n\t// Set up runner options\n\tconst runnerOptions: RunnerOptions = {\n\t\tconfig,\n\t\tfiles: filePatterns.length > 0 ? filePatterns : undefined,\n\t\tgrep: flags.grep,\n\t\tbail: flags.bail,\n\t};\n\n\t// Run tests\n\tconst runner = new TestRunner(runnerOptions);\n\n\t// loadFile callback: imports the test file and returns registered tests\n\tconst loadFile = async (file: string): Promise<RunnableTest[]> => {\n\t\tconst startIdx = testRegistry.length;\n\n\t\t// For TypeScript files, register a TypeScript loader if available\n\t\tif (file.endsWith('.ts') || file.endsWith('.mts')) {\n\t\t\tawait ensureTypeScriptLoader();\n\t\t}\n\n\t\tconst fileUrl = pathToFileURL(file).href;\n\t\tawait import(fileUrl);\n\t\treturn testRegistry.slice(startIdx).map((tc) => ({\n\t\t\ttitle: tc.title,\n\t\t\tsuitePath: tc.suitePath,\n\t\t\tskip: tc.skip,\n\t\t\tonly: tc.only,\n\t\t\toptions: tc.options,\n\t\t\tfn: tc.fn as (fixtures: unknown) => Promise<void>,\n\t\t}));\n\t};\n\n\t// Launch a shared browser for all tests\n\tlet sharedBrowser: Browser | undefined;\n\n\ttry {\n\t\tsharedBrowser = await Browser.launch({\n\t\t\tbrowser: config.browser,\n\t\t\theadless: config.headless,\n\t\t\texecutablePath: config.executablePath,\n\t\t\tdebug: config.debug,\n\t\t\ttimeout: config.timeout,\n\t\t});\n\t} catch (err) {\n\t\tconsole.error(`Failed to launch browser: ${err instanceof Error ? err.message : String(err)}`);\n\t\tprocess.exit(1);\n\t}\n\n\t// executeTest callback: runs a single test with fixture setup/teardown\n\tconst executeTest = async (test: RunnableTest) => {\n\t\treturn runTest(test as unknown as TestCase, sharedBrowser);\n\t};\n\n\ttry {\n\t\tconst exitCode = await runner.run(loadFile, executeTest);\n\t\tawait sharedBrowser.close().catch(() => {});\n\t\tprocess.exit(exitCode);\n\t} catch (err) {\n\t\tawait sharedBrowser?.close().catch(() => {});\n\t\tthrow err;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// BDD Command — runs .feature files with step definitions\n//\n// Supports:\n// - Single / multiple feature files: browsecraft test --bdd login.feature\n// - Tag filtering: --tag \"@smoke and not @wip\"\n// - Name filtering: --grep \"login\"\n// - Multi-browser: --browser chrome,firefox\n// - Parallel: --workers 4\n// - Strategy: --strategy parallel|sequential|matrix\n// ---------------------------------------------------------------------------\n\ntype BddModule = typeof import('browsecraft-bdd');\n\nasync function runBddTests(\n\tconfig: ReturnType<typeof resolveConfig>,\n\tuserConfig?: UserConfig,\n\tflags?: CLIFlags,\n\tfilePatterns?: string[],\n): Promise<void> {\n\tconst bddModule = (await import('browsecraft-bdd')) as BddModule;\n\tconst { parseGherkin, BddExecutor, registerBuiltInSteps, After, computeSummary } = bddModule;\n\tconst cwd = process.cwd();\n\n\t// ── Resolve options from config + CLI flags ────────────────────────\n\tconst bddConfig = userConfig?.bdd ?? {};\n\tconst featuresPattern = bddConfig.features ?? 'features/**/*.feature';\n\tconst stepsPattern = bddConfig.steps ?? 'steps/**/*.{ts,js,mts,mjs}';\n\tconst useBuiltInSteps = bddConfig.builtInSteps !== false;\n\n\t// Browsers: --browser chrome,firefox or config.browsers or [config.browser]\n\tconst browserNames: string[] = flags?.browser\n\t\t? flags.browser.split(',').map((b) => b.trim())\n\t\t: (config.browsers ?? [config.browser]);\n\n\t// Workers per browser (for parallel feature execution)\n\tconst workers = flags?.workers ?? (browserNames.length > 1 ? 1 : 1);\n\n\t// Strategy: --strategy or config.strategy\n\tconst strategy = (flags?.strategy ?? config.strategy ?? 'sequential') as\n\t\t| 'parallel'\n\t\t| 'sequential'\n\t\t| 'matrix';\n\n\t// Tag filter: --tag or bddConfig.tagFilter\n\tconst tagFilter = flags?.tag ?? bddConfig.tagFilter;\n\n\t// Grep: --grep or --scenario or bddConfig.grep\n\tconst grepPattern = flags?.scenario ?? flags?.grep ?? bddConfig.grep;\n\n\t// Fail fast: --bail\n\tconst failFast = flags?.bail ?? false;\n\n\t// ── Step 1: Discover .feature files ────────────────────────────────\n\t// Parse feature:line syntax (e.g. features/login.feature:15)\n\tconst targetLines = new Map<string, number[]>(); // file → line numbers\n\tlet featureFiles: string[];\n\n\tif (filePatterns && filePatterns.length > 0) {\n\t\t// Explicit feature files from CLI positional args\n\t\tconst resolvedPaths: string[] = [];\n\t\tfor (const pattern of filePatterns) {\n\t\t\tconst [filePart, linePart] = pattern.split(':');\n\t\t\tconst absPath = resolve(cwd, filePart!);\n\t\t\tif (!existsSync(absPath)) continue;\n\n\t\t\tif (!resolvedPaths.includes(absPath)) {\n\t\t\t\tresolvedPaths.push(absPath);\n\t\t\t}\n\t\t\tif (linePart) {\n\t\t\t\tconst lineNum = Number.parseInt(linePart, 10);\n\t\t\t\tif (!Number.isNaN(lineNum)) {\n\t\t\t\t\tconst existing = targetLines.get(absPath) ?? [];\n\t\t\t\t\texisting.push(lineNum);\n\t\t\t\t\ttargetLines.set(absPath, existing);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfeatureFiles = resolvedPaths;\n\t\tif (featureFiles.length === 0) {\n\t\t\tconsole.error('\\n No matching feature files found.\\n');\n\t\t\tprocess.exit(1);\n\t\t}\n\t} else {\n\t\tfeatureFiles = discoverFiles(cwd, featuresPattern, ['.feature']);\n\t}\n\n\tif (featureFiles.length === 0) {\n\t\tconsole.log('\\n No .feature files found.\\n');\n\t\tconsole.log(` Feature pattern: ${featuresPattern}`);\n\t\tconsole.log(' Create features/*.feature files or adjust bdd.features in your config.\\n');\n\t\tprocess.exit(0);\n\t}\n\n\t// ── Step 2: Register steps ─────────────────────────────────────────\n\tif (useBuiltInSteps) {\n\t\tregisterBuiltInSteps();\n\t}\n\n\tconst stepFiles = discoverFiles(cwd, stepsPattern, ['.ts', '.js', '.mts', '.mjs']);\n\tfor (const stepFile of stepFiles) {\n\t\tif (stepFile.endsWith('.ts') || stepFile.endsWith('.mts')) {\n\t\t\tawait ensureTypeScriptLoader();\n\t\t}\n\t\tconst fileUrl = pathToFileURL(stepFile).href;\n\t\tawait import(fileUrl);\n\t}\n\n\t// Cleanup hook for browser contexts\n\tAfter(async ({ world }) => {\n\t\tconst w = world as unknown as Record<string, { close(): Promise<unknown> } | undefined>;\n\t\tif (w?._context) {\n\t\t\tawait w._context.close().catch(() => {});\n\t\t}\n\t});\n\n\t// ── Step 3: Parse .feature files ───────────────────────────────────\n\tconst documents = featureFiles.map((file) => {\n\t\tconst source = readFileSync(file, 'utf-8');\n\t\treturn parseGherkin(source, relative(cwd, file));\n\t});\n\n\t// Build a scenario filter for line-number targeting\n\tconst lineFilter =\n\t\ttargetLines.size > 0\n\t\t\t? (scenario: { line: number; name: string }, _tags: string[], uri?: string) => {\n\t\t\t\t\tfor (const [file, lines] of targetLines) {\n\t\t\t\t\t\tconst relPath = relative(cwd, file);\n\t\t\t\t\t\tif (uri === relPath || uri === file) {\n\t\t\t\t\t\t\treturn lines.includes(scenario.line);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true; // no line constraint for this file\n\t\t\t\t}\n\t\t\t: undefined;\n\n\t// ── Step 4: Determine execution plan ───────────────────────────────\n\tconst isMultiBrowser = browserNames.length > 1;\n\tconst isParallel = workers > 1;\n\n\t// Header\n\tconst parts: string[] = [\n\t\t`${featureFiles.length} feature file${featureFiles.length > 1 ? 's' : ''}`,\n\t];\n\tif (isMultiBrowser) parts.push(`on ${browserNames.join(', ')}`);\n\tif (isParallel) parts.push(`(${workers} workers)`);\n\tif (tagFilter) parts.push(`[tags: ${tagFilter}]`);\n\tif (grepPattern) parts.push(`[grep: ${grepPattern}]`);\n\tif (targetLines.size > 0) {\n\t\tconst lineDescs = [...targetLines.entries()].map(\n\t\t\t([f, ls]) => `${relative(cwd, f)}:${ls.join(',')}`,\n\t\t);\n\t\tparts.push(`[lines: ${lineDescs.join(' ')}]`);\n\t}\n\n\tconsole.log(`\\n Browsecraft BDD - Running ${parts.join(' ')}\\n`);\n\n\tif (isMultiBrowser) {\n\t\tconsole.log(` Strategy: ${strategy}`);\n\t\tconsole.log(\n\t\t\t` Browsers: ${browserNames.map((b) => b.charAt(0).toUpperCase() + b.slice(1)).join(', ')}`,\n\t\t);\n\t\tconsole.log('');\n\t}\n\n\t// ── Step 5: Execute ────────────────────────────────────────────────\n\ttype FeatureResultType = Awaited<\n\t\tReturnType<InstanceType<typeof BddExecutor>['run']>\n\t>['features'][number];\n\n\t/**\n\t * Run a set of documents on a specific browser.\n\t * Returns the feature results and the launched browser instance.\n\t */\n\tconst runOnBrowser = async (\n\t\tbrowserName: string,\n\t\tdocs: ReturnType<typeof parseGherkin>[],\n\t\tprefix: string,\n\t): Promise<{ features: FeatureResultType[]; duration: number; browser: Browser }> => {\n\t\tconst browser = await Browser.launch({\n\t\t\tbrowser: browserName as BrowserName,\n\t\t\theadless: config.headless,\n\t\t\texecutablePath: config.executablePath,\n\t\t\tdebug: config.debug,\n\t\t\ttimeout: config.timeout,\n\t\t});\n\n\t\tconst createExecutor = (docSubset: ReturnType<typeof parseGherkin>[]) =>\n\t\t\tnew BddExecutor({\n\t\t\t\tstepTimeout: config.timeout,\n\t\t\t\ttagFilter: tagFilter ?? undefined,\n\t\t\t\tgrep: grepPattern ?? undefined,\n\t\t\t\tscenarioFilter: lineFilter ?? undefined,\n\t\t\t\tfailFast,\n\t\t\t\tworldFactory: async () => {\n\t\t\t\t\tconst context = await browser.newContext();\n\t\t\t\t\tconst page = await context.newPage();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpage,\n\t\t\t\t\t\tbrowser,\n\t\t\t\t\t\tctx: {},\n\t\t\t\t\t\tattach: () => {},\n\t\t\t\t\t\tlog: (msg: string) => console.log(` ${prefix}${msg}`),\n\t\t\t\t\t\t_context: context,\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\tonFeatureStart: (feature) => {\n\t\t\t\t\tconsole.log(`\\n ${prefix}Feature: ${feature.name}`);\n\t\t\t\t},\n\t\t\t\tonScenarioStart: (scenario) => {\n\t\t\t\t\tconsole.log(` ${prefix}Scenario: ${scenario.name}`);\n\t\t\t\t},\n\t\t\t\tonStepEnd: (result) => {\n\t\t\t\t\tconst icon =\n\t\t\t\t\t\tresult.status === 'passed'\n\t\t\t\t\t\t\t? '\\x1b[32m+\\x1b[0m'\n\t\t\t\t\t\t\t: result.status === 'failed'\n\t\t\t\t\t\t\t\t? '\\x1b[31mx\\x1b[0m'\n\t\t\t\t\t\t\t\t: result.status === 'undefined'\n\t\t\t\t\t\t\t\t\t? '\\x1b[33m?\\x1b[0m'\n\t\t\t\t\t\t\t\t\t: result.status === 'pending'\n\t\t\t\t\t\t\t\t\t\t? '\\x1b[33m-\\x1b[0m'\n\t\t\t\t\t\t\t\t\t\t: '\\x1b[90m-\\x1b[0m';\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t` ${prefix}${icon} ${result.keyword.trim()} ${result.text} (${result.duration}ms)`,\n\t\t\t\t\t);\n\t\t\t\t\tif (result.status === 'failed' && result.error) {\n\t\t\t\t\t\tconsole.log(` ${prefix}${result.error.message}`);\n\t\t\t\t\t}\n\t\t\t\t\tif (result.status === 'undefined') {\n\t\t\t\t\t\tconsole.log(` ${prefix}Step not defined. Add it to your step definitions.`);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonScenarioEnd: () => {},\n\t\t\t});\n\n\t\tlet allFeatures: FeatureResultType[] = [];\n\t\tconst start = Date.now();\n\n\t\tif (workers > 1 && docs.length > 1) {\n\t\t\t// Parallel: split documents into worker chunks\n\t\t\tconst chunks = splitIntoChunks(docs, workers);\n\t\t\tconst results = await Promise.all(\n\t\t\t\tchunks.map((chunk) => {\n\t\t\t\t\tconst exec = createExecutor(chunk);\n\t\t\t\t\treturn exec.run(chunk);\n\t\t\t\t}),\n\t\t\t);\n\t\t\tallFeatures = results.flatMap((r) => r.features);\n\t\t} else {\n\t\t\t// Sequential: single executor\n\t\t\tconst exec = createExecutor(docs);\n\t\t\tconst result = await exec.run(docs);\n\t\t\tallFeatures = result.features;\n\t\t}\n\n\t\treturn { features: allFeatures, duration: Date.now() - start, browser };\n\t};\n\n\t// ── Execute according to strategy ──────────────────────────────────\n\tconst browsers: Browser[] = [];\n\tlet allFeatures: FeatureResultType[] = [];\n\tlet totalDuration = 0;\n\tconst perBrowserResults: Array<{\n\t\tbrowserName: string;\n\t\tfeatures: FeatureResultType[];\n\t\tduration: number;\n\t}> = [];\n\n\ttry {\n\t\tif (!isMultiBrowser) {\n\t\t\t// Single browser — simple path\n\t\t\tconst { features, duration, browser } = await runOnBrowser(browserNames[0]!, documents, '');\n\t\t\tbrowsers.push(browser);\n\t\t\tallFeatures = features;\n\t\t\ttotalDuration = duration;\n\t\t\tperBrowserResults.push({ browserName: browserNames[0]!, features, duration });\n\t\t} else if (strategy === 'sequential') {\n\t\t\t// Sequential: one browser at a time, each runs all features\n\t\t\tfor (const bName of browserNames) {\n\t\t\t\tconst prefix = `\\x1b[36m[${bName}]\\x1b[0m `;\n\t\t\t\tconst { features, duration, browser } = await runOnBrowser(bName, documents, prefix);\n\t\t\t\tbrowsers.push(browser);\n\t\t\t\tallFeatures.push(...features);\n\t\t\t\ttotalDuration += duration;\n\t\t\t\tperBrowserResults.push({ browserName: bName, features, duration });\n\t\t\t}\n\t\t} else {\n\t\t\t// Parallel or Matrix: all browsers simultaneously\n\t\t\t// (matrix = every feature on every browser; parallel = same as matrix for distinct browsers)\n\t\t\tconst results = await Promise.all(\n\t\t\t\tbrowserNames.map((bName) => {\n\t\t\t\t\tconst prefix = `\\x1b[36m[${bName}]\\x1b[0m `;\n\t\t\t\t\treturn runOnBrowser(bName, documents, prefix);\n\t\t\t\t}),\n\t\t\t);\n\t\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\t\tconst r = results[i]!;\n\t\t\t\tbrowsers.push(r.browser);\n\t\t\t\tallFeatures.push(...r.features);\n\t\t\t\tperBrowserResults.push({\n\t\t\t\t\tbrowserName: browserNames[i]!,\n\t\t\t\t\tfeatures: r.features,\n\t\t\t\t\tduration: r.duration,\n\t\t\t\t});\n\t\t\t}\n\t\t\ttotalDuration = Math.max(...results.map((r) => r.duration));\n\t\t}\n\n\t\t// ── Print summary ──────────────────────────────────────────────\n\t\tconst summary = computeSummary(allFeatures);\n\t\tconsole.log('\\n ─────────────────────────────────────');\n\n\t\t// Per-browser breakdown for multi-browser runs\n\t\tif (isMultiBrowser) {\n\t\t\tfor (const br of perBrowserResults) {\n\t\t\t\tconst brSummary = computeSummary(br.features);\n\t\t\t\tconst brLabel = br.browserName.charAt(0).toUpperCase() + br.browserName.slice(1);\n\t\t\t\tconst brParts: string[] = [];\n\t\t\t\tif (brSummary.scenarios.passed > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[32m${brSummary.scenarios.passed} passed\\x1b[0m`);\n\t\t\t\tif (brSummary.scenarios.failed > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[31m${brSummary.scenarios.failed} failed\\x1b[0m`);\n\t\t\t\tif (brSummary.scenarios.skipped > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[33m${brSummary.scenarios.skipped} skipped\\x1b[0m`);\n\t\t\t\tconsole.log(\n\t\t\t\t\t` ${brLabel.padEnd(10)} ${brParts.join(', ')} (${brSummary.scenarios.total} scenarios) ${br.duration < 1000 ? `${br.duration}ms` : `${(br.duration / 1000).toFixed(1)}s`}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconsole.log(' ─────────────────────────────────────');\n\t\t}\n\n\t\tconst { scenarios, steps } = summary;\n\n\t\tconst scenarioParts: string[] = [];\n\t\tif (scenarios.passed > 0) scenarioParts.push(`\\x1b[32m${scenarios.passed} passed\\x1b[0m`);\n\t\tif (scenarios.failed > 0) scenarioParts.push(`\\x1b[31m${scenarios.failed} failed\\x1b[0m`);\n\t\tif (scenarios.skipped > 0) scenarioParts.push(`\\x1b[33m${scenarios.skipped} skipped\\x1b[0m`);\n\t\tif (scenarios.pending > 0) scenarioParts.push(`\\x1b[33m${scenarios.pending} pending\\x1b[0m`);\n\n\t\tconst stepParts: string[] = [];\n\t\tif (steps.passed > 0) stepParts.push(`\\x1b[32m${steps.passed} passed\\x1b[0m`);\n\t\tif (steps.failed > 0) stepParts.push(`\\x1b[31m${steps.failed} failed\\x1b[0m`);\n\t\tif (steps.undefined > 0) stepParts.push(`\\x1b[33m${steps.undefined} undefined\\x1b[0m`);\n\t\tif (steps.skipped > 0) stepParts.push(`\\x1b[90m${steps.skipped} skipped\\x1b[0m`);\n\n\t\tconsole.log(` Scenarios: ${scenarioParts.join(', ')} (${scenarios.total} total)`);\n\t\tconsole.log(` Steps: ${stepParts.join(', ')} (${steps.total} total)`);\n\t\tconsole.log(\n\t\t\t` Time: ${totalDuration < 1000 ? `${totalDuration}ms` : `${(totalDuration / 1000).toFixed(1)}s`}`,\n\t\t);\n\t\tif (isMultiBrowser) {\n\t\t\tconsole.log(` Strategy: ${strategy}`);\n\t\t}\n\t\tconsole.log('');\n\n\t\tif (scenarios.failed > 0) {\n\t\t\tconsole.log(' \\x1b[31mSome scenarios failed.\\x1b[0m\\n');\n\t\t} else if (steps.undefined > 0) {\n\t\t\tconsole.log(' \\x1b[33mSome steps are undefined.\\x1b[0m\\n');\n\t\t} else {\n\t\t\tconsole.log(' \\x1b[32mAll scenarios passed!\\x1b[0m\\n');\n\t\t}\n\n\t\t// Clean up all browsers\n\t\tfor (const b of browsers) {\n\t\t\tawait b.close().catch(() => {});\n\t\t}\n\n\t\tprocess.exit(scenarios.failed > 0 || steps.undefined > 0 ? 1 : 0);\n\t} catch (err) {\n\t\tfor (const b of browsers) {\n\t\t\tawait b.close().catch(() => {});\n\t\t}\n\t\tconsole.error(`BDD execution error: ${err instanceof Error ? err.message : String(err)}`);\n\t\tprocess.exit(1);\n\t}\n}\n\n/**\n * Split an array into N roughly-equal chunks.\n * Used for distributing feature files across parallel workers.\n */\nfunction splitIntoChunks<T>(items: T[], n: number): T[][] {\n\tconst chunks: T[][] = [];\n\tconst size = Math.ceil(items.length / n);\n\tfor (let i = 0; i < items.length; i += size) {\n\t\tchunks.push(items.slice(i, i + size));\n\t}\n\treturn chunks;\n}\n\n/**\n * Discover files matching a glob-like pattern within a directory.\n * Supports patterns like 'features/**\\/*.feature' or 'steps/**\\/*.{ts,js}'.\n */\nfunction discoverFiles(rootDir: string, pattern: string, extensions: string[]): string[] {\n\tconst files: string[] = [];\n\n\t// Extract the base directory from the pattern (e.g., 'features' from 'features/**/*.feature')\n\tconst baseParts = pattern.split('/');\n\tlet baseDir = rootDir;\n\tfor (const part of baseParts) {\n\t\tif (part.includes('*') || part.includes('{')) break;\n\t\tbaseDir = join(baseDir, part);\n\t}\n\n\tif (!existsSync(baseDir)) return files;\n\n\tconst walkDir = (dir: string): void => {\n\t\tconst skip = new Set(['node_modules', 'dist', '.browsecraft', '.git', 'coverage', '.turbo']);\n\t\tlet entries: string[];\n\t\ttry {\n\t\t\tentries = readdirSync(dir);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tif (skip.has(entry)) continue;\n\t\t\tconst fullPath = join(dir, entry);\n\t\t\tlet stat: ReturnType<typeof statSync>;\n\t\t\ttry {\n\t\t\t\tstat = statSync(fullPath);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (stat.isDirectory()) {\n\t\t\t\twalkDir(fullPath);\n\t\t\t} else if (stat.isFile()) {\n\t\t\t\tif (extensions.some((ext) => entry.endsWith(ext))) {\n\t\t\t\t\tfiles.push(fullPath);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\twalkDir(baseDir);\n\treturn files.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Init Command\n// ---------------------------------------------------------------------------\n\nasync function initProject() {\n\tconst cwd = process.cwd();\n\n\tconsole.log('\\n Browsecraft - Project Setup\\n');\n\n\t// Create config file\n\tconst configPath = join(cwd, 'browsecraft.config.ts');\n\tif (!existsSync(configPath)) {\n\t\twriteFileSync(\n\t\t\tconfigPath,\n\t\t\t`import { defineConfig } from 'browsecraft';\n\nexport default defineConfig({\n // Browser to use: 'chrome' | 'firefox' | 'edge'\n browser: 'chrome',\n\n // Run tests in headless mode\n headless: true,\n\n // Base URL for page.goto() calls\n // baseURL: 'http://localhost:3000',\n\n // Global timeout for actions (ms)\n timeout: 30_000,\n\n // Take screenshots on failure\n screenshot: 'on-failure',\n});\n`,\n\t\t);\n\t\tconsole.log(' Created browsecraft.config.ts');\n\t} else {\n\t\tconsole.log(' browsecraft.config.ts already exists, skipping');\n\t}\n\n\t// Create example test\n\tconst testsDir = join(cwd, 'tests');\n\tif (!existsSync(testsDir)) {\n\t\tmkdirSync(testsDir, { recursive: true });\n\t}\n\n\tconst exampleTest = join(testsDir, 'example.test.ts');\n\tif (!existsSync(exampleTest)) {\n\t\twriteFileSync(\n\t\t\texampleTest,\n\t\t\t`import { test, expect } from 'browsecraft';\n\ntest('homepage has correct title', async ({ page }) => {\n await page.goto('https://example.com');\n await expect(page).toHaveTitle('Example Domain');\n});\n\ntest('can navigate to more info', async ({ page }) => {\n await page.goto('https://example.com');\n await page.click('More information');\n await expect(page).toHaveURL(/iana\\\\.org/);\n});\n`,\n\t\t);\n\t\tconsole.log(' Created tests/example.test.ts');\n\t} else {\n\t\tconsole.log(' tests/example.test.ts already exists, skipping');\n\t}\n\n\t// Add .browsecraft to .gitignore\n\tconst gitignorePath = join(cwd, '.gitignore');\n\tif (existsSync(gitignorePath)) {\n\t\tconst content = await import('node:fs').then((fs) => fs.readFileSync(gitignorePath, 'utf-8'));\n\t\tif (!content.includes('.browsecraft')) {\n\t\t\twriteFileSync(gitignorePath, `${content.trimEnd()}\\n\\n# Browsecraft\\n.browsecraft/\\n`);\n\t\t\tconsole.log(' Updated .gitignore');\n\t\t}\n\t}\n\n\tconsole.log('\\n Setup complete! Run your first test:\\n');\n\tconsole.log(' npx browsecraft test\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Setup IDE — configures VS Code for Cucumber/Gherkin step discovery\n// ---------------------------------------------------------------------------\n\nasync function setupIde() {\n\tconst cwd = process.cwd();\n\n\tconsole.log('\\n Browsecraft — IDE Setup\\n');\n\tconsole.log(' Configuring VS Code for Cucumber/Gherkin step discovery...\\n');\n\n\t// Detect steps directory\n\tconst stepsDir = existsSync(join(cwd, 'steps'))\n\t\t? 'steps'\n\t\t: existsSync(join(cwd, 'step-definitions'))\n\t\t\t? 'step-definitions'\n\t\t\t: existsSync(join(cwd, 'step_definitions'))\n\t\t\t\t? 'step_definitions'\n\t\t\t\t: 'steps';\n\n\t// Detect features directory\n\tconst featuresDir = existsSync(join(cwd, 'features'))\n\t\t? 'features'\n\t\t: existsSync(join(cwd, 'test/features'))\n\t\t\t? 'test/features'\n\t\t\t: 'features';\n\n\t// Resolve the browsecraft-bdd glue path\n\tlet gluePath = 'node_modules/browsecraft-bdd/glue/steps.js';\n\ttry {\n\t\tconst { createRequire } = await import('node:module');\n\t\tconst userRequire = createRequire(join(cwd, 'package.json'));\n\t\tconst bddPkgPath = userRequire.resolve('browsecraft-bdd/package.json');\n\t\tconst bddDir = join(bddPkgPath, '..');\n\t\tconst relGlue = relative(cwd, join(bddDir, 'glue', 'steps.js')).replace(/\\\\/g, '/');\n\t\tif (existsSync(join(bddDir, 'glue', 'steps.js'))) {\n\t\t\tgluePath = relGlue;\n\t\t}\n\t} catch {\n\t\t// browsecraft-bdd not installed yet — use default path\n\t}\n\n\t// Create .vscode directory\n\tconst vscodeDir = join(cwd, '.vscode');\n\tif (!existsSync(vscodeDir)) {\n\t\tmkdirSync(vscodeDir, { recursive: true });\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/');\n\t}\n\n\t// Write or merge settings.json\n\tconst settingsPath = join(vscodeDir, 'settings.json');\n\tconst cucumberSettings: Record<string, unknown> = {\n\t\t'cucumberautocomplete.steps': [`${stepsDir}/**/*.ts`, `${stepsDir}/**/*.js`, gluePath],\n\t\t'cucumberautocomplete.strictGherkinCompletion': true,\n\t\t'cucumberautocomplete.strictGherkinValidation': true,\n\t\t'cucumber.glue': [`${stepsDir}/**/*.ts`, `${stepsDir}/**/*.js`, gluePath],\n\t\t'cucumber.features': [`${featuresDir}/**/*.feature`],\n\t};\n\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst existing = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n\t\t\tlet updated = false;\n\t\t\tfor (const [key, value] of Object.entries(cucumberSettings)) {\n\t\t\t\tif (!(key in existing)) {\n\t\t\t\t\texisting[key] = value;\n\t\t\t\t\tupdated = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updated) {\n\t\t\t\twriteFileSync(settingsPath, `${JSON.stringify(existing, null, 2)}\\n`, 'utf-8');\n\t\t\t\tconsole.log(' \\x1b[32mupdate\\x1b[0m .vscode/settings.json');\n\t\t\t} else {\n\t\t\t\tconsole.log(\n\t\t\t\t\t' \\x1b[33mskip\\x1b[0m .vscode/settings.json \\x1b[2m(already configured)\\x1b[0m',\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\twriteFileSync(settingsPath, `${JSON.stringify(cucumberSettings, null, 2)}\\n`, 'utf-8');\n\t\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/settings.json');\n\t\t}\n\t} else {\n\t\twriteFileSync(settingsPath, `${JSON.stringify(cucumberSettings, null, 2)}\\n`, 'utf-8');\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/settings.json');\n\t}\n\n\t// Write or merge extensions.json\n\tconst extensionsPath = join(vscodeDir, 'extensions.json');\n\tconst recommendedExtensions = [\n\t\t'alexkrechik.cucumberautocomplete',\n\t\t'CucumberOpen.cucumber-official',\n\t];\n\n\tif (existsSync(extensionsPath)) {\n\t\ttry {\n\t\t\tconst existing = JSON.parse(readFileSync(extensionsPath, 'utf-8'));\n\t\t\tconst recs: string[] = existing.recommendations ?? [];\n\t\t\tlet updated = false;\n\t\t\tfor (const ext of recommendedExtensions) {\n\t\t\t\tif (!recs.includes(ext)) {\n\t\t\t\t\trecs.push(ext);\n\t\t\t\t\tupdated = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updated) {\n\t\t\t\texisting.recommendations = recs;\n\t\t\t\twriteFileSync(extensionsPath, `${JSON.stringify(existing, null, 2)}\\n`, 'utf-8');\n\t\t\t\tconsole.log(' \\x1b[32mupdate\\x1b[0m .vscode/extensions.json');\n\t\t\t} else {\n\t\t\t\tconsole.log(\n\t\t\t\t\t' \\x1b[33mskip\\x1b[0m .vscode/extensions.json \\x1b[2m(already configured)\\x1b[0m',\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\twriteFileSync(\n\t\t\t\textensionsPath,\n\t\t\t\t`${JSON.stringify({ recommendations: recommendedExtensions }, null, 2)}\\n`,\n\t\t\t\t'utf-8',\n\t\t\t);\n\t\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/extensions.json');\n\t\t}\n\t} else {\n\t\twriteFileSync(\n\t\t\textensionsPath,\n\t\t\t`${JSON.stringify({ recommendations: recommendedExtensions }, null, 2)}\\n`,\n\t\t\t'utf-8',\n\t\t);\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/extensions.json');\n\t}\n\n\tconsole.log('\\n \\x1b[32mDone!\\x1b[0m IDE configured for Cucumber/Gherkin support.\\n');\n\tconsole.log(' What was set up:');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Cucumber extension discovers your custom steps');\n\tconsole.log(\" \\x1b[36m•\\x1b[0m Cucumber extension discovers BrowseCraft's 38 built-in steps\");\n\tconsole.log(' \\x1b[36m•\\x1b[0m Ctrl+Click navigation from .feature files to step definitions');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Autocomplete suggestions when writing features');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Recommended Cucumber extensions for VS Code');\n\tconsole.log();\n\tconsole.log(' If prompted, install the recommended extensions when VS Code asks.');\n\tconsole.log();\n}\n\n// ---------------------------------------------------------------------------\n// Config Loading\n// ---------------------------------------------------------------------------\n\nasync function loadConfig(): Promise<UserConfig | undefined> {\n\tconst cwd = process.cwd();\n\tconst candidates = [\n\t\t'browsecraft.config.ts',\n\t\t'browsecraft.config.js',\n\t\t'browsecraft.config.mjs',\n\t\t'browsecraft.config.mts',\n\t];\n\n\tfor (const name of candidates) {\n\t\tconst configPath = resolve(cwd, name);\n\t\tif (existsSync(configPath)) {\n\t\t\ttry {\n\t\t\t\t// For .ts files, ensure a TypeScript loader is registered\n\t\t\t\tif (name.endsWith('.ts') || name.endsWith('.mts')) {\n\t\t\t\t\tawait ensureTypeScriptLoader();\n\t\t\t\t}\n\t\t\t\tconst fileUrl = pathToFileURL(configPath).href;\n\t\t\t\tconst mod = await import(fileUrl);\n\t\t\t\treturn mod.default ?? mod;\n\t\t\t} catch {\n\t\t\t\t// Config file exists but couldn't be loaded -- continue with defaults\n\t\t\t\tconsole.warn(`Warning: Could not load ${name}. Using defaults.`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\n// ---------------------------------------------------------------------------\n// TypeScript Loader\n// ---------------------------------------------------------------------------\n\nlet tsLoaderRegistered = false;\n\n/**\n * Ensure a TypeScript loader is registered so that .ts test files can be imported.\n * Tries tsx first (fastest), then ts-node, then falls back to a helpful error.\n *\n * Resolution note: tsx is installed in the USER's project, not in browsecraft itself.\n * We must resolve it from the user's cwd using createRequire, not from our package.\n */\nasync function ensureTypeScriptLoader(): Promise<void> {\n\tif (tsLoaderRegistered) return;\n\n\t// Check if we're already running under a TS loader (e.g., `tsx`, `ts-node`, `bun`)\n\t// In that case, .ts imports already work\n\tconst execArgs = process.execArgv.join(' ');\n\tif (\n\t\texecArgs.includes('tsx') ||\n\t\texecArgs.includes('ts-node') ||\n\t\texecArgs.includes('loader') ||\n\t\tprocess.versions.bun // Bun handles TS natively\n\t) {\n\t\ttsLoaderRegistered = true;\n\t\treturn;\n\t}\n\n\t// Create a require function rooted at the user's cwd so we can find tsx/ts-node\n\t// installed in the user's project (not in our package)\n\tconst { createRequire } = await import('node:module');\n\tconst userRequire = createRequire(pathToFileURL(resolve(process.cwd(), 'package.json')));\n\n\t// Strategy 1: tsx 4.x — use the tsx/esm/api register() function\n\t// This is the modern approach that works with tsx 4.x+\n\ttry {\n\t\tconst tsxApiPath = userRequire.resolve('tsx/esm/api');\n\t\tconst { register } = await import(pathToFileURL(tsxApiPath).href);\n\t\tif (typeof register === 'function') {\n\t\t\tregister();\n\t\t\ttsLoaderRegistered = true;\n\t\t\treturn;\n\t\t}\n\t} catch {\n\t\t// tsx/esm/api not available, try next strategy\n\t}\n\n\t// Strategy 2: Older tsx/ts-node — use Node.js module.register()\n\t// Works with tsx <4.x and ts-node\n\tfor (const loader of ['tsx/esm', 'ts-node/esm']) {\n\t\ttry {\n\t\t\tconst { register } = await import('node:module');\n\t\t\tif (typeof register === 'function') {\n\t\t\t\t// Resolve from user's project root so the loader is found\n\t\t\t\tregister(loader, pathToFileURL(resolve(process.cwd(), '/')));\n\t\t\t\ttsLoaderRegistered = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Loader not available, try next\n\t\t}\n\t}\n\n\t// If neither tsx nor ts-node is available, give a helpful error\n\tconsole.error(\n\t\t'\\n Error: Cannot import TypeScript test files.\\n' +\n\t\t\t' Install tsx (recommended) or ts-node:\\n\\n' +\n\t\t\t' npm install -D tsx\\n\\n' +\n\t\t\t' Or run browsecraft with tsx:\\n\\n' +\n\t\t\t' npx tsx node_modules/.bin/browsecraft test\\n',\n\t);\n\tprocess.exit(1);\n}\n\n// ---------------------------------------------------------------------------\n// Flag parsing\n// ---------------------------------------------------------------------------\n\ninterface CLIFlags {\n\theaded?: boolean;\n\theadless?: boolean;\n\tbrowser?: string;\n\tworkers?: number;\n\ttimeout?: number;\n\tretries?: number;\n\tgrep?: string;\n\tbail?: boolean;\n\tdebug?: boolean;\n\tbdd?: boolean;\n\t/** BDD tag filter expression, e.g. \"@smoke and not @wip\" */\n\ttag?: string;\n\t/** Execution strategy: parallel, sequential, or matrix */\n\tstrategy?: string;\n\t/** BDD scenario name filter (alias for --grep in BDD mode) */\n\tscenario?: string;\n}\n\nfunction parseFlags(args: string[]): CLIFlags {\n\tconst flags: CLIFlags = {};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tswitch (arg) {\n\t\t\tcase '--headed':\n\t\t\t\tflags.headed = true;\n\t\t\t\tbreak;\n\t\t\tcase '--headless':\n\t\t\t\tflags.headless = true;\n\t\t\t\tbreak;\n\t\t\tcase '--debug':\n\t\t\t\tflags.debug = true;\n\t\t\t\tbreak;\n\t\t\tcase '--bdd':\n\t\t\t\tflags.bdd = true;\n\t\t\t\tbreak;\n\t\t\tcase '--bail':\n\t\t\t\tflags.bail = true;\n\t\t\t\tbreak;\n\t\t\tcase '--browser':\n\t\t\t\tflags.browser = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--workers':\n\t\t\t\tflags.workers = Number.parseInt(args[++i] ?? '1', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--timeout':\n\t\t\t\tflags.timeout = Number.parseInt(args[++i] ?? '30000', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--retries':\n\t\t\t\tflags.retries = Number.parseInt(args[++i] ?? '0', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--grep':\n\t\t\tcase '-g':\n\t\t\t\tflags.grep = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--tag':\n\t\t\tcase '--tags':\n\t\t\t\tflags.tag = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--strategy':\n\t\t\t\tflags.strategy = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--scenario':\n\t\t\t\tflags.scenario = args[++i];\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn flags;\n}\n\n// ---------------------------------------------------------------------------\n// Help\n// ---------------------------------------------------------------------------\n\nfunction printHelp() {\n\tconsole.log(`\n browsecraft v${VERSION} -- AI-native browser testing\n\n Usage:\n browsecraft test [files...] [options]\n browsecraft test --bdd [features...] [options]\n browsecraft init\n browsecraft setup-ide\n\n Commands:\n test Run browser tests\n test --bdd Run BDD feature files (Gherkin)\n init Create a new project with example config and test\n setup-ide Configure VS Code for Cucumber step discovery\n\n Options:\n --bdd Run BDD feature files instead of programmatic tests\n --browser <names> Browser(s) to use: chrome,firefox,edge (comma-separated)\n --headed Run in headed mode (show the browser)\n --headless Run in headless mode (default)\n --workers <n> Parallel workers — features run concurrently (default: 1)\n --timeout <ms> Global timeout in milliseconds (default: 30000)\n --retries <n> Retry failed tests n times (default: 0)\n --grep <pattern> Only run tests/scenarios matching pattern\n --scenario <name> Run only scenarios whose name contains <name>\n --tag <expr> BDD tag filter: \"@smoke\", \"@smoke and not @wip\"\n --strategy <s> Multi-browser strategy: parallel, sequential, matrix\n --bail Stop after first failure\n --debug Enable verbose debug logging\n -h, --help Show this help message\n -v, --version Show version\n\n BDD Examples:\n browsecraft test --bdd # All features, 1 browser\n browsecraft test --bdd features/login.feature # Single feature\n browsecraft test --bdd features/login.feature:15 # Specific scenario by line\n browsecraft test --bdd --scenario \"Valid login\" # Specific scenario by name\n browsecraft test --bdd --tag \"@smoke\" # Tag filter\n browsecraft test --bdd --grep \"checkout\" # Name filter\n browsecraft test --bdd --workers 4 # 4 features in parallel\n browsecraft test --bdd --browser chrome,firefox # Multi-browser\n browsecraft test --bdd --browser chrome,firefox,edge --strategy matrix\n browsecraft test --bdd --headed --browser firefox # Headed mode\n\n Programmatic Examples:\n browsecraft test # Run all tests\n browsecraft test tests/login.test.ts # Run specific file\n browsecraft test --headed --browser firefox\n browsecraft test --grep \"login\" --bail\n browsecraft setup-ide # Auto-configure IDE for BDD\n`);\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\nmain().catch((err) => {\n\tconsole.error('Fatal error:', err.message);\n\tprocess.exit(1);\n});\n"]}
1
+ {"version":3,"sources":["../src/cli.ts"],"names":["resolveConfig","TestRunner","testRegistry","pathToFileURL","Browser","runTest","resolve","existsSync","readFileSync","relative","allFeatures","join","readdirSync","statSync","writeFileSync","mkdirSync"],"mappings":"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","file":"cli.cjs","sourcesContent":["#!/usr/bin/env node\n// ============================================================================\n// Browsecraft - CLI\n// The command-line interface for running tests and initializing projects.\n//\n// npx browsecraft test # Run all tests\n// npx browsecraft test login.test.ts # Run specific file\n// npx browsecraft bdd # Run BDD feature files\n// npx browsecraft bdd login.feature # Run specific feature\n// npx browsecraft init # Scaffold a new project\n// npx browsecraft --help # Show help\n// ============================================================================\n\nimport { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';\nimport { join, relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { BrowserName } from 'browsecraft-bidi';\nimport { type RunnableTest, type RunnerOptions, TestRunner } from 'browsecraft-runner';\nimport { Browser } from './browser.js';\nimport { type UserConfig, resolveConfig } from './config.js';\nimport { type TestCase, runAfterAllHooks, runTest, testRegistry } from './test.js';\n\nconst VERSION = '0.3.0';\n\nasync function main() {\n\tconst args = process.argv.slice(2);\n\n\tif (args.length === 0 || args.includes('--help') || args.includes('-h')) {\n\t\tprintHelp();\n\t\treturn;\n\t}\n\n\tif (args.includes('--version') || args.includes('-v')) {\n\t\tconsole.log(`browsecraft v${VERSION}`);\n\t\treturn;\n\t}\n\n\tconst command = args[0];\n\n\tswitch (command) {\n\t\tcase 'test':\n\t\t\tawait runTests(args.slice(1));\n\t\t\tbreak;\n\t\tcase 'bdd':\n\t\t\t// \"browsecraft bdd\" is shorthand for \"browsecraft test --bdd\"\n\t\t\tawait runTests(['--bdd', ...args.slice(1)]);\n\t\t\tbreak;\n\t\tcase 'init':\n\t\t\tawait initProject();\n\t\t\tbreak;\n\t\tcase 'setup-ide':\n\t\t\tawait setupIde();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t// If no command, infer from file extension\n\t\t\tif (command?.endsWith('.feature')) {\n\t\t\t\tawait runTests(['--bdd', ...args]);\n\t\t\t} else if (command?.endsWith('.ts') || command?.endsWith('.js')) {\n\t\t\t\tawait runTests(args);\n\t\t\t} else {\n\t\t\t\tconsole.error(`Unknown command: ${command}`);\n\t\t\t\tconsole.error('Run \"browsecraft --help\" for usage information.');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Test Command\n// ---------------------------------------------------------------------------\n\nasync function runTests(args: string[]) {\n\t// Parse CLI flags\n\tconst flags = parseFlags(args);\n\tconst filePatterns = args.filter((a) => !a.startsWith('--'));\n\n\t// Load config file if it exists\n\tconst userConfig = await loadConfig();\n\tconst config = resolveConfig(userConfig);\n\n\t// Apply CLI overrides\n\tif (flags.headed || flags.headless === false) {\n\t\tconfig.headless = false;\n\t}\n\tif (flags.browser) {\n\t\tconfig.browser = flags.browser as BrowserName;\n\t}\n\tif (flags.workers !== undefined) {\n\t\tconfig.workers = flags.workers;\n\t}\n\tif (flags.timeout !== undefined) {\n\t\tconfig.timeout = flags.timeout;\n\t}\n\tif (flags.retries !== undefined) {\n\t\tconfig.retries = flags.retries;\n\t}\n\tif (flags.debug) {\n\t\tconfig.debug = true;\n\t}\n\n\t// BDD mode: run .feature files with step definitions\n\tif (flags.bdd) {\n\t\tawait runBddTests(config, userConfig, flags, filePatterns);\n\t\treturn;\n\t}\n\n\t// Set up runner options\n\tconst runnerOptions: RunnerOptions = {\n\t\tconfig,\n\t\tfiles: filePatterns.length > 0 ? filePatterns : undefined,\n\t\tgrep: flags.grep,\n\t\tbail: flags.bail,\n\t};\n\n\t// Run tests\n\tconst runner = new TestRunner(runnerOptions);\n\n\t// loadFile callback: imports the test file and returns registered tests\n\tconst loadFile = async (file: string): Promise<RunnableTest[]> => {\n\t\tconst startIdx = testRegistry.length;\n\n\t\t// For TypeScript files, register a TypeScript loader if available\n\t\tif (file.endsWith('.ts') || file.endsWith('.mts')) {\n\t\t\tawait ensureTypeScriptLoader();\n\t\t}\n\n\t\tconst fileUrl = pathToFileURL(file).href;\n\t\tawait import(fileUrl);\n\t\treturn testRegistry.slice(startIdx).map((tc) => ({\n\t\t\ttitle: tc.title,\n\t\t\tsuitePath: tc.suitePath,\n\t\t\tskip: tc.skip,\n\t\t\tonly: tc.only,\n\t\t\toptions: tc.options,\n\t\t\tfn: tc.fn as (fixtures: unknown) => Promise<void>,\n\t\t}));\n\t};\n\n\t// Launch a shared browser for all tests\n\tlet sharedBrowser: Browser | undefined;\n\n\ttry {\n\t\tsharedBrowser = await Browser.launch({\n\t\t\tbrowser: config.browser,\n\t\t\theadless: config.headless,\n\t\t\texecutablePath: config.executablePath,\n\t\t\tdebug: config.debug,\n\t\t\ttimeout: config.timeout,\n\t\t});\n\t} catch (err) {\n\t\tconsole.error(`Failed to launch browser: ${err instanceof Error ? err.message : String(err)}`);\n\t\tprocess.exit(1);\n\t}\n\n\t// executeTest callback: runs a single test with fixture setup/teardown\n\tconst executeTest = async (test: RunnableTest) => {\n\t\treturn runTest(test as unknown as TestCase, sharedBrowser);\n\t};\n\n\ttry {\n\t\tconst exitCode = await runner.run(loadFile, executeTest);\n\t\tawait sharedBrowser.close().catch(() => {});\n\t\tprocess.exit(exitCode);\n\t} catch (err) {\n\t\tawait sharedBrowser?.close().catch(() => {});\n\t\tthrow err;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// BDD Command — runs .feature files with step definitions\n//\n// Supports:\n// - Single / multiple feature files: browsecraft test --bdd login.feature\n// - Tag filtering: --tag \"@smoke and not @wip\"\n// - Name filtering: --grep \"login\"\n// - Multi-browser: --browser chrome,firefox\n// - Parallel: --workers 4\n// - Strategy: --strategy parallel|sequential|matrix\n// ---------------------------------------------------------------------------\n\ntype BddModule = typeof import('browsecraft-bdd');\n\nasync function runBddTests(\n\tconfig: ReturnType<typeof resolveConfig>,\n\tuserConfig?: UserConfig,\n\tflags?: CLIFlags,\n\tfilePatterns?: string[],\n): Promise<void> {\n\tconst bddModule = (await import('browsecraft-bdd')) as BddModule;\n\tconst { parseGherkin, BddExecutor, registerBuiltInSteps, After, computeSummary } = bddModule;\n\tconst cwd = process.cwd();\n\n\t// ── Resolve options from config + CLI flags ────────────────────────\n\tconst bddConfig = userConfig?.bdd ?? {};\n\tconst featuresPattern = bddConfig.features ?? 'features/**/*.feature';\n\tconst stepsPattern = bddConfig.steps ?? 'steps/**/*.{ts,js,mts,mjs}';\n\tconst useBuiltInSteps = bddConfig.builtInSteps !== false;\n\n\t// Browsers: --browser chrome,firefox or config.browsers or [config.browser]\n\tconst browserNames: string[] = flags?.browser\n\t\t? flags.browser.split(',').map((b) => b.trim())\n\t\t: (config.browsers ?? [config.browser]);\n\n\t// Workers per browser (for parallel feature execution)\n\tconst workers = flags?.workers ?? (browserNames.length > 1 ? 1 : 1);\n\n\t// Strategy: --strategy or config.strategy\n\tconst strategy = (flags?.strategy ?? config.strategy ?? 'sequential') as\n\t\t| 'parallel'\n\t\t| 'sequential'\n\t\t| 'matrix';\n\n\t// Tag filter: --tag or bddConfig.tagFilter\n\tconst tagFilter = flags?.tag ?? bddConfig.tagFilter;\n\n\t// Grep: --grep or --scenario or bddConfig.grep\n\tconst grepPattern = flags?.scenario ?? flags?.grep ?? bddConfig.grep;\n\n\t// Fail fast: --bail\n\tconst failFast = flags?.bail ?? false;\n\n\t// ── Step 1: Discover .feature files ────────────────────────────────\n\t// Parse feature:line syntax (e.g. features/login.feature:15)\n\tconst targetLines = new Map<string, number[]>(); // file → line numbers\n\tlet featureFiles: string[];\n\n\tif (filePatterns && filePatterns.length > 0) {\n\t\t// Explicit feature files from CLI positional args\n\t\tconst resolvedPaths: string[] = [];\n\t\tfor (const pattern of filePatterns) {\n\t\t\tconst [filePart, linePart] = pattern.split(':');\n\t\t\tconst absPath = resolve(cwd, filePart!);\n\t\t\tif (!existsSync(absPath)) continue;\n\n\t\t\tif (!resolvedPaths.includes(absPath)) {\n\t\t\t\tresolvedPaths.push(absPath);\n\t\t\t}\n\t\t\tif (linePart) {\n\t\t\t\tconst lineNum = Number.parseInt(linePart, 10);\n\t\t\t\tif (!Number.isNaN(lineNum)) {\n\t\t\t\t\tconst existing = targetLines.get(absPath) ?? [];\n\t\t\t\t\texisting.push(lineNum);\n\t\t\t\t\ttargetLines.set(absPath, existing);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfeatureFiles = resolvedPaths;\n\t\tif (featureFiles.length === 0) {\n\t\t\tconsole.error('\\n No matching feature files found.\\n');\n\t\t\tprocess.exit(1);\n\t\t}\n\t} else {\n\t\tfeatureFiles = discoverFiles(cwd, featuresPattern, ['.feature']);\n\t}\n\n\tif (featureFiles.length === 0) {\n\t\tconsole.log('\\n No .feature files found.\\n');\n\t\tconsole.log(` Feature pattern: ${featuresPattern}`);\n\t\tconsole.log(' Create features/*.feature files or adjust bdd.features in your config.\\n');\n\t\tprocess.exit(0);\n\t}\n\n\t// ── Step 2: Register steps ─────────────────────────────────────────\n\tif (useBuiltInSteps) {\n\t\tregisterBuiltInSteps();\n\t}\n\n\tconst stepFiles = discoverFiles(cwd, stepsPattern, ['.ts', '.js', '.mts', '.mjs']);\n\tfor (const stepFile of stepFiles) {\n\t\tif (stepFile.endsWith('.ts') || stepFile.endsWith('.mts')) {\n\t\t\tawait ensureTypeScriptLoader();\n\t\t}\n\t\tconst fileUrl = pathToFileURL(stepFile).href;\n\t\tawait import(fileUrl);\n\t}\n\n\t// Cleanup hook for browser contexts\n\tAfter(async ({ world }) => {\n\t\tconst w = world as unknown as Record<string, { close(): Promise<unknown> } | undefined>;\n\t\tif (w?._context) {\n\t\t\tawait w._context.close().catch(() => {});\n\t\t}\n\t});\n\n\t// ── Step 3: Parse .feature files ───────────────────────────────────\n\tconst documents = featureFiles.map((file) => {\n\t\tconst source = readFileSync(file, 'utf-8');\n\t\treturn parseGherkin(source, relative(cwd, file));\n\t});\n\n\t// Build a scenario filter for line-number targeting\n\tconst lineFilter =\n\t\ttargetLines.size > 0\n\t\t\t? (scenario: { line: number; name: string }, _tags: string[], uri?: string) => {\n\t\t\t\t\tfor (const [file, lines] of targetLines) {\n\t\t\t\t\t\tconst relPath = relative(cwd, file);\n\t\t\t\t\t\tif (uri === relPath || uri === file) {\n\t\t\t\t\t\t\treturn lines.includes(scenario.line);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true; // no line constraint for this file\n\t\t\t\t}\n\t\t\t: undefined;\n\n\t// ── Step 4: Determine execution plan ───────────────────────────────\n\tconst isMultiBrowser = browserNames.length > 1;\n\tconst isParallel = workers > 1;\n\n\t// Header\n\tconst parts: string[] = [\n\t\t`${featureFiles.length} feature file${featureFiles.length > 1 ? 's' : ''}`,\n\t];\n\tif (isMultiBrowser) parts.push(`on ${browserNames.join(', ')}`);\n\tif (isParallel) parts.push(`(${workers} workers)`);\n\tif (tagFilter) parts.push(`[tags: ${tagFilter}]`);\n\tif (grepPattern) parts.push(`[grep: ${grepPattern}]`);\n\tif (targetLines.size > 0) {\n\t\tconst lineDescs = [...targetLines.entries()].map(\n\t\t\t([f, ls]) => `${relative(cwd, f)}:${ls.join(',')}`,\n\t\t);\n\t\tparts.push(`[lines: ${lineDescs.join(' ')}]`);\n\t}\n\n\tconsole.log(`\\n Browsecraft BDD - Running ${parts.join(' ')}\\n`);\n\n\tif (isMultiBrowser) {\n\t\tconsole.log(` Strategy: ${strategy}`);\n\t\tconsole.log(\n\t\t\t` Browsers: ${browserNames.map((b) => b.charAt(0).toUpperCase() + b.slice(1)).join(', ')}`,\n\t\t);\n\t\tconsole.log('');\n\t}\n\n\t// ── Step 5: Execute ────────────────────────────────────────────────\n\ttype FeatureResultType = Awaited<\n\t\tReturnType<InstanceType<typeof BddExecutor>['run']>\n\t>['features'][number];\n\n\t/**\n\t * Run a set of documents on a specific browser.\n\t * Returns the feature results and the launched browser instance.\n\t */\n\tconst runOnBrowser = async (\n\t\tbrowserName: string,\n\t\tdocs: ReturnType<typeof parseGherkin>[],\n\t\tprefix: string,\n\t): Promise<{ features: FeatureResultType[]; duration: number; browser: Browser }> => {\n\t\tconst browser = await Browser.launch({\n\t\t\tbrowser: browserName as BrowserName,\n\t\t\theadless: config.headless,\n\t\t\texecutablePath: config.executablePath,\n\t\t\tdebug: config.debug,\n\t\t\ttimeout: config.timeout,\n\t\t});\n\n\t\tconst createExecutor = (docSubset: ReturnType<typeof parseGherkin>[]) =>\n\t\t\tnew BddExecutor({\n\t\t\t\tstepTimeout: config.timeout,\n\t\t\t\ttagFilter: tagFilter ?? undefined,\n\t\t\t\tgrep: grepPattern ?? undefined,\n\t\t\t\tscenarioFilter: lineFilter ?? undefined,\n\t\t\t\tfailFast,\n\t\t\t\tworldFactory: async () => {\n\t\t\t\t\tconst context = await browser.newContext();\n\t\t\t\t\tconst page = await context.newPage();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpage,\n\t\t\t\t\t\tbrowser,\n\t\t\t\t\t\tctx: {},\n\t\t\t\t\t\tattach: () => {},\n\t\t\t\t\t\tlog: (msg: string) => console.log(` ${prefix}${msg}`),\n\t\t\t\t\t\t_context: context,\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\tonFeatureStart: (feature) => {\n\t\t\t\t\tconsole.log(`\\n ${prefix}Feature: ${feature.name}`);\n\t\t\t\t},\n\t\t\t\tonScenarioStart: (scenario) => {\n\t\t\t\t\tconsole.log(` ${prefix}Scenario: ${scenario.name}`);\n\t\t\t\t},\n\t\t\t\tonStepEnd: (result) => {\n\t\t\t\t\tconst icon =\n\t\t\t\t\t\tresult.status === 'passed'\n\t\t\t\t\t\t\t? '\\x1b[32m+\\x1b[0m'\n\t\t\t\t\t\t\t: result.status === 'failed'\n\t\t\t\t\t\t\t\t? '\\x1b[31mx\\x1b[0m'\n\t\t\t\t\t\t\t\t: result.status === 'undefined'\n\t\t\t\t\t\t\t\t\t? '\\x1b[33m?\\x1b[0m'\n\t\t\t\t\t\t\t\t\t: result.status === 'pending'\n\t\t\t\t\t\t\t\t\t\t? '\\x1b[33m-\\x1b[0m'\n\t\t\t\t\t\t\t\t\t\t: '\\x1b[90m-\\x1b[0m';\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t` ${prefix}${icon} ${result.keyword.trim()} ${result.text} (${result.duration}ms)`,\n\t\t\t\t\t);\n\t\t\t\t\tif (result.status === 'failed' && result.error) {\n\t\t\t\t\t\tconsole.log(` ${prefix}${result.error.message}`);\n\t\t\t\t\t}\n\t\t\t\t\tif (result.status === 'undefined') {\n\t\t\t\t\t\tconsole.log(` ${prefix}Step not defined. Add it to your step definitions.`);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonScenarioEnd: (result) => {\n\t\t\t\t\t// Print hookError when worldFactory or hooks fail (0 steps executed)\n\t\t\t\t\tif (result.hookError) {\n\t\t\t\t\t\tconsole.log(` ${prefix}\\x1b[31m✗ ${result.hookError.message}\\x1b[0m`);\n\t\t\t\t\t}\n\t\t\t\t\t// Show scenario-level failure summary when steps ran but some failed\n\t\t\t\t\tif (result.status === 'failed' && !result.hookError && result.steps.length === 0) {\n\t\t\t\t\t\tconsole.log(` ${prefix}\\x1b[31m✗ Scenario failed with no steps executed\\x1b[0m`);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\n\t\tlet allFeatures: FeatureResultType[] = [];\n\t\tconst start = Date.now();\n\n\t\tif (workers > 1 && docs.length > 1) {\n\t\t\t// Parallel: split documents into worker chunks\n\t\t\tconst chunks = splitIntoChunks(docs, workers);\n\t\t\tconst results = await Promise.all(\n\t\t\t\tchunks.map((chunk) => {\n\t\t\t\t\tconst exec = createExecutor(chunk);\n\t\t\t\t\treturn exec.run(chunk);\n\t\t\t\t}),\n\t\t\t);\n\t\t\tallFeatures = results.flatMap((r) => r.features);\n\t\t} else {\n\t\t\t// Sequential: single executor\n\t\t\tconst exec = createExecutor(docs);\n\t\t\tconst result = await exec.run(docs);\n\t\t\tallFeatures = result.features;\n\t\t}\n\n\t\treturn { features: allFeatures, duration: Date.now() - start, browser };\n\t};\n\n\t// ── Execute according to strategy ──────────────────────────────────\n\tconst browsers: Browser[] = [];\n\tlet allFeatures: FeatureResultType[] = [];\n\tlet totalDuration = 0;\n\tconst perBrowserResults: Array<{\n\t\tbrowserName: string;\n\t\tfeatures: FeatureResultType[];\n\t\tduration: number;\n\t}> = [];\n\n\ttry {\n\t\tif (!isMultiBrowser) {\n\t\t\t// Single browser — simple path\n\t\t\tconst { features, duration, browser } = await runOnBrowser(browserNames[0]!, documents, '');\n\t\t\tbrowsers.push(browser);\n\t\t\tallFeatures = features;\n\t\t\ttotalDuration = duration;\n\t\t\tperBrowserResults.push({ browserName: browserNames[0]!, features, duration });\n\t\t} else if (strategy === 'sequential') {\n\t\t\t// Sequential: one browser at a time, each runs all features\n\t\t\tfor (const bName of browserNames) {\n\t\t\t\tconst prefix = `\\x1b[36m[${bName}]\\x1b[0m `;\n\t\t\t\tconst { features, duration, browser } = await runOnBrowser(bName, documents, prefix);\n\t\t\t\tbrowsers.push(browser);\n\t\t\t\tallFeatures.push(...features);\n\t\t\t\ttotalDuration += duration;\n\t\t\t\tperBrowserResults.push({ browserName: bName, features, duration });\n\t\t\t}\n\t\t} else {\n\t\t\t// Parallel or Matrix: all browsers simultaneously\n\t\t\t// (matrix = every feature on every browser; parallel = same as matrix for distinct browsers)\n\t\t\tconst results = await Promise.all(\n\t\t\t\tbrowserNames.map((bName) => {\n\t\t\t\t\tconst prefix = `\\x1b[36m[${bName}]\\x1b[0m `;\n\t\t\t\t\treturn runOnBrowser(bName, documents, prefix);\n\t\t\t\t}),\n\t\t\t);\n\t\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\t\tconst r = results[i]!;\n\t\t\t\tbrowsers.push(r.browser);\n\t\t\t\tallFeatures.push(...r.features);\n\t\t\t\tperBrowserResults.push({\n\t\t\t\t\tbrowserName: browserNames[i]!,\n\t\t\t\t\tfeatures: r.features,\n\t\t\t\t\tduration: r.duration,\n\t\t\t\t});\n\t\t\t}\n\t\t\ttotalDuration = Math.max(...results.map((r) => r.duration));\n\t\t}\n\n\t\t// ── Print summary ──────────────────────────────────────────────\n\t\tconst summary = computeSummary(allFeatures);\n\t\tconsole.log('\\n ─────────────────────────────────────');\n\n\t\t// Per-browser breakdown for multi-browser runs\n\t\tif (isMultiBrowser) {\n\t\t\tfor (const br of perBrowserResults) {\n\t\t\t\tconst brSummary = computeSummary(br.features);\n\t\t\t\tconst brLabel = br.browserName.charAt(0).toUpperCase() + br.browserName.slice(1);\n\t\t\t\tconst brParts: string[] = [];\n\t\t\t\tif (brSummary.scenarios.passed > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[32m${brSummary.scenarios.passed} passed\\x1b[0m`);\n\t\t\t\tif (brSummary.scenarios.failed > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[31m${brSummary.scenarios.failed} failed\\x1b[0m`);\n\t\t\t\tif (brSummary.scenarios.skipped > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[33m${brSummary.scenarios.skipped} skipped\\x1b[0m`);\n\t\t\t\tconsole.log(\n\t\t\t\t\t` ${brLabel.padEnd(10)} ${brParts.join(', ')} (${brSummary.scenarios.total} scenarios) ${br.duration < 1000 ? `${br.duration}ms` : `${(br.duration / 1000).toFixed(1)}s`}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconsole.log(' ─────────────────────────────────────');\n\t\t}\n\n\t\tconst { scenarios, steps } = summary;\n\n\t\tconst scenarioParts: string[] = [];\n\t\tif (scenarios.passed > 0) scenarioParts.push(`\\x1b[32m${scenarios.passed} passed\\x1b[0m`);\n\t\tif (scenarios.failed > 0) scenarioParts.push(`\\x1b[31m${scenarios.failed} failed\\x1b[0m`);\n\t\tif (scenarios.skipped > 0) scenarioParts.push(`\\x1b[33m${scenarios.skipped} skipped\\x1b[0m`);\n\t\tif (scenarios.pending > 0) scenarioParts.push(`\\x1b[33m${scenarios.pending} pending\\x1b[0m`);\n\n\t\tconst stepParts: string[] = [];\n\t\tif (steps.passed > 0) stepParts.push(`\\x1b[32m${steps.passed} passed\\x1b[0m`);\n\t\tif (steps.failed > 0) stepParts.push(`\\x1b[31m${steps.failed} failed\\x1b[0m`);\n\t\tif (steps.undefined > 0) stepParts.push(`\\x1b[33m${steps.undefined} undefined\\x1b[0m`);\n\t\tif (steps.skipped > 0) stepParts.push(`\\x1b[90m${steps.skipped} skipped\\x1b[0m`);\n\n\t\tconsole.log(` Scenarios: ${scenarioParts.join(', ')} (${scenarios.total} total)`);\n\t\tconsole.log(` Steps: ${stepParts.join(', ')} (${steps.total} total)`);\n\t\tconsole.log(\n\t\t\t` Time: ${totalDuration < 1000 ? `${totalDuration}ms` : `${(totalDuration / 1000).toFixed(1)}s`}`,\n\t\t);\n\t\tif (isMultiBrowser) {\n\t\t\tconsole.log(` Strategy: ${strategy}`);\n\t\t}\n\t\tconsole.log('');\n\n\t\tif (scenarios.failed > 0) {\n\t\t\t// List failed scenarios with error details\n\t\t\tconsole.log(' \\x1b[31mFailed scenarios:\\x1b[0m');\n\t\t\tfor (const feat of allFeatures) {\n\t\t\t\tfor (const scen of feat.scenarios) {\n\t\t\t\t\tif (scen.status !== 'failed') continue;\n\t\t\t\t\tconsole.log(` \\x1b[31m✗\\x1b[0m ${feat.name} → ${scen.name}`);\n\t\t\t\t\tif (scen.hookError) {\n\t\t\t\t\t\tconsole.log(` Error: ${scen.hookError.message}`);\n\t\t\t\t\t}\n\t\t\t\t\tfor (const st of scen.steps) {\n\t\t\t\t\t\tif (st.status === 'failed' && st.error) {\n\t\t\t\t\t\t\tconsole.log(` ${st.keyword.trim()} ${st.text}: ${st.error.message}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (st.status === 'undefined') {\n\t\t\t\t\t\t\tconsole.log(` ${st.keyword.trim()} ${st.text}: \\x1b[33mStep not defined\\x1b[0m`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tconsole.log('');\n\t\t} else if (steps.undefined > 0) {\n\t\t\tconsole.log(' \\x1b[33mSome steps are undefined.\\x1b[0m\\n');\n\t\t} else {\n\t\t\tconsole.log(' \\x1b[32mAll scenarios passed!\\x1b[0m\\n');\n\t\t}\n\n\t\t// Clean up all browsers\n\t\tfor (const b of browsers) {\n\t\t\tawait b.close().catch(() => {});\n\t\t}\n\n\t\tprocess.exit(scenarios.failed > 0 || steps.undefined > 0 ? 1 : 0);\n\t} catch (err) {\n\t\tfor (const b of browsers) {\n\t\t\tawait b.close().catch(() => {});\n\t\t}\n\t\tconsole.error(`BDD execution error: ${err instanceof Error ? err.message : String(err)}`);\n\t\tprocess.exit(1);\n\t}\n}\n\n/**\n * Split an array into N roughly-equal chunks.\n * Used for distributing feature files across parallel workers.\n */\nfunction splitIntoChunks<T>(items: T[], n: number): T[][] {\n\tconst chunks: T[][] = [];\n\tconst size = Math.ceil(items.length / n);\n\tfor (let i = 0; i < items.length; i += size) {\n\t\tchunks.push(items.slice(i, i + size));\n\t}\n\treturn chunks;\n}\n\n/**\n * Discover files matching a glob-like pattern within a directory.\n * Supports patterns like 'features/**\\/*.feature' or 'steps/**\\/*.{ts,js}'.\n */\nfunction discoverFiles(rootDir: string, pattern: string, extensions: string[]): string[] {\n\tconst files: string[] = [];\n\n\t// Extract the base directory from the pattern (e.g., 'features' from 'features/**/*.feature')\n\tconst baseParts = pattern.split('/');\n\tlet baseDir = rootDir;\n\tfor (const part of baseParts) {\n\t\tif (part.includes('*') || part.includes('{')) break;\n\t\tbaseDir = join(baseDir, part);\n\t}\n\n\tif (!existsSync(baseDir)) return files;\n\n\tconst walkDir = (dir: string): void => {\n\t\tconst skip = new Set(['node_modules', 'dist', '.browsecraft', '.git', 'coverage', '.turbo']);\n\t\tlet entries: string[];\n\t\ttry {\n\t\t\tentries = readdirSync(dir);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tif (skip.has(entry)) continue;\n\t\t\tconst fullPath = join(dir, entry);\n\t\t\tlet stat: ReturnType<typeof statSync>;\n\t\t\ttry {\n\t\t\t\tstat = statSync(fullPath);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (stat.isDirectory()) {\n\t\t\t\twalkDir(fullPath);\n\t\t\t} else if (stat.isFile()) {\n\t\t\t\tif (extensions.some((ext) => entry.endsWith(ext))) {\n\t\t\t\t\tfiles.push(fullPath);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\twalkDir(baseDir);\n\treturn files.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Init Command\n// ---------------------------------------------------------------------------\n\nasync function initProject() {\n\tconst cwd = process.cwd();\n\n\tconsole.log('\\n Browsecraft - Project Setup\\n');\n\n\t// Create config file\n\tconst configPath = join(cwd, 'browsecraft.config.ts');\n\tif (!existsSync(configPath)) {\n\t\twriteFileSync(\n\t\t\tconfigPath,\n\t\t\t`import { defineConfig } from 'browsecraft';\n\nexport default defineConfig({\n // Browser to use: 'chrome' | 'firefox' | 'edge'\n browser: 'chrome',\n\n // Run tests in headless mode\n headless: true,\n\n // Base URL for page.goto() calls\n // baseURL: 'http://localhost:3000',\n\n // Global timeout for actions (ms)\n timeout: 30_000,\n\n // Take screenshots on failure\n screenshot: 'on-failure',\n});\n`,\n\t\t);\n\t\tconsole.log(' Created browsecraft.config.ts');\n\t} else {\n\t\tconsole.log(' browsecraft.config.ts already exists, skipping');\n\t}\n\n\t// Create example test\n\tconst testsDir = join(cwd, 'tests');\n\tif (!existsSync(testsDir)) {\n\t\tmkdirSync(testsDir, { recursive: true });\n\t}\n\n\tconst exampleTest = join(testsDir, 'example.test.ts');\n\tif (!existsSync(exampleTest)) {\n\t\twriteFileSync(\n\t\t\texampleTest,\n\t\t\t`import { test, expect } from 'browsecraft';\n\ntest('homepage has correct title', async ({ page }) => {\n await page.goto('https://example.com');\n await expect(page).toHaveTitle('Example Domain');\n});\n\ntest('can navigate to more info', async ({ page }) => {\n await page.goto('https://example.com');\n await page.click('More information');\n await expect(page).toHaveURL(/iana\\\\.org/);\n});\n`,\n\t\t);\n\t\tconsole.log(' Created tests/example.test.ts');\n\t} else {\n\t\tconsole.log(' tests/example.test.ts already exists, skipping');\n\t}\n\n\t// Add .browsecraft to .gitignore\n\tconst gitignorePath = join(cwd, '.gitignore');\n\tif (existsSync(gitignorePath)) {\n\t\tconst content = await import('node:fs').then((fs) => fs.readFileSync(gitignorePath, 'utf-8'));\n\t\tif (!content.includes('.browsecraft')) {\n\t\t\twriteFileSync(gitignorePath, `${content.trimEnd()}\\n\\n# Browsecraft\\n.browsecraft/\\n`);\n\t\t\tconsole.log(' Updated .gitignore');\n\t\t}\n\t}\n\n\tconsole.log('\\n Setup complete! Run your first test:\\n');\n\tconsole.log(' npx browsecraft test\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Setup IDE — configures VS Code for Cucumber/Gherkin step discovery\n// ---------------------------------------------------------------------------\n\nasync function setupIde() {\n\tconst cwd = process.cwd();\n\n\tconsole.log('\\n Browsecraft — IDE Setup\\n');\n\tconsole.log(' Configuring VS Code for Cucumber/Gherkin step discovery...\\n');\n\n\t// Detect steps directory\n\tconst stepsDir = existsSync(join(cwd, 'steps'))\n\t\t? 'steps'\n\t\t: existsSync(join(cwd, 'step-definitions'))\n\t\t\t? 'step-definitions'\n\t\t\t: existsSync(join(cwd, 'step_definitions'))\n\t\t\t\t? 'step_definitions'\n\t\t\t\t: 'steps';\n\n\t// Detect features directory\n\tconst featuresDir = existsSync(join(cwd, 'features'))\n\t\t? 'features'\n\t\t: existsSync(join(cwd, 'test/features'))\n\t\t\t? 'test/features'\n\t\t\t: 'features';\n\n\t// Resolve the browsecraft-bdd glue path\n\tlet gluePath = 'node_modules/browsecraft-bdd/glue/steps.js';\n\ttry {\n\t\tconst { createRequire } = await import('node:module');\n\t\tconst userRequire = createRequire(join(cwd, 'package.json'));\n\t\tconst bddPkgPath = userRequire.resolve('browsecraft-bdd/package.json');\n\t\tconst bddDir = join(bddPkgPath, '..');\n\t\tconst relGlue = relative(cwd, join(bddDir, 'glue', 'steps.js')).replace(/\\\\/g, '/');\n\t\tif (existsSync(join(bddDir, 'glue', 'steps.js'))) {\n\t\t\tgluePath = relGlue;\n\t\t}\n\t} catch {\n\t\t// browsecraft-bdd not installed yet — use default path\n\t}\n\n\t// Create .vscode directory\n\tconst vscodeDir = join(cwd, '.vscode');\n\tif (!existsSync(vscodeDir)) {\n\t\tmkdirSync(vscodeDir, { recursive: true });\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/');\n\t}\n\n\t// Write or merge settings.json\n\tconst settingsPath = join(vscodeDir, 'settings.json');\n\tconst cucumberSettings: Record<string, unknown> = {\n\t\t'cucumberautocomplete.steps': [`${stepsDir}/**/*.ts`, `${stepsDir}/**/*.js`, gluePath],\n\t\t'cucumberautocomplete.strictGherkinCompletion': true,\n\t\t'cucumberautocomplete.strictGherkinValidation': true,\n\t\t'cucumber.glue': [`${stepsDir}/**/*.ts`, `${stepsDir}/**/*.js`, gluePath],\n\t\t'cucumber.features': [`${featuresDir}/**/*.feature`],\n\t};\n\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst existing = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n\t\t\tlet updated = false;\n\t\t\tfor (const [key, value] of Object.entries(cucumberSettings)) {\n\t\t\t\tif (!(key in existing)) {\n\t\t\t\t\texisting[key] = value;\n\t\t\t\t\tupdated = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updated) {\n\t\t\t\twriteFileSync(settingsPath, `${JSON.stringify(existing, null, 2)}\\n`, 'utf-8');\n\t\t\t\tconsole.log(' \\x1b[32mupdate\\x1b[0m .vscode/settings.json');\n\t\t\t} else {\n\t\t\t\tconsole.log(\n\t\t\t\t\t' \\x1b[33mskip\\x1b[0m .vscode/settings.json \\x1b[2m(already configured)\\x1b[0m',\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\twriteFileSync(settingsPath, `${JSON.stringify(cucumberSettings, null, 2)}\\n`, 'utf-8');\n\t\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/settings.json');\n\t\t}\n\t} else {\n\t\twriteFileSync(settingsPath, `${JSON.stringify(cucumberSettings, null, 2)}\\n`, 'utf-8');\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/settings.json');\n\t}\n\n\t// Write or merge extensions.json\n\tconst extensionsPath = join(vscodeDir, 'extensions.json');\n\tconst recommendedExtensions = [\n\t\t'alexkrechik.cucumberautocomplete',\n\t\t'CucumberOpen.cucumber-official',\n\t];\n\n\tif (existsSync(extensionsPath)) {\n\t\ttry {\n\t\t\tconst existing = JSON.parse(readFileSync(extensionsPath, 'utf-8'));\n\t\t\tconst recs: string[] = existing.recommendations ?? [];\n\t\t\tlet updated = false;\n\t\t\tfor (const ext of recommendedExtensions) {\n\t\t\t\tif (!recs.includes(ext)) {\n\t\t\t\t\trecs.push(ext);\n\t\t\t\t\tupdated = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updated) {\n\t\t\t\texisting.recommendations = recs;\n\t\t\t\twriteFileSync(extensionsPath, `${JSON.stringify(existing, null, 2)}\\n`, 'utf-8');\n\t\t\t\tconsole.log(' \\x1b[32mupdate\\x1b[0m .vscode/extensions.json');\n\t\t\t} else {\n\t\t\t\tconsole.log(\n\t\t\t\t\t' \\x1b[33mskip\\x1b[0m .vscode/extensions.json \\x1b[2m(already configured)\\x1b[0m',\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\twriteFileSync(\n\t\t\t\textensionsPath,\n\t\t\t\t`${JSON.stringify({ recommendations: recommendedExtensions }, null, 2)}\\n`,\n\t\t\t\t'utf-8',\n\t\t\t);\n\t\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/extensions.json');\n\t\t}\n\t} else {\n\t\twriteFileSync(\n\t\t\textensionsPath,\n\t\t\t`${JSON.stringify({ recommendations: recommendedExtensions }, null, 2)}\\n`,\n\t\t\t'utf-8',\n\t\t);\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/extensions.json');\n\t}\n\n\tconsole.log('\\n \\x1b[32mDone!\\x1b[0m IDE configured for Cucumber/Gherkin support.\\n');\n\tconsole.log(' What was set up:');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Cucumber extension discovers your custom steps');\n\tconsole.log(\" \\x1b[36m•\\x1b[0m Cucumber extension discovers BrowseCraft's 38 built-in steps\");\n\tconsole.log(' \\x1b[36m•\\x1b[0m Ctrl+Click navigation from .feature files to step definitions');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Autocomplete suggestions when writing features');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Recommended Cucumber extensions for VS Code');\n\tconsole.log();\n\tconsole.log(' If prompted, install the recommended extensions when VS Code asks.');\n\tconsole.log();\n}\n\n// ---------------------------------------------------------------------------\n// Config Loading\n// ---------------------------------------------------------------------------\n\nasync function loadConfig(): Promise<UserConfig | undefined> {\n\tconst cwd = process.cwd();\n\tconst candidates = [\n\t\t'browsecraft.config.ts',\n\t\t'browsecraft.config.js',\n\t\t'browsecraft.config.mjs',\n\t\t'browsecraft.config.mts',\n\t];\n\n\tfor (const name of candidates) {\n\t\tconst configPath = resolve(cwd, name);\n\t\tif (existsSync(configPath)) {\n\t\t\ttry {\n\t\t\t\t// For .ts files, ensure a TypeScript loader is registered\n\t\t\t\tif (name.endsWith('.ts') || name.endsWith('.mts')) {\n\t\t\t\t\tawait ensureTypeScriptLoader();\n\t\t\t\t}\n\t\t\t\tconst fileUrl = pathToFileURL(configPath).href;\n\t\t\t\tconst mod = await import(fileUrl);\n\t\t\t\treturn mod.default ?? mod;\n\t\t\t} catch {\n\t\t\t\t// Config file exists but couldn't be loaded -- continue with defaults\n\t\t\t\tconsole.warn(`Warning: Could not load ${name}. Using defaults.`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\n// ---------------------------------------------------------------------------\n// TypeScript Loader\n// ---------------------------------------------------------------------------\n\nlet tsLoaderRegistered = false;\n\n/**\n * Ensure a TypeScript loader is registered so that .ts test files can be imported.\n * Tries tsx first (fastest), then ts-node, then falls back to a helpful error.\n *\n * Resolution note: tsx is installed in the USER's project, not in browsecraft itself.\n * We must resolve it from the user's cwd using createRequire, not from our package.\n */\nasync function ensureTypeScriptLoader(): Promise<void> {\n\tif (tsLoaderRegistered) return;\n\n\t// Check if we're already running under a TS loader (e.g., `tsx`, `ts-node`, `bun`)\n\t// In that case, .ts imports already work\n\tconst execArgs = process.execArgv.join(' ');\n\tif (\n\t\texecArgs.includes('tsx') ||\n\t\texecArgs.includes('ts-node') ||\n\t\texecArgs.includes('loader') ||\n\t\tprocess.versions.bun // Bun handles TS natively\n\t) {\n\t\ttsLoaderRegistered = true;\n\t\treturn;\n\t}\n\n\t// Create a require function rooted at the user's cwd so we can find tsx/ts-node\n\t// installed in the user's project (not in our package)\n\tconst { createRequire } = await import('node:module');\n\tconst userRequire = createRequire(pathToFileURL(resolve(process.cwd(), 'package.json')));\n\n\t// Strategy 1: tsx 4.x — use the tsx/esm/api register() function\n\t// This is the modern approach that works with tsx 4.x+\n\ttry {\n\t\tconst tsxApiPath = userRequire.resolve('tsx/esm/api');\n\t\tconst { register } = await import(pathToFileURL(tsxApiPath).href);\n\t\tif (typeof register === 'function') {\n\t\t\tregister();\n\t\t\ttsLoaderRegistered = true;\n\t\t\treturn;\n\t\t}\n\t} catch {\n\t\t// tsx/esm/api not available, try next strategy\n\t}\n\n\t// Strategy 2: Older tsx/ts-node — use Node.js module.register()\n\t// Works with tsx <4.x and ts-node\n\tfor (const loader of ['tsx/esm', 'ts-node/esm']) {\n\t\ttry {\n\t\t\tconst { register } = await import('node:module');\n\t\t\tif (typeof register === 'function') {\n\t\t\t\t// Resolve from user's project root so the loader is found\n\t\t\t\tregister(loader, pathToFileURL(resolve(process.cwd(), '/')));\n\t\t\t\ttsLoaderRegistered = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Loader not available, try next\n\t\t}\n\t}\n\n\t// If neither tsx nor ts-node is available, give a helpful error\n\tconsole.error(\n\t\t'\\n Error: Cannot import TypeScript test files.\\n' +\n\t\t\t' Install tsx (recommended) or ts-node:\\n\\n' +\n\t\t\t' npm install -D tsx\\n\\n' +\n\t\t\t' Or run browsecraft with tsx:\\n\\n' +\n\t\t\t' npx tsx node_modules/.bin/browsecraft test\\n',\n\t);\n\tprocess.exit(1);\n}\n\n// ---------------------------------------------------------------------------\n// Flag parsing\n// ---------------------------------------------------------------------------\n\ninterface CLIFlags {\n\theaded?: boolean;\n\theadless?: boolean;\n\tbrowser?: string;\n\tworkers?: number;\n\ttimeout?: number;\n\tretries?: number;\n\tgrep?: string;\n\tbail?: boolean;\n\tdebug?: boolean;\n\tbdd?: boolean;\n\t/** BDD tag filter expression, e.g. \"@smoke and not @wip\" */\n\ttag?: string;\n\t/** Execution strategy: parallel, sequential, or matrix */\n\tstrategy?: string;\n\t/** BDD scenario name filter (alias for --grep in BDD mode) */\n\tscenario?: string;\n}\n\nfunction parseFlags(args: string[]): CLIFlags {\n\tconst flags: CLIFlags = {};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tswitch (arg) {\n\t\t\tcase '--headed':\n\t\t\t\tflags.headed = true;\n\t\t\t\tbreak;\n\t\t\tcase '--headless':\n\t\t\t\tflags.headless = true;\n\t\t\t\tbreak;\n\t\t\tcase '--debug':\n\t\t\t\tflags.debug = true;\n\t\t\t\tbreak;\n\t\t\tcase '--bdd':\n\t\t\t\tflags.bdd = true;\n\t\t\t\tbreak;\n\t\t\tcase '--bail':\n\t\t\t\tflags.bail = true;\n\t\t\t\tbreak;\n\t\t\tcase '--browser':\n\t\t\t\tflags.browser = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--workers':\n\t\t\t\tflags.workers = Number.parseInt(args[++i] ?? '1', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--timeout':\n\t\t\t\tflags.timeout = Number.parseInt(args[++i] ?? '30000', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--retries':\n\t\t\t\tflags.retries = Number.parseInt(args[++i] ?? '0', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--grep':\n\t\t\tcase '-g':\n\t\t\t\tflags.grep = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--tag':\n\t\t\tcase '--tags':\n\t\t\t\tflags.tag = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--strategy':\n\t\t\t\tflags.strategy = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--scenario':\n\t\t\t\tflags.scenario = args[++i];\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn flags;\n}\n\n// ---------------------------------------------------------------------------\n// Help\n// ---------------------------------------------------------------------------\n\nfunction printHelp() {\n\tconsole.log(`\n browsecraft v${VERSION} -- AI-native browser testing\n\n Usage:\n browsecraft test [files...] [options]\n browsecraft bdd [features...] [options]\n browsecraft test --bdd [features...] [options]\n browsecraft init\n browsecraft setup-ide\n\n Commands:\n test Run browser tests\n bdd Run BDD feature files (shorthand for test --bdd)\n test --bdd Run BDD feature files (Gherkin)\n init Create a new project with example config and test\n setup-ide Configure VS Code for Cucumber step discovery\n\n Options:\n --bdd Run BDD feature files instead of programmatic tests\n --browser <names> Browser(s) to use: chrome,firefox,edge (comma-separated)\n --headed Run in headed mode (show the browser)\n --headless Run in headless mode (default)\n --workers <n> Parallel workers — features run concurrently (default: 1)\n --timeout <ms> Global timeout in milliseconds (default: 30000)\n --retries <n> Retry failed tests n times (default: 0)\n --grep <pattern> Only run tests/scenarios matching pattern\n --scenario <name> Run only scenarios whose name contains <name>\n --tag <expr> BDD tag filter: \"@smoke\", \"@smoke and not @wip\"\n --strategy <s> Multi-browser strategy: parallel, sequential, matrix\n --bail Stop after first failure\n --debug Enable verbose debug logging\n -h, --help Show this help message\n -v, --version Show version\n\n BDD Examples:\n browsecraft bdd # All features, 1 browser\n browsecraft bdd features/login.feature # Single feature\n browsecraft bdd features/login.feature:15 # Specific scenario by line\n browsecraft bdd --headed # Watch it run\n browsecraft test --bdd features/login.feature # Equivalent long form\n browsecraft test --bdd --scenario \"Valid login\" # Specific scenario by name\n browsecraft test --bdd --tag \"@smoke\" # Tag filter\n browsecraft test --bdd --grep \"checkout\" # Name filter\n browsecraft test --bdd --workers 4 # 4 features in parallel\n browsecraft test --bdd --browser chrome,firefox # Multi-browser\n browsecraft test --bdd --browser chrome,firefox,edge --strategy matrix\n browsecraft test --bdd --headed --browser firefox # Headed mode\n\n Programmatic Examples:\n browsecraft test # Run all tests\n browsecraft test tests/login.test.ts # Run specific file\n browsecraft test --headed --browser firefox\n browsecraft test --grep \"login\" --bail\n browsecraft setup-ide # Auto-configure IDE for BDD\n`);\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\nmain().catch((err) => {\n\tconsole.error('Fatal error:', err.message);\n\tprocess.exit(1);\n});\n"]}
package/dist/cli.js CHANGED
@@ -21,6 +21,9 @@ async function main() {
21
21
  case "test":
22
22
  await runTests(args.slice(1));
23
23
  break;
24
+ case "bdd":
25
+ await runTests(["--bdd", ...args.slice(1)]);
26
+ break;
24
27
  case "init":
25
28
  await initProject();
26
29
  break;
@@ -28,7 +31,9 @@ async function main() {
28
31
  await setupIde();
29
32
  break;
30
33
  default:
31
- if (command && (command.endsWith(".ts") || command.endsWith(".js"))) {
34
+ if (command?.endsWith(".feature")) {
35
+ await runTests(["--bdd", ...args]);
36
+ } else if (command?.endsWith(".ts") || command?.endsWith(".js")) {
32
37
  await runTests(args);
33
38
  } else {
34
39
  console.error(`Unknown command: ${command}`);
@@ -264,7 +269,13 @@ async function runBddTests(config, userConfig, flags, filePatterns) {
264
269
  console.log(` ${prefix}Step not defined. Add it to your step definitions.`);
265
270
  }
266
271
  },
267
- onScenarioEnd: () => {
272
+ onScenarioEnd: (result) => {
273
+ if (result.hookError) {
274
+ console.log(` ${prefix}\x1B[31m\u2717 ${result.hookError.message}\x1B[0m`);
275
+ }
276
+ if (result.status === "failed" && !result.hookError && result.steps.length === 0) {
277
+ console.log(` ${prefix}\x1B[31m\u2717 Scenario failed with no steps executed\x1B[0m`);
278
+ }
268
279
  }
269
280
  });
270
281
  let allFeatures2 = [];
@@ -364,7 +375,25 @@ async function runBddTests(config, userConfig, flags, filePatterns) {
364
375
  }
365
376
  console.log("");
366
377
  if (scenarios.failed > 0) {
367
- console.log(" \x1B[31mSome scenarios failed.\x1B[0m\n");
378
+ console.log(" \x1B[31mFailed scenarios:\x1B[0m");
379
+ for (const feat of allFeatures) {
380
+ for (const scen of feat.scenarios) {
381
+ if (scen.status !== "failed") continue;
382
+ console.log(` \x1B[31m\u2717\x1B[0m ${feat.name} \u2192 ${scen.name}`);
383
+ if (scen.hookError) {
384
+ console.log(` Error: ${scen.hookError.message}`);
385
+ }
386
+ for (const st of scen.steps) {
387
+ if (st.status === "failed" && st.error) {
388
+ console.log(` ${st.keyword.trim()} ${st.text}: ${st.error.message}`);
389
+ }
390
+ if (st.status === "undefined") {
391
+ console.log(` ${st.keyword.trim()} ${st.text}: \x1B[33mStep not defined\x1B[0m`);
392
+ }
393
+ }
394
+ }
395
+ }
396
+ console.log("");
368
397
  } else if (steps.undefined > 0) {
369
398
  console.log(" \x1B[33mSome steps are undefined.\x1B[0m\n");
370
399
  } else {
@@ -734,12 +763,14 @@ function printHelp() {
734
763
 
735
764
  Usage:
736
765
  browsecraft test [files...] [options]
766
+ browsecraft bdd [features...] [options]
737
767
  browsecraft test --bdd [features...] [options]
738
768
  browsecraft init
739
769
  browsecraft setup-ide
740
770
 
741
771
  Commands:
742
772
  test Run browser tests
773
+ bdd Run BDD feature files (shorthand for test --bdd)
743
774
  test --bdd Run BDD feature files (Gherkin)
744
775
  init Create a new project with example config and test
745
776
  setup-ide Configure VS Code for Cucumber step discovery
@@ -762,9 +793,11 @@ function printHelp() {
762
793
  -v, --version Show version
763
794
 
764
795
  BDD Examples:
765
- browsecraft test --bdd # All features, 1 browser
766
- browsecraft test --bdd features/login.feature # Single feature
767
- browsecraft test --bdd features/login.feature:15 # Specific scenario by line
796
+ browsecraft bdd # All features, 1 browser
797
+ browsecraft bdd features/login.feature # Single feature
798
+ browsecraft bdd features/login.feature:15 # Specific scenario by line
799
+ browsecraft bdd --headed # Watch it run
800
+ browsecraft test --bdd features/login.feature # Equivalent long form
768
801
  browsecraft test --bdd --scenario "Valid login" # Specific scenario by name
769
802
  browsecraft test --bdd --tag "@smoke" # Tag filter
770
803
  browsecraft test --bdd --grep "checkout" # Name filter
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"names":["allFeatures"],"mappings":"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","file":"cli.js","sourcesContent":["#!/usr/bin/env node\n// ============================================================================\n// Browsecraft - CLI\n// The command-line interface for running tests and initializing projects.\n//\n// npx browsecraft test # Run all tests\n// npx browsecraft test login.test.ts # Run specific file\n// npx browsecraft init # Scaffold a new project\n// npx browsecraft --help # Show help\n// ============================================================================\n\nimport { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';\nimport { join, relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { BrowserName } from 'browsecraft-bidi';\nimport { type RunnableTest, type RunnerOptions, TestRunner } from 'browsecraft-runner';\nimport { Browser } from './browser.js';\nimport { type UserConfig, resolveConfig } from './config.js';\nimport { type TestCase, runAfterAllHooks, runTest, testRegistry } from './test.js';\n\nconst VERSION = '0.3.0';\n\nasync function main() {\n\tconst args = process.argv.slice(2);\n\n\tif (args.length === 0 || args.includes('--help') || args.includes('-h')) {\n\t\tprintHelp();\n\t\treturn;\n\t}\n\n\tif (args.includes('--version') || args.includes('-v')) {\n\t\tconsole.log(`browsecraft v${VERSION}`);\n\t\treturn;\n\t}\n\n\tconst command = args[0];\n\n\tswitch (command) {\n\t\tcase 'test':\n\t\t\tawait runTests(args.slice(1));\n\t\t\tbreak;\n\t\tcase 'init':\n\t\t\tawait initProject();\n\t\t\tbreak;\n\t\tcase 'setup-ide':\n\t\t\tawait setupIde();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t// If no command, assume it's a file path to test\n\t\t\tif (command && (command.endsWith('.ts') || command.endsWith('.js'))) {\n\t\t\t\tawait runTests(args);\n\t\t\t} else {\n\t\t\t\tconsole.error(`Unknown command: ${command}`);\n\t\t\t\tconsole.error('Run \"browsecraft --help\" for usage information.');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Test Command\n// ---------------------------------------------------------------------------\n\nasync function runTests(args: string[]) {\n\t// Parse CLI flags\n\tconst flags = parseFlags(args);\n\tconst filePatterns = args.filter((a) => !a.startsWith('--'));\n\n\t// Load config file if it exists\n\tconst userConfig = await loadConfig();\n\tconst config = resolveConfig(userConfig);\n\n\t// Apply CLI overrides\n\tif (flags.headed || flags.headless === false) {\n\t\tconfig.headless = false;\n\t}\n\tif (flags.browser) {\n\t\tconfig.browser = flags.browser as BrowserName;\n\t}\n\tif (flags.workers !== undefined) {\n\t\tconfig.workers = flags.workers;\n\t}\n\tif (flags.timeout !== undefined) {\n\t\tconfig.timeout = flags.timeout;\n\t}\n\tif (flags.retries !== undefined) {\n\t\tconfig.retries = flags.retries;\n\t}\n\tif (flags.debug) {\n\t\tconfig.debug = true;\n\t}\n\n\t// BDD mode: run .feature files with step definitions\n\tif (flags.bdd) {\n\t\tawait runBddTests(config, userConfig, flags, filePatterns);\n\t\treturn;\n\t}\n\n\t// Set up runner options\n\tconst runnerOptions: RunnerOptions = {\n\t\tconfig,\n\t\tfiles: filePatterns.length > 0 ? filePatterns : undefined,\n\t\tgrep: flags.grep,\n\t\tbail: flags.bail,\n\t};\n\n\t// Run tests\n\tconst runner = new TestRunner(runnerOptions);\n\n\t// loadFile callback: imports the test file and returns registered tests\n\tconst loadFile = async (file: string): Promise<RunnableTest[]> => {\n\t\tconst startIdx = testRegistry.length;\n\n\t\t// For TypeScript files, register a TypeScript loader if available\n\t\tif (file.endsWith('.ts') || file.endsWith('.mts')) {\n\t\t\tawait ensureTypeScriptLoader();\n\t\t}\n\n\t\tconst fileUrl = pathToFileURL(file).href;\n\t\tawait import(fileUrl);\n\t\treturn testRegistry.slice(startIdx).map((tc) => ({\n\t\t\ttitle: tc.title,\n\t\t\tsuitePath: tc.suitePath,\n\t\t\tskip: tc.skip,\n\t\t\tonly: tc.only,\n\t\t\toptions: tc.options,\n\t\t\tfn: tc.fn as (fixtures: unknown) => Promise<void>,\n\t\t}));\n\t};\n\n\t// Launch a shared browser for all tests\n\tlet sharedBrowser: Browser | undefined;\n\n\ttry {\n\t\tsharedBrowser = await Browser.launch({\n\t\t\tbrowser: config.browser,\n\t\t\theadless: config.headless,\n\t\t\texecutablePath: config.executablePath,\n\t\t\tdebug: config.debug,\n\t\t\ttimeout: config.timeout,\n\t\t});\n\t} catch (err) {\n\t\tconsole.error(`Failed to launch browser: ${err instanceof Error ? err.message : String(err)}`);\n\t\tprocess.exit(1);\n\t}\n\n\t// executeTest callback: runs a single test with fixture setup/teardown\n\tconst executeTest = async (test: RunnableTest) => {\n\t\treturn runTest(test as unknown as TestCase, sharedBrowser);\n\t};\n\n\ttry {\n\t\tconst exitCode = await runner.run(loadFile, executeTest);\n\t\tawait sharedBrowser.close().catch(() => {});\n\t\tprocess.exit(exitCode);\n\t} catch (err) {\n\t\tawait sharedBrowser?.close().catch(() => {});\n\t\tthrow err;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// BDD Command — runs .feature files with step definitions\n//\n// Supports:\n// - Single / multiple feature files: browsecraft test --bdd login.feature\n// - Tag filtering: --tag \"@smoke and not @wip\"\n// - Name filtering: --grep \"login\"\n// - Multi-browser: --browser chrome,firefox\n// - Parallel: --workers 4\n// - Strategy: --strategy parallel|sequential|matrix\n// ---------------------------------------------------------------------------\n\ntype BddModule = typeof import('browsecraft-bdd');\n\nasync function runBddTests(\n\tconfig: ReturnType<typeof resolveConfig>,\n\tuserConfig?: UserConfig,\n\tflags?: CLIFlags,\n\tfilePatterns?: string[],\n): Promise<void> {\n\tconst bddModule = (await import('browsecraft-bdd')) as BddModule;\n\tconst { parseGherkin, BddExecutor, registerBuiltInSteps, After, computeSummary } = bddModule;\n\tconst cwd = process.cwd();\n\n\t// ── Resolve options from config + CLI flags ────────────────────────\n\tconst bddConfig = userConfig?.bdd ?? {};\n\tconst featuresPattern = bddConfig.features ?? 'features/**/*.feature';\n\tconst stepsPattern = bddConfig.steps ?? 'steps/**/*.{ts,js,mts,mjs}';\n\tconst useBuiltInSteps = bddConfig.builtInSteps !== false;\n\n\t// Browsers: --browser chrome,firefox or config.browsers or [config.browser]\n\tconst browserNames: string[] = flags?.browser\n\t\t? flags.browser.split(',').map((b) => b.trim())\n\t\t: (config.browsers ?? [config.browser]);\n\n\t// Workers per browser (for parallel feature execution)\n\tconst workers = flags?.workers ?? (browserNames.length > 1 ? 1 : 1);\n\n\t// Strategy: --strategy or config.strategy\n\tconst strategy = (flags?.strategy ?? config.strategy ?? 'sequential') as\n\t\t| 'parallel'\n\t\t| 'sequential'\n\t\t| 'matrix';\n\n\t// Tag filter: --tag or bddConfig.tagFilter\n\tconst tagFilter = flags?.tag ?? bddConfig.tagFilter;\n\n\t// Grep: --grep or --scenario or bddConfig.grep\n\tconst grepPattern = flags?.scenario ?? flags?.grep ?? bddConfig.grep;\n\n\t// Fail fast: --bail\n\tconst failFast = flags?.bail ?? false;\n\n\t// ── Step 1: Discover .feature files ────────────────────────────────\n\t// Parse feature:line syntax (e.g. features/login.feature:15)\n\tconst targetLines = new Map<string, number[]>(); // file → line numbers\n\tlet featureFiles: string[];\n\n\tif (filePatterns && filePatterns.length > 0) {\n\t\t// Explicit feature files from CLI positional args\n\t\tconst resolvedPaths: string[] = [];\n\t\tfor (const pattern of filePatterns) {\n\t\t\tconst [filePart, linePart] = pattern.split(':');\n\t\t\tconst absPath = resolve(cwd, filePart!);\n\t\t\tif (!existsSync(absPath)) continue;\n\n\t\t\tif (!resolvedPaths.includes(absPath)) {\n\t\t\t\tresolvedPaths.push(absPath);\n\t\t\t}\n\t\t\tif (linePart) {\n\t\t\t\tconst lineNum = Number.parseInt(linePart, 10);\n\t\t\t\tif (!Number.isNaN(lineNum)) {\n\t\t\t\t\tconst existing = targetLines.get(absPath) ?? [];\n\t\t\t\t\texisting.push(lineNum);\n\t\t\t\t\ttargetLines.set(absPath, existing);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfeatureFiles = resolvedPaths;\n\t\tif (featureFiles.length === 0) {\n\t\t\tconsole.error('\\n No matching feature files found.\\n');\n\t\t\tprocess.exit(1);\n\t\t}\n\t} else {\n\t\tfeatureFiles = discoverFiles(cwd, featuresPattern, ['.feature']);\n\t}\n\n\tif (featureFiles.length === 0) {\n\t\tconsole.log('\\n No .feature files found.\\n');\n\t\tconsole.log(` Feature pattern: ${featuresPattern}`);\n\t\tconsole.log(' Create features/*.feature files or adjust bdd.features in your config.\\n');\n\t\tprocess.exit(0);\n\t}\n\n\t// ── Step 2: Register steps ─────────────────────────────────────────\n\tif (useBuiltInSteps) {\n\t\tregisterBuiltInSteps();\n\t}\n\n\tconst stepFiles = discoverFiles(cwd, stepsPattern, ['.ts', '.js', '.mts', '.mjs']);\n\tfor (const stepFile of stepFiles) {\n\t\tif (stepFile.endsWith('.ts') || stepFile.endsWith('.mts')) {\n\t\t\tawait ensureTypeScriptLoader();\n\t\t}\n\t\tconst fileUrl = pathToFileURL(stepFile).href;\n\t\tawait import(fileUrl);\n\t}\n\n\t// Cleanup hook for browser contexts\n\tAfter(async ({ world }) => {\n\t\tconst w = world as unknown as Record<string, { close(): Promise<unknown> } | undefined>;\n\t\tif (w?._context) {\n\t\t\tawait w._context.close().catch(() => {});\n\t\t}\n\t});\n\n\t// ── Step 3: Parse .feature files ───────────────────────────────────\n\tconst documents = featureFiles.map((file) => {\n\t\tconst source = readFileSync(file, 'utf-8');\n\t\treturn parseGherkin(source, relative(cwd, file));\n\t});\n\n\t// Build a scenario filter for line-number targeting\n\tconst lineFilter =\n\t\ttargetLines.size > 0\n\t\t\t? (scenario: { line: number; name: string }, _tags: string[], uri?: string) => {\n\t\t\t\t\tfor (const [file, lines] of targetLines) {\n\t\t\t\t\t\tconst relPath = relative(cwd, file);\n\t\t\t\t\t\tif (uri === relPath || uri === file) {\n\t\t\t\t\t\t\treturn lines.includes(scenario.line);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true; // no line constraint for this file\n\t\t\t\t}\n\t\t\t: undefined;\n\n\t// ── Step 4: Determine execution plan ───────────────────────────────\n\tconst isMultiBrowser = browserNames.length > 1;\n\tconst isParallel = workers > 1;\n\n\t// Header\n\tconst parts: string[] = [\n\t\t`${featureFiles.length} feature file${featureFiles.length > 1 ? 's' : ''}`,\n\t];\n\tif (isMultiBrowser) parts.push(`on ${browserNames.join(', ')}`);\n\tif (isParallel) parts.push(`(${workers} workers)`);\n\tif (tagFilter) parts.push(`[tags: ${tagFilter}]`);\n\tif (grepPattern) parts.push(`[grep: ${grepPattern}]`);\n\tif (targetLines.size > 0) {\n\t\tconst lineDescs = [...targetLines.entries()].map(\n\t\t\t([f, ls]) => `${relative(cwd, f)}:${ls.join(',')}`,\n\t\t);\n\t\tparts.push(`[lines: ${lineDescs.join(' ')}]`);\n\t}\n\n\tconsole.log(`\\n Browsecraft BDD - Running ${parts.join(' ')}\\n`);\n\n\tif (isMultiBrowser) {\n\t\tconsole.log(` Strategy: ${strategy}`);\n\t\tconsole.log(\n\t\t\t` Browsers: ${browserNames.map((b) => b.charAt(0).toUpperCase() + b.slice(1)).join(', ')}`,\n\t\t);\n\t\tconsole.log('');\n\t}\n\n\t// ── Step 5: Execute ────────────────────────────────────────────────\n\ttype FeatureResultType = Awaited<\n\t\tReturnType<InstanceType<typeof BddExecutor>['run']>\n\t>['features'][number];\n\n\t/**\n\t * Run a set of documents on a specific browser.\n\t * Returns the feature results and the launched browser instance.\n\t */\n\tconst runOnBrowser = async (\n\t\tbrowserName: string,\n\t\tdocs: ReturnType<typeof parseGherkin>[],\n\t\tprefix: string,\n\t): Promise<{ features: FeatureResultType[]; duration: number; browser: Browser }> => {\n\t\tconst browser = await Browser.launch({\n\t\t\tbrowser: browserName as BrowserName,\n\t\t\theadless: config.headless,\n\t\t\texecutablePath: config.executablePath,\n\t\t\tdebug: config.debug,\n\t\t\ttimeout: config.timeout,\n\t\t});\n\n\t\tconst createExecutor = (docSubset: ReturnType<typeof parseGherkin>[]) =>\n\t\t\tnew BddExecutor({\n\t\t\t\tstepTimeout: config.timeout,\n\t\t\t\ttagFilter: tagFilter ?? undefined,\n\t\t\t\tgrep: grepPattern ?? undefined,\n\t\t\t\tscenarioFilter: lineFilter ?? undefined,\n\t\t\t\tfailFast,\n\t\t\t\tworldFactory: async () => {\n\t\t\t\t\tconst context = await browser.newContext();\n\t\t\t\t\tconst page = await context.newPage();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpage,\n\t\t\t\t\t\tbrowser,\n\t\t\t\t\t\tctx: {},\n\t\t\t\t\t\tattach: () => {},\n\t\t\t\t\t\tlog: (msg: string) => console.log(` ${prefix}${msg}`),\n\t\t\t\t\t\t_context: context,\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\tonFeatureStart: (feature) => {\n\t\t\t\t\tconsole.log(`\\n ${prefix}Feature: ${feature.name}`);\n\t\t\t\t},\n\t\t\t\tonScenarioStart: (scenario) => {\n\t\t\t\t\tconsole.log(` ${prefix}Scenario: ${scenario.name}`);\n\t\t\t\t},\n\t\t\t\tonStepEnd: (result) => {\n\t\t\t\t\tconst icon =\n\t\t\t\t\t\tresult.status === 'passed'\n\t\t\t\t\t\t\t? '\\x1b[32m+\\x1b[0m'\n\t\t\t\t\t\t\t: result.status === 'failed'\n\t\t\t\t\t\t\t\t? '\\x1b[31mx\\x1b[0m'\n\t\t\t\t\t\t\t\t: result.status === 'undefined'\n\t\t\t\t\t\t\t\t\t? '\\x1b[33m?\\x1b[0m'\n\t\t\t\t\t\t\t\t\t: result.status === 'pending'\n\t\t\t\t\t\t\t\t\t\t? '\\x1b[33m-\\x1b[0m'\n\t\t\t\t\t\t\t\t\t\t: '\\x1b[90m-\\x1b[0m';\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t` ${prefix}${icon} ${result.keyword.trim()} ${result.text} (${result.duration}ms)`,\n\t\t\t\t\t);\n\t\t\t\t\tif (result.status === 'failed' && result.error) {\n\t\t\t\t\t\tconsole.log(` ${prefix}${result.error.message}`);\n\t\t\t\t\t}\n\t\t\t\t\tif (result.status === 'undefined') {\n\t\t\t\t\t\tconsole.log(` ${prefix}Step not defined. Add it to your step definitions.`);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonScenarioEnd: () => {},\n\t\t\t});\n\n\t\tlet allFeatures: FeatureResultType[] = [];\n\t\tconst start = Date.now();\n\n\t\tif (workers > 1 && docs.length > 1) {\n\t\t\t// Parallel: split documents into worker chunks\n\t\t\tconst chunks = splitIntoChunks(docs, workers);\n\t\t\tconst results = await Promise.all(\n\t\t\t\tchunks.map((chunk) => {\n\t\t\t\t\tconst exec = createExecutor(chunk);\n\t\t\t\t\treturn exec.run(chunk);\n\t\t\t\t}),\n\t\t\t);\n\t\t\tallFeatures = results.flatMap((r) => r.features);\n\t\t} else {\n\t\t\t// Sequential: single executor\n\t\t\tconst exec = createExecutor(docs);\n\t\t\tconst result = await exec.run(docs);\n\t\t\tallFeatures = result.features;\n\t\t}\n\n\t\treturn { features: allFeatures, duration: Date.now() - start, browser };\n\t};\n\n\t// ── Execute according to strategy ──────────────────────────────────\n\tconst browsers: Browser[] = [];\n\tlet allFeatures: FeatureResultType[] = [];\n\tlet totalDuration = 0;\n\tconst perBrowserResults: Array<{\n\t\tbrowserName: string;\n\t\tfeatures: FeatureResultType[];\n\t\tduration: number;\n\t}> = [];\n\n\ttry {\n\t\tif (!isMultiBrowser) {\n\t\t\t// Single browser — simple path\n\t\t\tconst { features, duration, browser } = await runOnBrowser(browserNames[0]!, documents, '');\n\t\t\tbrowsers.push(browser);\n\t\t\tallFeatures = features;\n\t\t\ttotalDuration = duration;\n\t\t\tperBrowserResults.push({ browserName: browserNames[0]!, features, duration });\n\t\t} else if (strategy === 'sequential') {\n\t\t\t// Sequential: one browser at a time, each runs all features\n\t\t\tfor (const bName of browserNames) {\n\t\t\t\tconst prefix = `\\x1b[36m[${bName}]\\x1b[0m `;\n\t\t\t\tconst { features, duration, browser } = await runOnBrowser(bName, documents, prefix);\n\t\t\t\tbrowsers.push(browser);\n\t\t\t\tallFeatures.push(...features);\n\t\t\t\ttotalDuration += duration;\n\t\t\t\tperBrowserResults.push({ browserName: bName, features, duration });\n\t\t\t}\n\t\t} else {\n\t\t\t// Parallel or Matrix: all browsers simultaneously\n\t\t\t// (matrix = every feature on every browser; parallel = same as matrix for distinct browsers)\n\t\t\tconst results = await Promise.all(\n\t\t\t\tbrowserNames.map((bName) => {\n\t\t\t\t\tconst prefix = `\\x1b[36m[${bName}]\\x1b[0m `;\n\t\t\t\t\treturn runOnBrowser(bName, documents, prefix);\n\t\t\t\t}),\n\t\t\t);\n\t\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\t\tconst r = results[i]!;\n\t\t\t\tbrowsers.push(r.browser);\n\t\t\t\tallFeatures.push(...r.features);\n\t\t\t\tperBrowserResults.push({\n\t\t\t\t\tbrowserName: browserNames[i]!,\n\t\t\t\t\tfeatures: r.features,\n\t\t\t\t\tduration: r.duration,\n\t\t\t\t});\n\t\t\t}\n\t\t\ttotalDuration = Math.max(...results.map((r) => r.duration));\n\t\t}\n\n\t\t// ── Print summary ──────────────────────────────────────────────\n\t\tconst summary = computeSummary(allFeatures);\n\t\tconsole.log('\\n ─────────────────────────────────────');\n\n\t\t// Per-browser breakdown for multi-browser runs\n\t\tif (isMultiBrowser) {\n\t\t\tfor (const br of perBrowserResults) {\n\t\t\t\tconst brSummary = computeSummary(br.features);\n\t\t\t\tconst brLabel = br.browserName.charAt(0).toUpperCase() + br.browserName.slice(1);\n\t\t\t\tconst brParts: string[] = [];\n\t\t\t\tif (brSummary.scenarios.passed > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[32m${brSummary.scenarios.passed} passed\\x1b[0m`);\n\t\t\t\tif (brSummary.scenarios.failed > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[31m${brSummary.scenarios.failed} failed\\x1b[0m`);\n\t\t\t\tif (brSummary.scenarios.skipped > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[33m${brSummary.scenarios.skipped} skipped\\x1b[0m`);\n\t\t\t\tconsole.log(\n\t\t\t\t\t` ${brLabel.padEnd(10)} ${brParts.join(', ')} (${brSummary.scenarios.total} scenarios) ${br.duration < 1000 ? `${br.duration}ms` : `${(br.duration / 1000).toFixed(1)}s`}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconsole.log(' ─────────────────────────────────────');\n\t\t}\n\n\t\tconst { scenarios, steps } = summary;\n\n\t\tconst scenarioParts: string[] = [];\n\t\tif (scenarios.passed > 0) scenarioParts.push(`\\x1b[32m${scenarios.passed} passed\\x1b[0m`);\n\t\tif (scenarios.failed > 0) scenarioParts.push(`\\x1b[31m${scenarios.failed} failed\\x1b[0m`);\n\t\tif (scenarios.skipped > 0) scenarioParts.push(`\\x1b[33m${scenarios.skipped} skipped\\x1b[0m`);\n\t\tif (scenarios.pending > 0) scenarioParts.push(`\\x1b[33m${scenarios.pending} pending\\x1b[0m`);\n\n\t\tconst stepParts: string[] = [];\n\t\tif (steps.passed > 0) stepParts.push(`\\x1b[32m${steps.passed} passed\\x1b[0m`);\n\t\tif (steps.failed > 0) stepParts.push(`\\x1b[31m${steps.failed} failed\\x1b[0m`);\n\t\tif (steps.undefined > 0) stepParts.push(`\\x1b[33m${steps.undefined} undefined\\x1b[0m`);\n\t\tif (steps.skipped > 0) stepParts.push(`\\x1b[90m${steps.skipped} skipped\\x1b[0m`);\n\n\t\tconsole.log(` Scenarios: ${scenarioParts.join(', ')} (${scenarios.total} total)`);\n\t\tconsole.log(` Steps: ${stepParts.join(', ')} (${steps.total} total)`);\n\t\tconsole.log(\n\t\t\t` Time: ${totalDuration < 1000 ? `${totalDuration}ms` : `${(totalDuration / 1000).toFixed(1)}s`}`,\n\t\t);\n\t\tif (isMultiBrowser) {\n\t\t\tconsole.log(` Strategy: ${strategy}`);\n\t\t}\n\t\tconsole.log('');\n\n\t\tif (scenarios.failed > 0) {\n\t\t\tconsole.log(' \\x1b[31mSome scenarios failed.\\x1b[0m\\n');\n\t\t} else if (steps.undefined > 0) {\n\t\t\tconsole.log(' \\x1b[33mSome steps are undefined.\\x1b[0m\\n');\n\t\t} else {\n\t\t\tconsole.log(' \\x1b[32mAll scenarios passed!\\x1b[0m\\n');\n\t\t}\n\n\t\t// Clean up all browsers\n\t\tfor (const b of browsers) {\n\t\t\tawait b.close().catch(() => {});\n\t\t}\n\n\t\tprocess.exit(scenarios.failed > 0 || steps.undefined > 0 ? 1 : 0);\n\t} catch (err) {\n\t\tfor (const b of browsers) {\n\t\t\tawait b.close().catch(() => {});\n\t\t}\n\t\tconsole.error(`BDD execution error: ${err instanceof Error ? err.message : String(err)}`);\n\t\tprocess.exit(1);\n\t}\n}\n\n/**\n * Split an array into N roughly-equal chunks.\n * Used for distributing feature files across parallel workers.\n */\nfunction splitIntoChunks<T>(items: T[], n: number): T[][] {\n\tconst chunks: T[][] = [];\n\tconst size = Math.ceil(items.length / n);\n\tfor (let i = 0; i < items.length; i += size) {\n\t\tchunks.push(items.slice(i, i + size));\n\t}\n\treturn chunks;\n}\n\n/**\n * Discover files matching a glob-like pattern within a directory.\n * Supports patterns like 'features/**\\/*.feature' or 'steps/**\\/*.{ts,js}'.\n */\nfunction discoverFiles(rootDir: string, pattern: string, extensions: string[]): string[] {\n\tconst files: string[] = [];\n\n\t// Extract the base directory from the pattern (e.g., 'features' from 'features/**/*.feature')\n\tconst baseParts = pattern.split('/');\n\tlet baseDir = rootDir;\n\tfor (const part of baseParts) {\n\t\tif (part.includes('*') || part.includes('{')) break;\n\t\tbaseDir = join(baseDir, part);\n\t}\n\n\tif (!existsSync(baseDir)) return files;\n\n\tconst walkDir = (dir: string): void => {\n\t\tconst skip = new Set(['node_modules', 'dist', '.browsecraft', '.git', 'coverage', '.turbo']);\n\t\tlet entries: string[];\n\t\ttry {\n\t\t\tentries = readdirSync(dir);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tif (skip.has(entry)) continue;\n\t\t\tconst fullPath = join(dir, entry);\n\t\t\tlet stat: ReturnType<typeof statSync>;\n\t\t\ttry {\n\t\t\t\tstat = statSync(fullPath);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (stat.isDirectory()) {\n\t\t\t\twalkDir(fullPath);\n\t\t\t} else if (stat.isFile()) {\n\t\t\t\tif (extensions.some((ext) => entry.endsWith(ext))) {\n\t\t\t\t\tfiles.push(fullPath);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\twalkDir(baseDir);\n\treturn files.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Init Command\n// ---------------------------------------------------------------------------\n\nasync function initProject() {\n\tconst cwd = process.cwd();\n\n\tconsole.log('\\n Browsecraft - Project Setup\\n');\n\n\t// Create config file\n\tconst configPath = join(cwd, 'browsecraft.config.ts');\n\tif (!existsSync(configPath)) {\n\t\twriteFileSync(\n\t\t\tconfigPath,\n\t\t\t`import { defineConfig } from 'browsecraft';\n\nexport default defineConfig({\n // Browser to use: 'chrome' | 'firefox' | 'edge'\n browser: 'chrome',\n\n // Run tests in headless mode\n headless: true,\n\n // Base URL for page.goto() calls\n // baseURL: 'http://localhost:3000',\n\n // Global timeout for actions (ms)\n timeout: 30_000,\n\n // Take screenshots on failure\n screenshot: 'on-failure',\n});\n`,\n\t\t);\n\t\tconsole.log(' Created browsecraft.config.ts');\n\t} else {\n\t\tconsole.log(' browsecraft.config.ts already exists, skipping');\n\t}\n\n\t// Create example test\n\tconst testsDir = join(cwd, 'tests');\n\tif (!existsSync(testsDir)) {\n\t\tmkdirSync(testsDir, { recursive: true });\n\t}\n\n\tconst exampleTest = join(testsDir, 'example.test.ts');\n\tif (!existsSync(exampleTest)) {\n\t\twriteFileSync(\n\t\t\texampleTest,\n\t\t\t`import { test, expect } from 'browsecraft';\n\ntest('homepage has correct title', async ({ page }) => {\n await page.goto('https://example.com');\n await expect(page).toHaveTitle('Example Domain');\n});\n\ntest('can navigate to more info', async ({ page }) => {\n await page.goto('https://example.com');\n await page.click('More information');\n await expect(page).toHaveURL(/iana\\\\.org/);\n});\n`,\n\t\t);\n\t\tconsole.log(' Created tests/example.test.ts');\n\t} else {\n\t\tconsole.log(' tests/example.test.ts already exists, skipping');\n\t}\n\n\t// Add .browsecraft to .gitignore\n\tconst gitignorePath = join(cwd, '.gitignore');\n\tif (existsSync(gitignorePath)) {\n\t\tconst content = await import('node:fs').then((fs) => fs.readFileSync(gitignorePath, 'utf-8'));\n\t\tif (!content.includes('.browsecraft')) {\n\t\t\twriteFileSync(gitignorePath, `${content.trimEnd()}\\n\\n# Browsecraft\\n.browsecraft/\\n`);\n\t\t\tconsole.log(' Updated .gitignore');\n\t\t}\n\t}\n\n\tconsole.log('\\n Setup complete! Run your first test:\\n');\n\tconsole.log(' npx browsecraft test\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Setup IDE — configures VS Code for Cucumber/Gherkin step discovery\n// ---------------------------------------------------------------------------\n\nasync function setupIde() {\n\tconst cwd = process.cwd();\n\n\tconsole.log('\\n Browsecraft — IDE Setup\\n');\n\tconsole.log(' Configuring VS Code for Cucumber/Gherkin step discovery...\\n');\n\n\t// Detect steps directory\n\tconst stepsDir = existsSync(join(cwd, 'steps'))\n\t\t? 'steps'\n\t\t: existsSync(join(cwd, 'step-definitions'))\n\t\t\t? 'step-definitions'\n\t\t\t: existsSync(join(cwd, 'step_definitions'))\n\t\t\t\t? 'step_definitions'\n\t\t\t\t: 'steps';\n\n\t// Detect features directory\n\tconst featuresDir = existsSync(join(cwd, 'features'))\n\t\t? 'features'\n\t\t: existsSync(join(cwd, 'test/features'))\n\t\t\t? 'test/features'\n\t\t\t: 'features';\n\n\t// Resolve the browsecraft-bdd glue path\n\tlet gluePath = 'node_modules/browsecraft-bdd/glue/steps.js';\n\ttry {\n\t\tconst { createRequire } = await import('node:module');\n\t\tconst userRequire = createRequire(join(cwd, 'package.json'));\n\t\tconst bddPkgPath = userRequire.resolve('browsecraft-bdd/package.json');\n\t\tconst bddDir = join(bddPkgPath, '..');\n\t\tconst relGlue = relative(cwd, join(bddDir, 'glue', 'steps.js')).replace(/\\\\/g, '/');\n\t\tif (existsSync(join(bddDir, 'glue', 'steps.js'))) {\n\t\t\tgluePath = relGlue;\n\t\t}\n\t} catch {\n\t\t// browsecraft-bdd not installed yet — use default path\n\t}\n\n\t// Create .vscode directory\n\tconst vscodeDir = join(cwd, '.vscode');\n\tif (!existsSync(vscodeDir)) {\n\t\tmkdirSync(vscodeDir, { recursive: true });\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/');\n\t}\n\n\t// Write or merge settings.json\n\tconst settingsPath = join(vscodeDir, 'settings.json');\n\tconst cucumberSettings: Record<string, unknown> = {\n\t\t'cucumberautocomplete.steps': [`${stepsDir}/**/*.ts`, `${stepsDir}/**/*.js`, gluePath],\n\t\t'cucumberautocomplete.strictGherkinCompletion': true,\n\t\t'cucumberautocomplete.strictGherkinValidation': true,\n\t\t'cucumber.glue': [`${stepsDir}/**/*.ts`, `${stepsDir}/**/*.js`, gluePath],\n\t\t'cucumber.features': [`${featuresDir}/**/*.feature`],\n\t};\n\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst existing = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n\t\t\tlet updated = false;\n\t\t\tfor (const [key, value] of Object.entries(cucumberSettings)) {\n\t\t\t\tif (!(key in existing)) {\n\t\t\t\t\texisting[key] = value;\n\t\t\t\t\tupdated = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updated) {\n\t\t\t\twriteFileSync(settingsPath, `${JSON.stringify(existing, null, 2)}\\n`, 'utf-8');\n\t\t\t\tconsole.log(' \\x1b[32mupdate\\x1b[0m .vscode/settings.json');\n\t\t\t} else {\n\t\t\t\tconsole.log(\n\t\t\t\t\t' \\x1b[33mskip\\x1b[0m .vscode/settings.json \\x1b[2m(already configured)\\x1b[0m',\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\twriteFileSync(settingsPath, `${JSON.stringify(cucumberSettings, null, 2)}\\n`, 'utf-8');\n\t\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/settings.json');\n\t\t}\n\t} else {\n\t\twriteFileSync(settingsPath, `${JSON.stringify(cucumberSettings, null, 2)}\\n`, 'utf-8');\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/settings.json');\n\t}\n\n\t// Write or merge extensions.json\n\tconst extensionsPath = join(vscodeDir, 'extensions.json');\n\tconst recommendedExtensions = [\n\t\t'alexkrechik.cucumberautocomplete',\n\t\t'CucumberOpen.cucumber-official',\n\t];\n\n\tif (existsSync(extensionsPath)) {\n\t\ttry {\n\t\t\tconst existing = JSON.parse(readFileSync(extensionsPath, 'utf-8'));\n\t\t\tconst recs: string[] = existing.recommendations ?? [];\n\t\t\tlet updated = false;\n\t\t\tfor (const ext of recommendedExtensions) {\n\t\t\t\tif (!recs.includes(ext)) {\n\t\t\t\t\trecs.push(ext);\n\t\t\t\t\tupdated = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updated) {\n\t\t\t\texisting.recommendations = recs;\n\t\t\t\twriteFileSync(extensionsPath, `${JSON.stringify(existing, null, 2)}\\n`, 'utf-8');\n\t\t\t\tconsole.log(' \\x1b[32mupdate\\x1b[0m .vscode/extensions.json');\n\t\t\t} else {\n\t\t\t\tconsole.log(\n\t\t\t\t\t' \\x1b[33mskip\\x1b[0m .vscode/extensions.json \\x1b[2m(already configured)\\x1b[0m',\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\twriteFileSync(\n\t\t\t\textensionsPath,\n\t\t\t\t`${JSON.stringify({ recommendations: recommendedExtensions }, null, 2)}\\n`,\n\t\t\t\t'utf-8',\n\t\t\t);\n\t\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/extensions.json');\n\t\t}\n\t} else {\n\t\twriteFileSync(\n\t\t\textensionsPath,\n\t\t\t`${JSON.stringify({ recommendations: recommendedExtensions }, null, 2)}\\n`,\n\t\t\t'utf-8',\n\t\t);\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/extensions.json');\n\t}\n\n\tconsole.log('\\n \\x1b[32mDone!\\x1b[0m IDE configured for Cucumber/Gherkin support.\\n');\n\tconsole.log(' What was set up:');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Cucumber extension discovers your custom steps');\n\tconsole.log(\" \\x1b[36m•\\x1b[0m Cucumber extension discovers BrowseCraft's 38 built-in steps\");\n\tconsole.log(' \\x1b[36m•\\x1b[0m Ctrl+Click navigation from .feature files to step definitions');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Autocomplete suggestions when writing features');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Recommended Cucumber extensions for VS Code');\n\tconsole.log();\n\tconsole.log(' If prompted, install the recommended extensions when VS Code asks.');\n\tconsole.log();\n}\n\n// ---------------------------------------------------------------------------\n// Config Loading\n// ---------------------------------------------------------------------------\n\nasync function loadConfig(): Promise<UserConfig | undefined> {\n\tconst cwd = process.cwd();\n\tconst candidates = [\n\t\t'browsecraft.config.ts',\n\t\t'browsecraft.config.js',\n\t\t'browsecraft.config.mjs',\n\t\t'browsecraft.config.mts',\n\t];\n\n\tfor (const name of candidates) {\n\t\tconst configPath = resolve(cwd, name);\n\t\tif (existsSync(configPath)) {\n\t\t\ttry {\n\t\t\t\t// For .ts files, ensure a TypeScript loader is registered\n\t\t\t\tif (name.endsWith('.ts') || name.endsWith('.mts')) {\n\t\t\t\t\tawait ensureTypeScriptLoader();\n\t\t\t\t}\n\t\t\t\tconst fileUrl = pathToFileURL(configPath).href;\n\t\t\t\tconst mod = await import(fileUrl);\n\t\t\t\treturn mod.default ?? mod;\n\t\t\t} catch {\n\t\t\t\t// Config file exists but couldn't be loaded -- continue with defaults\n\t\t\t\tconsole.warn(`Warning: Could not load ${name}. Using defaults.`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\n// ---------------------------------------------------------------------------\n// TypeScript Loader\n// ---------------------------------------------------------------------------\n\nlet tsLoaderRegistered = false;\n\n/**\n * Ensure a TypeScript loader is registered so that .ts test files can be imported.\n * Tries tsx first (fastest), then ts-node, then falls back to a helpful error.\n *\n * Resolution note: tsx is installed in the USER's project, not in browsecraft itself.\n * We must resolve it from the user's cwd using createRequire, not from our package.\n */\nasync function ensureTypeScriptLoader(): Promise<void> {\n\tif (tsLoaderRegistered) return;\n\n\t// Check if we're already running under a TS loader (e.g., `tsx`, `ts-node`, `bun`)\n\t// In that case, .ts imports already work\n\tconst execArgs = process.execArgv.join(' ');\n\tif (\n\t\texecArgs.includes('tsx') ||\n\t\texecArgs.includes('ts-node') ||\n\t\texecArgs.includes('loader') ||\n\t\tprocess.versions.bun // Bun handles TS natively\n\t) {\n\t\ttsLoaderRegistered = true;\n\t\treturn;\n\t}\n\n\t// Create a require function rooted at the user's cwd so we can find tsx/ts-node\n\t// installed in the user's project (not in our package)\n\tconst { createRequire } = await import('node:module');\n\tconst userRequire = createRequire(pathToFileURL(resolve(process.cwd(), 'package.json')));\n\n\t// Strategy 1: tsx 4.x — use the tsx/esm/api register() function\n\t// This is the modern approach that works with tsx 4.x+\n\ttry {\n\t\tconst tsxApiPath = userRequire.resolve('tsx/esm/api');\n\t\tconst { register } = await import(pathToFileURL(tsxApiPath).href);\n\t\tif (typeof register === 'function') {\n\t\t\tregister();\n\t\t\ttsLoaderRegistered = true;\n\t\t\treturn;\n\t\t}\n\t} catch {\n\t\t// tsx/esm/api not available, try next strategy\n\t}\n\n\t// Strategy 2: Older tsx/ts-node — use Node.js module.register()\n\t// Works with tsx <4.x and ts-node\n\tfor (const loader of ['tsx/esm', 'ts-node/esm']) {\n\t\ttry {\n\t\t\tconst { register } = await import('node:module');\n\t\t\tif (typeof register === 'function') {\n\t\t\t\t// Resolve from user's project root so the loader is found\n\t\t\t\tregister(loader, pathToFileURL(resolve(process.cwd(), '/')));\n\t\t\t\ttsLoaderRegistered = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Loader not available, try next\n\t\t}\n\t}\n\n\t// If neither tsx nor ts-node is available, give a helpful error\n\tconsole.error(\n\t\t'\\n Error: Cannot import TypeScript test files.\\n' +\n\t\t\t' Install tsx (recommended) or ts-node:\\n\\n' +\n\t\t\t' npm install -D tsx\\n\\n' +\n\t\t\t' Or run browsecraft with tsx:\\n\\n' +\n\t\t\t' npx tsx node_modules/.bin/browsecraft test\\n',\n\t);\n\tprocess.exit(1);\n}\n\n// ---------------------------------------------------------------------------\n// Flag parsing\n// ---------------------------------------------------------------------------\n\ninterface CLIFlags {\n\theaded?: boolean;\n\theadless?: boolean;\n\tbrowser?: string;\n\tworkers?: number;\n\ttimeout?: number;\n\tretries?: number;\n\tgrep?: string;\n\tbail?: boolean;\n\tdebug?: boolean;\n\tbdd?: boolean;\n\t/** BDD tag filter expression, e.g. \"@smoke and not @wip\" */\n\ttag?: string;\n\t/** Execution strategy: parallel, sequential, or matrix */\n\tstrategy?: string;\n\t/** BDD scenario name filter (alias for --grep in BDD mode) */\n\tscenario?: string;\n}\n\nfunction parseFlags(args: string[]): CLIFlags {\n\tconst flags: CLIFlags = {};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tswitch (arg) {\n\t\t\tcase '--headed':\n\t\t\t\tflags.headed = true;\n\t\t\t\tbreak;\n\t\t\tcase '--headless':\n\t\t\t\tflags.headless = true;\n\t\t\t\tbreak;\n\t\t\tcase '--debug':\n\t\t\t\tflags.debug = true;\n\t\t\t\tbreak;\n\t\t\tcase '--bdd':\n\t\t\t\tflags.bdd = true;\n\t\t\t\tbreak;\n\t\t\tcase '--bail':\n\t\t\t\tflags.bail = true;\n\t\t\t\tbreak;\n\t\t\tcase '--browser':\n\t\t\t\tflags.browser = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--workers':\n\t\t\t\tflags.workers = Number.parseInt(args[++i] ?? '1', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--timeout':\n\t\t\t\tflags.timeout = Number.parseInt(args[++i] ?? '30000', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--retries':\n\t\t\t\tflags.retries = Number.parseInt(args[++i] ?? '0', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--grep':\n\t\t\tcase '-g':\n\t\t\t\tflags.grep = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--tag':\n\t\t\tcase '--tags':\n\t\t\t\tflags.tag = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--strategy':\n\t\t\t\tflags.strategy = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--scenario':\n\t\t\t\tflags.scenario = args[++i];\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn flags;\n}\n\n// ---------------------------------------------------------------------------\n// Help\n// ---------------------------------------------------------------------------\n\nfunction printHelp() {\n\tconsole.log(`\n browsecraft v${VERSION} -- AI-native browser testing\n\n Usage:\n browsecraft test [files...] [options]\n browsecraft test --bdd [features...] [options]\n browsecraft init\n browsecraft setup-ide\n\n Commands:\n test Run browser tests\n test --bdd Run BDD feature files (Gherkin)\n init Create a new project with example config and test\n setup-ide Configure VS Code for Cucumber step discovery\n\n Options:\n --bdd Run BDD feature files instead of programmatic tests\n --browser <names> Browser(s) to use: chrome,firefox,edge (comma-separated)\n --headed Run in headed mode (show the browser)\n --headless Run in headless mode (default)\n --workers <n> Parallel workers — features run concurrently (default: 1)\n --timeout <ms> Global timeout in milliseconds (default: 30000)\n --retries <n> Retry failed tests n times (default: 0)\n --grep <pattern> Only run tests/scenarios matching pattern\n --scenario <name> Run only scenarios whose name contains <name>\n --tag <expr> BDD tag filter: \"@smoke\", \"@smoke and not @wip\"\n --strategy <s> Multi-browser strategy: parallel, sequential, matrix\n --bail Stop after first failure\n --debug Enable verbose debug logging\n -h, --help Show this help message\n -v, --version Show version\n\n BDD Examples:\n browsecraft test --bdd # All features, 1 browser\n browsecraft test --bdd features/login.feature # Single feature\n browsecraft test --bdd features/login.feature:15 # Specific scenario by line\n browsecraft test --bdd --scenario \"Valid login\" # Specific scenario by name\n browsecraft test --bdd --tag \"@smoke\" # Tag filter\n browsecraft test --bdd --grep \"checkout\" # Name filter\n browsecraft test --bdd --workers 4 # 4 features in parallel\n browsecraft test --bdd --browser chrome,firefox # Multi-browser\n browsecraft test --bdd --browser chrome,firefox,edge --strategy matrix\n browsecraft test --bdd --headed --browser firefox # Headed mode\n\n Programmatic Examples:\n browsecraft test # Run all tests\n browsecraft test tests/login.test.ts # Run specific file\n browsecraft test --headed --browser firefox\n browsecraft test --grep \"login\" --bail\n browsecraft setup-ide # Auto-configure IDE for BDD\n`);\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\nmain().catch((err) => {\n\tconsole.error('Fatal error:', err.message);\n\tprocess.exit(1);\n});\n"]}
1
+ {"version":3,"sources":["../src/cli.ts"],"names":["allFeatures"],"mappings":"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","file":"cli.js","sourcesContent":["#!/usr/bin/env node\n// ============================================================================\n// Browsecraft - CLI\n// The command-line interface for running tests and initializing projects.\n//\n// npx browsecraft test # Run all tests\n// npx browsecraft test login.test.ts # Run specific file\n// npx browsecraft bdd # Run BDD feature files\n// npx browsecraft bdd login.feature # Run specific feature\n// npx browsecraft init # Scaffold a new project\n// npx browsecraft --help # Show help\n// ============================================================================\n\nimport { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';\nimport { join, relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { BrowserName } from 'browsecraft-bidi';\nimport { type RunnableTest, type RunnerOptions, TestRunner } from 'browsecraft-runner';\nimport { Browser } from './browser.js';\nimport { type UserConfig, resolveConfig } from './config.js';\nimport { type TestCase, runAfterAllHooks, runTest, testRegistry } from './test.js';\n\nconst VERSION = '0.3.0';\n\nasync function main() {\n\tconst args = process.argv.slice(2);\n\n\tif (args.length === 0 || args.includes('--help') || args.includes('-h')) {\n\t\tprintHelp();\n\t\treturn;\n\t}\n\n\tif (args.includes('--version') || args.includes('-v')) {\n\t\tconsole.log(`browsecraft v${VERSION}`);\n\t\treturn;\n\t}\n\n\tconst command = args[0];\n\n\tswitch (command) {\n\t\tcase 'test':\n\t\t\tawait runTests(args.slice(1));\n\t\t\tbreak;\n\t\tcase 'bdd':\n\t\t\t// \"browsecraft bdd\" is shorthand for \"browsecraft test --bdd\"\n\t\t\tawait runTests(['--bdd', ...args.slice(1)]);\n\t\t\tbreak;\n\t\tcase 'init':\n\t\t\tawait initProject();\n\t\t\tbreak;\n\t\tcase 'setup-ide':\n\t\t\tawait setupIde();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t// If no command, infer from file extension\n\t\t\tif (command?.endsWith('.feature')) {\n\t\t\t\tawait runTests(['--bdd', ...args]);\n\t\t\t} else if (command?.endsWith('.ts') || command?.endsWith('.js')) {\n\t\t\t\tawait runTests(args);\n\t\t\t} else {\n\t\t\t\tconsole.error(`Unknown command: ${command}`);\n\t\t\t\tconsole.error('Run \"browsecraft --help\" for usage information.');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Test Command\n// ---------------------------------------------------------------------------\n\nasync function runTests(args: string[]) {\n\t// Parse CLI flags\n\tconst flags = parseFlags(args);\n\tconst filePatterns = args.filter((a) => !a.startsWith('--'));\n\n\t// Load config file if it exists\n\tconst userConfig = await loadConfig();\n\tconst config = resolveConfig(userConfig);\n\n\t// Apply CLI overrides\n\tif (flags.headed || flags.headless === false) {\n\t\tconfig.headless = false;\n\t}\n\tif (flags.browser) {\n\t\tconfig.browser = flags.browser as BrowserName;\n\t}\n\tif (flags.workers !== undefined) {\n\t\tconfig.workers = flags.workers;\n\t}\n\tif (flags.timeout !== undefined) {\n\t\tconfig.timeout = flags.timeout;\n\t}\n\tif (flags.retries !== undefined) {\n\t\tconfig.retries = flags.retries;\n\t}\n\tif (flags.debug) {\n\t\tconfig.debug = true;\n\t}\n\n\t// BDD mode: run .feature files with step definitions\n\tif (flags.bdd) {\n\t\tawait runBddTests(config, userConfig, flags, filePatterns);\n\t\treturn;\n\t}\n\n\t// Set up runner options\n\tconst runnerOptions: RunnerOptions = {\n\t\tconfig,\n\t\tfiles: filePatterns.length > 0 ? filePatterns : undefined,\n\t\tgrep: flags.grep,\n\t\tbail: flags.bail,\n\t};\n\n\t// Run tests\n\tconst runner = new TestRunner(runnerOptions);\n\n\t// loadFile callback: imports the test file and returns registered tests\n\tconst loadFile = async (file: string): Promise<RunnableTest[]> => {\n\t\tconst startIdx = testRegistry.length;\n\n\t\t// For TypeScript files, register a TypeScript loader if available\n\t\tif (file.endsWith('.ts') || file.endsWith('.mts')) {\n\t\t\tawait ensureTypeScriptLoader();\n\t\t}\n\n\t\tconst fileUrl = pathToFileURL(file).href;\n\t\tawait import(fileUrl);\n\t\treturn testRegistry.slice(startIdx).map((tc) => ({\n\t\t\ttitle: tc.title,\n\t\t\tsuitePath: tc.suitePath,\n\t\t\tskip: tc.skip,\n\t\t\tonly: tc.only,\n\t\t\toptions: tc.options,\n\t\t\tfn: tc.fn as (fixtures: unknown) => Promise<void>,\n\t\t}));\n\t};\n\n\t// Launch a shared browser for all tests\n\tlet sharedBrowser: Browser | undefined;\n\n\ttry {\n\t\tsharedBrowser = await Browser.launch({\n\t\t\tbrowser: config.browser,\n\t\t\theadless: config.headless,\n\t\t\texecutablePath: config.executablePath,\n\t\t\tdebug: config.debug,\n\t\t\ttimeout: config.timeout,\n\t\t});\n\t} catch (err) {\n\t\tconsole.error(`Failed to launch browser: ${err instanceof Error ? err.message : String(err)}`);\n\t\tprocess.exit(1);\n\t}\n\n\t// executeTest callback: runs a single test with fixture setup/teardown\n\tconst executeTest = async (test: RunnableTest) => {\n\t\treturn runTest(test as unknown as TestCase, sharedBrowser);\n\t};\n\n\ttry {\n\t\tconst exitCode = await runner.run(loadFile, executeTest);\n\t\tawait sharedBrowser.close().catch(() => {});\n\t\tprocess.exit(exitCode);\n\t} catch (err) {\n\t\tawait sharedBrowser?.close().catch(() => {});\n\t\tthrow err;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// BDD Command — runs .feature files with step definitions\n//\n// Supports:\n// - Single / multiple feature files: browsecraft test --bdd login.feature\n// - Tag filtering: --tag \"@smoke and not @wip\"\n// - Name filtering: --grep \"login\"\n// - Multi-browser: --browser chrome,firefox\n// - Parallel: --workers 4\n// - Strategy: --strategy parallel|sequential|matrix\n// ---------------------------------------------------------------------------\n\ntype BddModule = typeof import('browsecraft-bdd');\n\nasync function runBddTests(\n\tconfig: ReturnType<typeof resolveConfig>,\n\tuserConfig?: UserConfig,\n\tflags?: CLIFlags,\n\tfilePatterns?: string[],\n): Promise<void> {\n\tconst bddModule = (await import('browsecraft-bdd')) as BddModule;\n\tconst { parseGherkin, BddExecutor, registerBuiltInSteps, After, computeSummary } = bddModule;\n\tconst cwd = process.cwd();\n\n\t// ── Resolve options from config + CLI flags ────────────────────────\n\tconst bddConfig = userConfig?.bdd ?? {};\n\tconst featuresPattern = bddConfig.features ?? 'features/**/*.feature';\n\tconst stepsPattern = bddConfig.steps ?? 'steps/**/*.{ts,js,mts,mjs}';\n\tconst useBuiltInSteps = bddConfig.builtInSteps !== false;\n\n\t// Browsers: --browser chrome,firefox or config.browsers or [config.browser]\n\tconst browserNames: string[] = flags?.browser\n\t\t? flags.browser.split(',').map((b) => b.trim())\n\t\t: (config.browsers ?? [config.browser]);\n\n\t// Workers per browser (for parallel feature execution)\n\tconst workers = flags?.workers ?? (browserNames.length > 1 ? 1 : 1);\n\n\t// Strategy: --strategy or config.strategy\n\tconst strategy = (flags?.strategy ?? config.strategy ?? 'sequential') as\n\t\t| 'parallel'\n\t\t| 'sequential'\n\t\t| 'matrix';\n\n\t// Tag filter: --tag or bddConfig.tagFilter\n\tconst tagFilter = flags?.tag ?? bddConfig.tagFilter;\n\n\t// Grep: --grep or --scenario or bddConfig.grep\n\tconst grepPattern = flags?.scenario ?? flags?.grep ?? bddConfig.grep;\n\n\t// Fail fast: --bail\n\tconst failFast = flags?.bail ?? false;\n\n\t// ── Step 1: Discover .feature files ────────────────────────────────\n\t// Parse feature:line syntax (e.g. features/login.feature:15)\n\tconst targetLines = new Map<string, number[]>(); // file → line numbers\n\tlet featureFiles: string[];\n\n\tif (filePatterns && filePatterns.length > 0) {\n\t\t// Explicit feature files from CLI positional args\n\t\tconst resolvedPaths: string[] = [];\n\t\tfor (const pattern of filePatterns) {\n\t\t\tconst [filePart, linePart] = pattern.split(':');\n\t\t\tconst absPath = resolve(cwd, filePart!);\n\t\t\tif (!existsSync(absPath)) continue;\n\n\t\t\tif (!resolvedPaths.includes(absPath)) {\n\t\t\t\tresolvedPaths.push(absPath);\n\t\t\t}\n\t\t\tif (linePart) {\n\t\t\t\tconst lineNum = Number.parseInt(linePart, 10);\n\t\t\t\tif (!Number.isNaN(lineNum)) {\n\t\t\t\t\tconst existing = targetLines.get(absPath) ?? [];\n\t\t\t\t\texisting.push(lineNum);\n\t\t\t\t\ttargetLines.set(absPath, existing);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfeatureFiles = resolvedPaths;\n\t\tif (featureFiles.length === 0) {\n\t\t\tconsole.error('\\n No matching feature files found.\\n');\n\t\t\tprocess.exit(1);\n\t\t}\n\t} else {\n\t\tfeatureFiles = discoverFiles(cwd, featuresPattern, ['.feature']);\n\t}\n\n\tif (featureFiles.length === 0) {\n\t\tconsole.log('\\n No .feature files found.\\n');\n\t\tconsole.log(` Feature pattern: ${featuresPattern}`);\n\t\tconsole.log(' Create features/*.feature files or adjust bdd.features in your config.\\n');\n\t\tprocess.exit(0);\n\t}\n\n\t// ── Step 2: Register steps ─────────────────────────────────────────\n\tif (useBuiltInSteps) {\n\t\tregisterBuiltInSteps();\n\t}\n\n\tconst stepFiles = discoverFiles(cwd, stepsPattern, ['.ts', '.js', '.mts', '.mjs']);\n\tfor (const stepFile of stepFiles) {\n\t\tif (stepFile.endsWith('.ts') || stepFile.endsWith('.mts')) {\n\t\t\tawait ensureTypeScriptLoader();\n\t\t}\n\t\tconst fileUrl = pathToFileURL(stepFile).href;\n\t\tawait import(fileUrl);\n\t}\n\n\t// Cleanup hook for browser contexts\n\tAfter(async ({ world }) => {\n\t\tconst w = world as unknown as Record<string, { close(): Promise<unknown> } | undefined>;\n\t\tif (w?._context) {\n\t\t\tawait w._context.close().catch(() => {});\n\t\t}\n\t});\n\n\t// ── Step 3: Parse .feature files ───────────────────────────────────\n\tconst documents = featureFiles.map((file) => {\n\t\tconst source = readFileSync(file, 'utf-8');\n\t\treturn parseGherkin(source, relative(cwd, file));\n\t});\n\n\t// Build a scenario filter for line-number targeting\n\tconst lineFilter =\n\t\ttargetLines.size > 0\n\t\t\t? (scenario: { line: number; name: string }, _tags: string[], uri?: string) => {\n\t\t\t\t\tfor (const [file, lines] of targetLines) {\n\t\t\t\t\t\tconst relPath = relative(cwd, file);\n\t\t\t\t\t\tif (uri === relPath || uri === file) {\n\t\t\t\t\t\t\treturn lines.includes(scenario.line);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true; // no line constraint for this file\n\t\t\t\t}\n\t\t\t: undefined;\n\n\t// ── Step 4: Determine execution plan ───────────────────────────────\n\tconst isMultiBrowser = browserNames.length > 1;\n\tconst isParallel = workers > 1;\n\n\t// Header\n\tconst parts: string[] = [\n\t\t`${featureFiles.length} feature file${featureFiles.length > 1 ? 's' : ''}`,\n\t];\n\tif (isMultiBrowser) parts.push(`on ${browserNames.join(', ')}`);\n\tif (isParallel) parts.push(`(${workers} workers)`);\n\tif (tagFilter) parts.push(`[tags: ${tagFilter}]`);\n\tif (grepPattern) parts.push(`[grep: ${grepPattern}]`);\n\tif (targetLines.size > 0) {\n\t\tconst lineDescs = [...targetLines.entries()].map(\n\t\t\t([f, ls]) => `${relative(cwd, f)}:${ls.join(',')}`,\n\t\t);\n\t\tparts.push(`[lines: ${lineDescs.join(' ')}]`);\n\t}\n\n\tconsole.log(`\\n Browsecraft BDD - Running ${parts.join(' ')}\\n`);\n\n\tif (isMultiBrowser) {\n\t\tconsole.log(` Strategy: ${strategy}`);\n\t\tconsole.log(\n\t\t\t` Browsers: ${browserNames.map((b) => b.charAt(0).toUpperCase() + b.slice(1)).join(', ')}`,\n\t\t);\n\t\tconsole.log('');\n\t}\n\n\t// ── Step 5: Execute ────────────────────────────────────────────────\n\ttype FeatureResultType = Awaited<\n\t\tReturnType<InstanceType<typeof BddExecutor>['run']>\n\t>['features'][number];\n\n\t/**\n\t * Run a set of documents on a specific browser.\n\t * Returns the feature results and the launched browser instance.\n\t */\n\tconst runOnBrowser = async (\n\t\tbrowserName: string,\n\t\tdocs: ReturnType<typeof parseGherkin>[],\n\t\tprefix: string,\n\t): Promise<{ features: FeatureResultType[]; duration: number; browser: Browser }> => {\n\t\tconst browser = await Browser.launch({\n\t\t\tbrowser: browserName as BrowserName,\n\t\t\theadless: config.headless,\n\t\t\texecutablePath: config.executablePath,\n\t\t\tdebug: config.debug,\n\t\t\ttimeout: config.timeout,\n\t\t});\n\n\t\tconst createExecutor = (docSubset: ReturnType<typeof parseGherkin>[]) =>\n\t\t\tnew BddExecutor({\n\t\t\t\tstepTimeout: config.timeout,\n\t\t\t\ttagFilter: tagFilter ?? undefined,\n\t\t\t\tgrep: grepPattern ?? undefined,\n\t\t\t\tscenarioFilter: lineFilter ?? undefined,\n\t\t\t\tfailFast,\n\t\t\t\tworldFactory: async () => {\n\t\t\t\t\tconst context = await browser.newContext();\n\t\t\t\t\tconst page = await context.newPage();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpage,\n\t\t\t\t\t\tbrowser,\n\t\t\t\t\t\tctx: {},\n\t\t\t\t\t\tattach: () => {},\n\t\t\t\t\t\tlog: (msg: string) => console.log(` ${prefix}${msg}`),\n\t\t\t\t\t\t_context: context,\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\tonFeatureStart: (feature) => {\n\t\t\t\t\tconsole.log(`\\n ${prefix}Feature: ${feature.name}`);\n\t\t\t\t},\n\t\t\t\tonScenarioStart: (scenario) => {\n\t\t\t\t\tconsole.log(` ${prefix}Scenario: ${scenario.name}`);\n\t\t\t\t},\n\t\t\t\tonStepEnd: (result) => {\n\t\t\t\t\tconst icon =\n\t\t\t\t\t\tresult.status === 'passed'\n\t\t\t\t\t\t\t? '\\x1b[32m+\\x1b[0m'\n\t\t\t\t\t\t\t: result.status === 'failed'\n\t\t\t\t\t\t\t\t? '\\x1b[31mx\\x1b[0m'\n\t\t\t\t\t\t\t\t: result.status === 'undefined'\n\t\t\t\t\t\t\t\t\t? '\\x1b[33m?\\x1b[0m'\n\t\t\t\t\t\t\t\t\t: result.status === 'pending'\n\t\t\t\t\t\t\t\t\t\t? '\\x1b[33m-\\x1b[0m'\n\t\t\t\t\t\t\t\t\t\t: '\\x1b[90m-\\x1b[0m';\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t` ${prefix}${icon} ${result.keyword.trim()} ${result.text} (${result.duration}ms)`,\n\t\t\t\t\t);\n\t\t\t\t\tif (result.status === 'failed' && result.error) {\n\t\t\t\t\t\tconsole.log(` ${prefix}${result.error.message}`);\n\t\t\t\t\t}\n\t\t\t\t\tif (result.status === 'undefined') {\n\t\t\t\t\t\tconsole.log(` ${prefix}Step not defined. Add it to your step definitions.`);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonScenarioEnd: (result) => {\n\t\t\t\t\t// Print hookError when worldFactory or hooks fail (0 steps executed)\n\t\t\t\t\tif (result.hookError) {\n\t\t\t\t\t\tconsole.log(` ${prefix}\\x1b[31m✗ ${result.hookError.message}\\x1b[0m`);\n\t\t\t\t\t}\n\t\t\t\t\t// Show scenario-level failure summary when steps ran but some failed\n\t\t\t\t\tif (result.status === 'failed' && !result.hookError && result.steps.length === 0) {\n\t\t\t\t\t\tconsole.log(` ${prefix}\\x1b[31m✗ Scenario failed with no steps executed\\x1b[0m`);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\n\t\tlet allFeatures: FeatureResultType[] = [];\n\t\tconst start = Date.now();\n\n\t\tif (workers > 1 && docs.length > 1) {\n\t\t\t// Parallel: split documents into worker chunks\n\t\t\tconst chunks = splitIntoChunks(docs, workers);\n\t\t\tconst results = await Promise.all(\n\t\t\t\tchunks.map((chunk) => {\n\t\t\t\t\tconst exec = createExecutor(chunk);\n\t\t\t\t\treturn exec.run(chunk);\n\t\t\t\t}),\n\t\t\t);\n\t\t\tallFeatures = results.flatMap((r) => r.features);\n\t\t} else {\n\t\t\t// Sequential: single executor\n\t\t\tconst exec = createExecutor(docs);\n\t\t\tconst result = await exec.run(docs);\n\t\t\tallFeatures = result.features;\n\t\t}\n\n\t\treturn { features: allFeatures, duration: Date.now() - start, browser };\n\t};\n\n\t// ── Execute according to strategy ──────────────────────────────────\n\tconst browsers: Browser[] = [];\n\tlet allFeatures: FeatureResultType[] = [];\n\tlet totalDuration = 0;\n\tconst perBrowserResults: Array<{\n\t\tbrowserName: string;\n\t\tfeatures: FeatureResultType[];\n\t\tduration: number;\n\t}> = [];\n\n\ttry {\n\t\tif (!isMultiBrowser) {\n\t\t\t// Single browser — simple path\n\t\t\tconst { features, duration, browser } = await runOnBrowser(browserNames[0]!, documents, '');\n\t\t\tbrowsers.push(browser);\n\t\t\tallFeatures = features;\n\t\t\ttotalDuration = duration;\n\t\t\tperBrowserResults.push({ browserName: browserNames[0]!, features, duration });\n\t\t} else if (strategy === 'sequential') {\n\t\t\t// Sequential: one browser at a time, each runs all features\n\t\t\tfor (const bName of browserNames) {\n\t\t\t\tconst prefix = `\\x1b[36m[${bName}]\\x1b[0m `;\n\t\t\t\tconst { features, duration, browser } = await runOnBrowser(bName, documents, prefix);\n\t\t\t\tbrowsers.push(browser);\n\t\t\t\tallFeatures.push(...features);\n\t\t\t\ttotalDuration += duration;\n\t\t\t\tperBrowserResults.push({ browserName: bName, features, duration });\n\t\t\t}\n\t\t} else {\n\t\t\t// Parallel or Matrix: all browsers simultaneously\n\t\t\t// (matrix = every feature on every browser; parallel = same as matrix for distinct browsers)\n\t\t\tconst results = await Promise.all(\n\t\t\t\tbrowserNames.map((bName) => {\n\t\t\t\t\tconst prefix = `\\x1b[36m[${bName}]\\x1b[0m `;\n\t\t\t\t\treturn runOnBrowser(bName, documents, prefix);\n\t\t\t\t}),\n\t\t\t);\n\t\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\t\tconst r = results[i]!;\n\t\t\t\tbrowsers.push(r.browser);\n\t\t\t\tallFeatures.push(...r.features);\n\t\t\t\tperBrowserResults.push({\n\t\t\t\t\tbrowserName: browserNames[i]!,\n\t\t\t\t\tfeatures: r.features,\n\t\t\t\t\tduration: r.duration,\n\t\t\t\t});\n\t\t\t}\n\t\t\ttotalDuration = Math.max(...results.map((r) => r.duration));\n\t\t}\n\n\t\t// ── Print summary ──────────────────────────────────────────────\n\t\tconst summary = computeSummary(allFeatures);\n\t\tconsole.log('\\n ─────────────────────────────────────');\n\n\t\t// Per-browser breakdown for multi-browser runs\n\t\tif (isMultiBrowser) {\n\t\t\tfor (const br of perBrowserResults) {\n\t\t\t\tconst brSummary = computeSummary(br.features);\n\t\t\t\tconst brLabel = br.browserName.charAt(0).toUpperCase() + br.browserName.slice(1);\n\t\t\t\tconst brParts: string[] = [];\n\t\t\t\tif (brSummary.scenarios.passed > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[32m${brSummary.scenarios.passed} passed\\x1b[0m`);\n\t\t\t\tif (brSummary.scenarios.failed > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[31m${brSummary.scenarios.failed} failed\\x1b[0m`);\n\t\t\t\tif (brSummary.scenarios.skipped > 0)\n\t\t\t\t\tbrParts.push(`\\x1b[33m${brSummary.scenarios.skipped} skipped\\x1b[0m`);\n\t\t\t\tconsole.log(\n\t\t\t\t\t` ${brLabel.padEnd(10)} ${brParts.join(', ')} (${brSummary.scenarios.total} scenarios) ${br.duration < 1000 ? `${br.duration}ms` : `${(br.duration / 1000).toFixed(1)}s`}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconsole.log(' ─────────────────────────────────────');\n\t\t}\n\n\t\tconst { scenarios, steps } = summary;\n\n\t\tconst scenarioParts: string[] = [];\n\t\tif (scenarios.passed > 0) scenarioParts.push(`\\x1b[32m${scenarios.passed} passed\\x1b[0m`);\n\t\tif (scenarios.failed > 0) scenarioParts.push(`\\x1b[31m${scenarios.failed} failed\\x1b[0m`);\n\t\tif (scenarios.skipped > 0) scenarioParts.push(`\\x1b[33m${scenarios.skipped} skipped\\x1b[0m`);\n\t\tif (scenarios.pending > 0) scenarioParts.push(`\\x1b[33m${scenarios.pending} pending\\x1b[0m`);\n\n\t\tconst stepParts: string[] = [];\n\t\tif (steps.passed > 0) stepParts.push(`\\x1b[32m${steps.passed} passed\\x1b[0m`);\n\t\tif (steps.failed > 0) stepParts.push(`\\x1b[31m${steps.failed} failed\\x1b[0m`);\n\t\tif (steps.undefined > 0) stepParts.push(`\\x1b[33m${steps.undefined} undefined\\x1b[0m`);\n\t\tif (steps.skipped > 0) stepParts.push(`\\x1b[90m${steps.skipped} skipped\\x1b[0m`);\n\n\t\tconsole.log(` Scenarios: ${scenarioParts.join(', ')} (${scenarios.total} total)`);\n\t\tconsole.log(` Steps: ${stepParts.join(', ')} (${steps.total} total)`);\n\t\tconsole.log(\n\t\t\t` Time: ${totalDuration < 1000 ? `${totalDuration}ms` : `${(totalDuration / 1000).toFixed(1)}s`}`,\n\t\t);\n\t\tif (isMultiBrowser) {\n\t\t\tconsole.log(` Strategy: ${strategy}`);\n\t\t}\n\t\tconsole.log('');\n\n\t\tif (scenarios.failed > 0) {\n\t\t\t// List failed scenarios with error details\n\t\t\tconsole.log(' \\x1b[31mFailed scenarios:\\x1b[0m');\n\t\t\tfor (const feat of allFeatures) {\n\t\t\t\tfor (const scen of feat.scenarios) {\n\t\t\t\t\tif (scen.status !== 'failed') continue;\n\t\t\t\t\tconsole.log(` \\x1b[31m✗\\x1b[0m ${feat.name} → ${scen.name}`);\n\t\t\t\t\tif (scen.hookError) {\n\t\t\t\t\t\tconsole.log(` Error: ${scen.hookError.message}`);\n\t\t\t\t\t}\n\t\t\t\t\tfor (const st of scen.steps) {\n\t\t\t\t\t\tif (st.status === 'failed' && st.error) {\n\t\t\t\t\t\t\tconsole.log(` ${st.keyword.trim()} ${st.text}: ${st.error.message}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (st.status === 'undefined') {\n\t\t\t\t\t\t\tconsole.log(` ${st.keyword.trim()} ${st.text}: \\x1b[33mStep not defined\\x1b[0m`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tconsole.log('');\n\t\t} else if (steps.undefined > 0) {\n\t\t\tconsole.log(' \\x1b[33mSome steps are undefined.\\x1b[0m\\n');\n\t\t} else {\n\t\t\tconsole.log(' \\x1b[32mAll scenarios passed!\\x1b[0m\\n');\n\t\t}\n\n\t\t// Clean up all browsers\n\t\tfor (const b of browsers) {\n\t\t\tawait b.close().catch(() => {});\n\t\t}\n\n\t\tprocess.exit(scenarios.failed > 0 || steps.undefined > 0 ? 1 : 0);\n\t} catch (err) {\n\t\tfor (const b of browsers) {\n\t\t\tawait b.close().catch(() => {});\n\t\t}\n\t\tconsole.error(`BDD execution error: ${err instanceof Error ? err.message : String(err)}`);\n\t\tprocess.exit(1);\n\t}\n}\n\n/**\n * Split an array into N roughly-equal chunks.\n * Used for distributing feature files across parallel workers.\n */\nfunction splitIntoChunks<T>(items: T[], n: number): T[][] {\n\tconst chunks: T[][] = [];\n\tconst size = Math.ceil(items.length / n);\n\tfor (let i = 0; i < items.length; i += size) {\n\t\tchunks.push(items.slice(i, i + size));\n\t}\n\treturn chunks;\n}\n\n/**\n * Discover files matching a glob-like pattern within a directory.\n * Supports patterns like 'features/**\\/*.feature' or 'steps/**\\/*.{ts,js}'.\n */\nfunction discoverFiles(rootDir: string, pattern: string, extensions: string[]): string[] {\n\tconst files: string[] = [];\n\n\t// Extract the base directory from the pattern (e.g., 'features' from 'features/**/*.feature')\n\tconst baseParts = pattern.split('/');\n\tlet baseDir = rootDir;\n\tfor (const part of baseParts) {\n\t\tif (part.includes('*') || part.includes('{')) break;\n\t\tbaseDir = join(baseDir, part);\n\t}\n\n\tif (!existsSync(baseDir)) return files;\n\n\tconst walkDir = (dir: string): void => {\n\t\tconst skip = new Set(['node_modules', 'dist', '.browsecraft', '.git', 'coverage', '.turbo']);\n\t\tlet entries: string[];\n\t\ttry {\n\t\t\tentries = readdirSync(dir);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tif (skip.has(entry)) continue;\n\t\t\tconst fullPath = join(dir, entry);\n\t\t\tlet stat: ReturnType<typeof statSync>;\n\t\t\ttry {\n\t\t\t\tstat = statSync(fullPath);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (stat.isDirectory()) {\n\t\t\t\twalkDir(fullPath);\n\t\t\t} else if (stat.isFile()) {\n\t\t\t\tif (extensions.some((ext) => entry.endsWith(ext))) {\n\t\t\t\t\tfiles.push(fullPath);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\twalkDir(baseDir);\n\treturn files.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Init Command\n// ---------------------------------------------------------------------------\n\nasync function initProject() {\n\tconst cwd = process.cwd();\n\n\tconsole.log('\\n Browsecraft - Project Setup\\n');\n\n\t// Create config file\n\tconst configPath = join(cwd, 'browsecraft.config.ts');\n\tif (!existsSync(configPath)) {\n\t\twriteFileSync(\n\t\t\tconfigPath,\n\t\t\t`import { defineConfig } from 'browsecraft';\n\nexport default defineConfig({\n // Browser to use: 'chrome' | 'firefox' | 'edge'\n browser: 'chrome',\n\n // Run tests in headless mode\n headless: true,\n\n // Base URL for page.goto() calls\n // baseURL: 'http://localhost:3000',\n\n // Global timeout for actions (ms)\n timeout: 30_000,\n\n // Take screenshots on failure\n screenshot: 'on-failure',\n});\n`,\n\t\t);\n\t\tconsole.log(' Created browsecraft.config.ts');\n\t} else {\n\t\tconsole.log(' browsecraft.config.ts already exists, skipping');\n\t}\n\n\t// Create example test\n\tconst testsDir = join(cwd, 'tests');\n\tif (!existsSync(testsDir)) {\n\t\tmkdirSync(testsDir, { recursive: true });\n\t}\n\n\tconst exampleTest = join(testsDir, 'example.test.ts');\n\tif (!existsSync(exampleTest)) {\n\t\twriteFileSync(\n\t\t\texampleTest,\n\t\t\t`import { test, expect } from 'browsecraft';\n\ntest('homepage has correct title', async ({ page }) => {\n await page.goto('https://example.com');\n await expect(page).toHaveTitle('Example Domain');\n});\n\ntest('can navigate to more info', async ({ page }) => {\n await page.goto('https://example.com');\n await page.click('More information');\n await expect(page).toHaveURL(/iana\\\\.org/);\n});\n`,\n\t\t);\n\t\tconsole.log(' Created tests/example.test.ts');\n\t} else {\n\t\tconsole.log(' tests/example.test.ts already exists, skipping');\n\t}\n\n\t// Add .browsecraft to .gitignore\n\tconst gitignorePath = join(cwd, '.gitignore');\n\tif (existsSync(gitignorePath)) {\n\t\tconst content = await import('node:fs').then((fs) => fs.readFileSync(gitignorePath, 'utf-8'));\n\t\tif (!content.includes('.browsecraft')) {\n\t\t\twriteFileSync(gitignorePath, `${content.trimEnd()}\\n\\n# Browsecraft\\n.browsecraft/\\n`);\n\t\t\tconsole.log(' Updated .gitignore');\n\t\t}\n\t}\n\n\tconsole.log('\\n Setup complete! Run your first test:\\n');\n\tconsole.log(' npx browsecraft test\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Setup IDE — configures VS Code for Cucumber/Gherkin step discovery\n// ---------------------------------------------------------------------------\n\nasync function setupIde() {\n\tconst cwd = process.cwd();\n\n\tconsole.log('\\n Browsecraft — IDE Setup\\n');\n\tconsole.log(' Configuring VS Code for Cucumber/Gherkin step discovery...\\n');\n\n\t// Detect steps directory\n\tconst stepsDir = existsSync(join(cwd, 'steps'))\n\t\t? 'steps'\n\t\t: existsSync(join(cwd, 'step-definitions'))\n\t\t\t? 'step-definitions'\n\t\t\t: existsSync(join(cwd, 'step_definitions'))\n\t\t\t\t? 'step_definitions'\n\t\t\t\t: 'steps';\n\n\t// Detect features directory\n\tconst featuresDir = existsSync(join(cwd, 'features'))\n\t\t? 'features'\n\t\t: existsSync(join(cwd, 'test/features'))\n\t\t\t? 'test/features'\n\t\t\t: 'features';\n\n\t// Resolve the browsecraft-bdd glue path\n\tlet gluePath = 'node_modules/browsecraft-bdd/glue/steps.js';\n\ttry {\n\t\tconst { createRequire } = await import('node:module');\n\t\tconst userRequire = createRequire(join(cwd, 'package.json'));\n\t\tconst bddPkgPath = userRequire.resolve('browsecraft-bdd/package.json');\n\t\tconst bddDir = join(bddPkgPath, '..');\n\t\tconst relGlue = relative(cwd, join(bddDir, 'glue', 'steps.js')).replace(/\\\\/g, '/');\n\t\tif (existsSync(join(bddDir, 'glue', 'steps.js'))) {\n\t\t\tgluePath = relGlue;\n\t\t}\n\t} catch {\n\t\t// browsecraft-bdd not installed yet — use default path\n\t}\n\n\t// Create .vscode directory\n\tconst vscodeDir = join(cwd, '.vscode');\n\tif (!existsSync(vscodeDir)) {\n\t\tmkdirSync(vscodeDir, { recursive: true });\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/');\n\t}\n\n\t// Write or merge settings.json\n\tconst settingsPath = join(vscodeDir, 'settings.json');\n\tconst cucumberSettings: Record<string, unknown> = {\n\t\t'cucumberautocomplete.steps': [`${stepsDir}/**/*.ts`, `${stepsDir}/**/*.js`, gluePath],\n\t\t'cucumberautocomplete.strictGherkinCompletion': true,\n\t\t'cucumberautocomplete.strictGherkinValidation': true,\n\t\t'cucumber.glue': [`${stepsDir}/**/*.ts`, `${stepsDir}/**/*.js`, gluePath],\n\t\t'cucumber.features': [`${featuresDir}/**/*.feature`],\n\t};\n\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst existing = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n\t\t\tlet updated = false;\n\t\t\tfor (const [key, value] of Object.entries(cucumberSettings)) {\n\t\t\t\tif (!(key in existing)) {\n\t\t\t\t\texisting[key] = value;\n\t\t\t\t\tupdated = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updated) {\n\t\t\t\twriteFileSync(settingsPath, `${JSON.stringify(existing, null, 2)}\\n`, 'utf-8');\n\t\t\t\tconsole.log(' \\x1b[32mupdate\\x1b[0m .vscode/settings.json');\n\t\t\t} else {\n\t\t\t\tconsole.log(\n\t\t\t\t\t' \\x1b[33mskip\\x1b[0m .vscode/settings.json \\x1b[2m(already configured)\\x1b[0m',\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\twriteFileSync(settingsPath, `${JSON.stringify(cucumberSettings, null, 2)}\\n`, 'utf-8');\n\t\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/settings.json');\n\t\t}\n\t} else {\n\t\twriteFileSync(settingsPath, `${JSON.stringify(cucumberSettings, null, 2)}\\n`, 'utf-8');\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/settings.json');\n\t}\n\n\t// Write or merge extensions.json\n\tconst extensionsPath = join(vscodeDir, 'extensions.json');\n\tconst recommendedExtensions = [\n\t\t'alexkrechik.cucumberautocomplete',\n\t\t'CucumberOpen.cucumber-official',\n\t];\n\n\tif (existsSync(extensionsPath)) {\n\t\ttry {\n\t\t\tconst existing = JSON.parse(readFileSync(extensionsPath, 'utf-8'));\n\t\t\tconst recs: string[] = existing.recommendations ?? [];\n\t\t\tlet updated = false;\n\t\t\tfor (const ext of recommendedExtensions) {\n\t\t\t\tif (!recs.includes(ext)) {\n\t\t\t\t\trecs.push(ext);\n\t\t\t\t\tupdated = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updated) {\n\t\t\t\texisting.recommendations = recs;\n\t\t\t\twriteFileSync(extensionsPath, `${JSON.stringify(existing, null, 2)}\\n`, 'utf-8');\n\t\t\t\tconsole.log(' \\x1b[32mupdate\\x1b[0m .vscode/extensions.json');\n\t\t\t} else {\n\t\t\t\tconsole.log(\n\t\t\t\t\t' \\x1b[33mskip\\x1b[0m .vscode/extensions.json \\x1b[2m(already configured)\\x1b[0m',\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\twriteFileSync(\n\t\t\t\textensionsPath,\n\t\t\t\t`${JSON.stringify({ recommendations: recommendedExtensions }, null, 2)}\\n`,\n\t\t\t\t'utf-8',\n\t\t\t);\n\t\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/extensions.json');\n\t\t}\n\t} else {\n\t\twriteFileSync(\n\t\t\textensionsPath,\n\t\t\t`${JSON.stringify({ recommendations: recommendedExtensions }, null, 2)}\\n`,\n\t\t\t'utf-8',\n\t\t);\n\t\tconsole.log(' \\x1b[32mcreate\\x1b[0m .vscode/extensions.json');\n\t}\n\n\tconsole.log('\\n \\x1b[32mDone!\\x1b[0m IDE configured for Cucumber/Gherkin support.\\n');\n\tconsole.log(' What was set up:');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Cucumber extension discovers your custom steps');\n\tconsole.log(\" \\x1b[36m•\\x1b[0m Cucumber extension discovers BrowseCraft's 38 built-in steps\");\n\tconsole.log(' \\x1b[36m•\\x1b[0m Ctrl+Click navigation from .feature files to step definitions');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Autocomplete suggestions when writing features');\n\tconsole.log(' \\x1b[36m•\\x1b[0m Recommended Cucumber extensions for VS Code');\n\tconsole.log();\n\tconsole.log(' If prompted, install the recommended extensions when VS Code asks.');\n\tconsole.log();\n}\n\n// ---------------------------------------------------------------------------\n// Config Loading\n// ---------------------------------------------------------------------------\n\nasync function loadConfig(): Promise<UserConfig | undefined> {\n\tconst cwd = process.cwd();\n\tconst candidates = [\n\t\t'browsecraft.config.ts',\n\t\t'browsecraft.config.js',\n\t\t'browsecraft.config.mjs',\n\t\t'browsecraft.config.mts',\n\t];\n\n\tfor (const name of candidates) {\n\t\tconst configPath = resolve(cwd, name);\n\t\tif (existsSync(configPath)) {\n\t\t\ttry {\n\t\t\t\t// For .ts files, ensure a TypeScript loader is registered\n\t\t\t\tif (name.endsWith('.ts') || name.endsWith('.mts')) {\n\t\t\t\t\tawait ensureTypeScriptLoader();\n\t\t\t\t}\n\t\t\t\tconst fileUrl = pathToFileURL(configPath).href;\n\t\t\t\tconst mod = await import(fileUrl);\n\t\t\t\treturn mod.default ?? mod;\n\t\t\t} catch {\n\t\t\t\t// Config file exists but couldn't be loaded -- continue with defaults\n\t\t\t\tconsole.warn(`Warning: Could not load ${name}. Using defaults.`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\n// ---------------------------------------------------------------------------\n// TypeScript Loader\n// ---------------------------------------------------------------------------\n\nlet tsLoaderRegistered = false;\n\n/**\n * Ensure a TypeScript loader is registered so that .ts test files can be imported.\n * Tries tsx first (fastest), then ts-node, then falls back to a helpful error.\n *\n * Resolution note: tsx is installed in the USER's project, not in browsecraft itself.\n * We must resolve it from the user's cwd using createRequire, not from our package.\n */\nasync function ensureTypeScriptLoader(): Promise<void> {\n\tif (tsLoaderRegistered) return;\n\n\t// Check if we're already running under a TS loader (e.g., `tsx`, `ts-node`, `bun`)\n\t// In that case, .ts imports already work\n\tconst execArgs = process.execArgv.join(' ');\n\tif (\n\t\texecArgs.includes('tsx') ||\n\t\texecArgs.includes('ts-node') ||\n\t\texecArgs.includes('loader') ||\n\t\tprocess.versions.bun // Bun handles TS natively\n\t) {\n\t\ttsLoaderRegistered = true;\n\t\treturn;\n\t}\n\n\t// Create a require function rooted at the user's cwd so we can find tsx/ts-node\n\t// installed in the user's project (not in our package)\n\tconst { createRequire } = await import('node:module');\n\tconst userRequire = createRequire(pathToFileURL(resolve(process.cwd(), 'package.json')));\n\n\t// Strategy 1: tsx 4.x — use the tsx/esm/api register() function\n\t// This is the modern approach that works with tsx 4.x+\n\ttry {\n\t\tconst tsxApiPath = userRequire.resolve('tsx/esm/api');\n\t\tconst { register } = await import(pathToFileURL(tsxApiPath).href);\n\t\tif (typeof register === 'function') {\n\t\t\tregister();\n\t\t\ttsLoaderRegistered = true;\n\t\t\treturn;\n\t\t}\n\t} catch {\n\t\t// tsx/esm/api not available, try next strategy\n\t}\n\n\t// Strategy 2: Older tsx/ts-node — use Node.js module.register()\n\t// Works with tsx <4.x and ts-node\n\tfor (const loader of ['tsx/esm', 'ts-node/esm']) {\n\t\ttry {\n\t\t\tconst { register } = await import('node:module');\n\t\t\tif (typeof register === 'function') {\n\t\t\t\t// Resolve from user's project root so the loader is found\n\t\t\t\tregister(loader, pathToFileURL(resolve(process.cwd(), '/')));\n\t\t\t\ttsLoaderRegistered = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Loader not available, try next\n\t\t}\n\t}\n\n\t// If neither tsx nor ts-node is available, give a helpful error\n\tconsole.error(\n\t\t'\\n Error: Cannot import TypeScript test files.\\n' +\n\t\t\t' Install tsx (recommended) or ts-node:\\n\\n' +\n\t\t\t' npm install -D tsx\\n\\n' +\n\t\t\t' Or run browsecraft with tsx:\\n\\n' +\n\t\t\t' npx tsx node_modules/.bin/browsecraft test\\n',\n\t);\n\tprocess.exit(1);\n}\n\n// ---------------------------------------------------------------------------\n// Flag parsing\n// ---------------------------------------------------------------------------\n\ninterface CLIFlags {\n\theaded?: boolean;\n\theadless?: boolean;\n\tbrowser?: string;\n\tworkers?: number;\n\ttimeout?: number;\n\tretries?: number;\n\tgrep?: string;\n\tbail?: boolean;\n\tdebug?: boolean;\n\tbdd?: boolean;\n\t/** BDD tag filter expression, e.g. \"@smoke and not @wip\" */\n\ttag?: string;\n\t/** Execution strategy: parallel, sequential, or matrix */\n\tstrategy?: string;\n\t/** BDD scenario name filter (alias for --grep in BDD mode) */\n\tscenario?: string;\n}\n\nfunction parseFlags(args: string[]): CLIFlags {\n\tconst flags: CLIFlags = {};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i]!;\n\t\tswitch (arg) {\n\t\t\tcase '--headed':\n\t\t\t\tflags.headed = true;\n\t\t\t\tbreak;\n\t\t\tcase '--headless':\n\t\t\t\tflags.headless = true;\n\t\t\t\tbreak;\n\t\t\tcase '--debug':\n\t\t\t\tflags.debug = true;\n\t\t\t\tbreak;\n\t\t\tcase '--bdd':\n\t\t\t\tflags.bdd = true;\n\t\t\t\tbreak;\n\t\t\tcase '--bail':\n\t\t\t\tflags.bail = true;\n\t\t\t\tbreak;\n\t\t\tcase '--browser':\n\t\t\t\tflags.browser = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--workers':\n\t\t\t\tflags.workers = Number.parseInt(args[++i] ?? '1', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--timeout':\n\t\t\t\tflags.timeout = Number.parseInt(args[++i] ?? '30000', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--retries':\n\t\t\t\tflags.retries = Number.parseInt(args[++i] ?? '0', 10);\n\t\t\t\tbreak;\n\t\t\tcase '--grep':\n\t\t\tcase '-g':\n\t\t\t\tflags.grep = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--tag':\n\t\t\tcase '--tags':\n\t\t\t\tflags.tag = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--strategy':\n\t\t\t\tflags.strategy = args[++i];\n\t\t\t\tbreak;\n\t\t\tcase '--scenario':\n\t\t\t\tflags.scenario = args[++i];\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn flags;\n}\n\n// ---------------------------------------------------------------------------\n// Help\n// ---------------------------------------------------------------------------\n\nfunction printHelp() {\n\tconsole.log(`\n browsecraft v${VERSION} -- AI-native browser testing\n\n Usage:\n browsecraft test [files...] [options]\n browsecraft bdd [features...] [options]\n browsecraft test --bdd [features...] [options]\n browsecraft init\n browsecraft setup-ide\n\n Commands:\n test Run browser tests\n bdd Run BDD feature files (shorthand for test --bdd)\n test --bdd Run BDD feature files (Gherkin)\n init Create a new project with example config and test\n setup-ide Configure VS Code for Cucumber step discovery\n\n Options:\n --bdd Run BDD feature files instead of programmatic tests\n --browser <names> Browser(s) to use: chrome,firefox,edge (comma-separated)\n --headed Run in headed mode (show the browser)\n --headless Run in headless mode (default)\n --workers <n> Parallel workers — features run concurrently (default: 1)\n --timeout <ms> Global timeout in milliseconds (default: 30000)\n --retries <n> Retry failed tests n times (default: 0)\n --grep <pattern> Only run tests/scenarios matching pattern\n --scenario <name> Run only scenarios whose name contains <name>\n --tag <expr> BDD tag filter: \"@smoke\", \"@smoke and not @wip\"\n --strategy <s> Multi-browser strategy: parallel, sequential, matrix\n --bail Stop after first failure\n --debug Enable verbose debug logging\n -h, --help Show this help message\n -v, --version Show version\n\n BDD Examples:\n browsecraft bdd # All features, 1 browser\n browsecraft bdd features/login.feature # Single feature\n browsecraft bdd features/login.feature:15 # Specific scenario by line\n browsecraft bdd --headed # Watch it run\n browsecraft test --bdd features/login.feature # Equivalent long form\n browsecraft test --bdd --scenario \"Valid login\" # Specific scenario by name\n browsecraft test --bdd --tag \"@smoke\" # Tag filter\n browsecraft test --bdd --grep \"checkout\" # Name filter\n browsecraft test --bdd --workers 4 # 4 features in parallel\n browsecraft test --bdd --browser chrome,firefox # Multi-browser\n browsecraft test --bdd --browser chrome,firefox,edge --strategy matrix\n browsecraft test --bdd --headed --browser firefox # Headed mode\n\n Programmatic Examples:\n browsecraft test # Run all tests\n browsecraft test tests/login.test.ts # Run specific file\n browsecraft test --headed --browser firefox\n browsecraft test --grep \"login\" --bail\n browsecraft setup-ide # Auto-configure IDE for BDD\n`);\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\nmain().catch((err) => {\n\tconsole.error('Fatal error:', err.message);\n\tprocess.exit(1);\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browsecraft",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "AI-native browser automation framework. Craft browser tests that just work.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -25,9 +25,9 @@
25
25
  "access": "public"
26
26
  },
27
27
  "dependencies": {
28
- "browsecraft-bdd": "0.5.0",
29
- "browsecraft-bidi": "0.5.0",
30
- "browsecraft-runner": "0.5.0"
28
+ "browsecraft-bidi": "0.5.1",
29
+ "browsecraft-bdd": "0.5.1",
30
+ "browsecraft-runner": "0.5.1"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^25.3.0",