prowl-tools 0.1.3 → 0.1.4

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/index.js CHANGED
@@ -2,14 +2,19 @@
2
2
  import {
3
3
  DEFAULT_FLAKY_THRESHOLD,
4
4
  analyzePage,
5
+ closeBrowser,
6
+ createPlaywrightDriver,
5
7
  generateHunt,
8
+ launchBrowser,
9
+ parseBrowserEngine,
6
10
  printCiSummary,
7
11
  rankFlaky,
8
12
  readHuntHistory,
9
13
  runHunt,
10
14
  runSuite,
15
+ saveStorageState,
11
16
  updateBacklogFromSuite
12
- } from "./chunk-T7YLXF6X.js";
17
+ } from "./chunk-ZEFVTKQT.js";
13
18
  import {
14
19
  CONFIG_DIR,
15
20
  listHunts,
@@ -17,7 +22,7 @@ import {
17
22
  loadHuntMeta,
18
23
  loadHuntTags,
19
24
  resolveViewport
20
- } from "./chunk-NXXGJOBG.js";
25
+ } from "./chunk-MBAIGNVO.js";
21
26
 
22
27
  // src/cli/program.ts
23
28
  import { Command as Command13 } from "commander";
@@ -25,11 +30,11 @@ import { Command as Command13 } from "commander";
25
30
  // package.json
26
31
  var package_default = {
27
32
  name: "prowl-tools",
28
- version: "0.1.3",
33
+ version: "0.1.4",
29
34
  description: "CLI-first QA testing tool for deterministic Playwright flows.",
30
35
  type: "module",
31
36
  license: "Apache-2.0",
32
- author: "Michael Tookes",
37
+ author: "Prowl Tools",
33
38
  repository: {
34
39
  type: "git",
35
40
  url: "https://github.com/prowl-tools/prowl.git"
@@ -396,7 +401,6 @@ import path2 from "path";
396
401
  import readline from "readline";
397
402
  import chalk5 from "chalk";
398
403
  import { Command as Command3 } from "commander";
399
- import { chromium } from "playwright";
400
404
  function resolvePath(configDir, inputPath) {
401
405
  if (path2.isAbsolute(inputPath)) {
402
406
  return inputPath;
@@ -415,30 +419,35 @@ function waitForEnter(prompt) {
415
419
  }
416
420
  function buildLoginCommand() {
417
421
  const command = new Command3("login").option("--url <target>", "Override target URL").option("--config <path>", "Custom config path").action(async (options) => {
418
- let browser = null;
419
- let context = null;
422
+ let session = null;
420
423
  try {
421
424
  const { config, configDir } = loadConfig(options.config);
425
+ if (config.target.type === "macos") {
426
+ throw new Error("`prowl login` captures browser auth state and only applies to web targets.");
427
+ }
422
428
  const targetUrl = options.url ?? config.target.url;
423
429
  const storageStatePath = config.auth.storageStatePath ? resolvePath(configDir, config.auth.storageStatePath) : resolvePath(configDir, ".prowl/auth-state.json");
424
- browser = await chromium.launch({ headless: false });
425
- context = await browser.newContext();
426
- const page = await context.newPage();
427
- await page.goto(targetUrl);
430
+ session = await launchBrowser({
431
+ headless: false,
432
+ slowMo: 0,
433
+ timeout: config.browser.timeout,
434
+ trace: false,
435
+ recordHar: false,
436
+ runDir: configDir
437
+ });
438
+ const driver = createPlaywrightDriver(session.page);
439
+ await driver.goto(targetUrl);
428
440
  console.log(chalk5.green("Browser opened. Log in manually."));
429
441
  await waitForEnter("Press Enter to save auth state and close the browser... ");
430
- await context.storageState({ path: storageStatePath });
442
+ await saveStorageState(session, storageStatePath);
431
443
  console.log(chalk5.green(`Saved auth state to ${storageStatePath}`));
432
444
  } catch (error) {
433
445
  const message = error instanceof Error ? error.message : "Login failed";
434
446
  console.error(chalk5.red(`Error: ${message}`));
435
447
  process.exitCode = 1;
436
448
  } finally {
437
- if (context) {
438
- await context.close();
439
- }
440
- if (browser) {
441
- await browser.close();
449
+ if (session) {
450
+ await closeBrowser(session);
442
451
  }
443
452
  }
444
453
  });
@@ -763,8 +772,6 @@ function buildUpdateBaselinesCommand() {
763
772
  // src/cli/commands/analyze.ts
764
773
  import { Command as Command8 } from "commander";
765
774
  import chalk10 from "chalk";
766
- import { chromium as chromium2, firefox, webkit } from "playwright";
767
- var ENGINES = { chromium: chromium2, firefox, webkit };
768
775
  function parseViewportFlag(value) {
769
776
  const match = /^(\d+)x(\d+)$/i.exec(value);
770
777
  if (match) {
@@ -775,19 +782,24 @@ function parseViewportFlag(value) {
775
782
  function buildAnalyzeCommand() {
776
783
  const command = new Command8("analyze").argument("<url>", "URL to analyze").description("Analyze a page to discover interactive elements and selectors").option("--json", "Output as JSON").option("--browser <engine>", "Browser engine: chromium, firefox, or webkit").option("--channel <name>", "Browser channel: chrome, msedge, etc.").option("--viewport <size>", "Viewport size: WxH or preset (mobile, tablet, desktop)").option("--headed", "Show browser window").option("--config <path>", "Custom config path").action(async (url, options) => {
777
784
  try {
778
- const engine = options.browser ?? "chromium";
785
+ const engine = parseBrowserEngine(options.browser);
779
786
  const channel = options.channel;
780
787
  const viewport = options.viewport ? resolveViewport(parseViewportFlag(options.viewport)) : { width: 1280, height: 720 };
781
- const browserEngine = ENGINES[engine];
782
- const browser = await browserEngine.launch({
788
+ const session = await launchBrowser({
783
789
  headless: !options.headed,
784
- channel
790
+ slowMo: 0,
791
+ timeout: 3e4,
792
+ trace: false,
793
+ recordHar: false,
794
+ runDir: process.cwd(),
795
+ engine,
796
+ channel,
797
+ viewport
785
798
  });
786
- const context = await browser.newContext({ viewport });
787
- const page = await context.newPage();
799
+ const driver = createPlaywrightDriver(session.page);
788
800
  try {
789
- await page.goto(url, { waitUntil: "networkidle" });
790
- const result = await analyzePage(page);
801
+ await driver.goto(url, { waitUntil: "networkidle" });
802
+ const result = await analyzePage(driver);
791
803
  if (options.json) {
792
804
  console.log(JSON.stringify(result, null, 2));
793
805
  } else {
@@ -832,8 +844,7 @@ function buildAnalyzeCommand() {
832
844
  `));
833
845
  }
834
846
  } finally {
835
- await context.close();
836
- await browser.close();
847
+ await closeBrowser(session);
837
848
  }
838
849
  } catch (error) {
839
850
  const message = error instanceof Error ? error.message : "Analysis failed";
@@ -908,7 +919,7 @@ function buildGenerateCommand() {
908
919
  } else if (options.output) {
909
920
  let configDir;
910
921
  try {
911
- const { loadConfig: loadConfig2 } = await import("./loader-5RDNTJHH.js");
922
+ const { loadConfig: loadConfig2 } = await import("./loader-XMTDB6OL.js");
912
923
  const result = loadConfig2(options.config);
913
924
  configDir = result.configDir;
914
925
  } catch {