@desplega.ai/qa-use 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/lib/api/sse.d.ts.map +1 -1
  2. package/dist/lib/api/sse.js +31 -7
  3. package/dist/lib/api/sse.js.map +1 -1
  4. package/dist/package.json +1 -1
  5. package/dist/src/cli/commands/test/export.d.ts +6 -0
  6. package/dist/src/cli/commands/test/export.d.ts.map +1 -0
  7. package/dist/src/cli/commands/test/export.js +82 -0
  8. package/dist/src/cli/commands/test/export.js.map +1 -0
  9. package/dist/src/cli/commands/test/index.d.ts.map +1 -1
  10. package/dist/src/cli/commands/test/index.js +4 -0
  11. package/dist/src/cli/commands/test/index.js.map +1 -1
  12. package/dist/src/cli/commands/test/run.d.ts.map +1 -1
  13. package/dist/src/cli/commands/test/run.js +17 -6
  14. package/dist/src/cli/commands/test/run.js.map +1 -1
  15. package/dist/src/cli/commands/test/sync.d.ts +6 -0
  16. package/dist/src/cli/commands/test/sync.d.ts.map +1 -0
  17. package/dist/src/cli/commands/test/sync.js +157 -0
  18. package/dist/src/cli/commands/test/sync.js.map +1 -0
  19. package/dist/src/cli/lib/browser.d.ts +50 -0
  20. package/dist/src/cli/lib/browser.d.ts.map +1 -0
  21. package/dist/src/cli/lib/browser.js +111 -0
  22. package/dist/src/cli/lib/browser.js.map +1 -0
  23. package/dist/src/cli/lib/id-injector.d.ts +59 -0
  24. package/dist/src/cli/lib/id-injector.d.ts.map +1 -0
  25. package/dist/src/cli/lib/id-injector.js +143 -0
  26. package/dist/src/cli/lib/id-injector.js.map +1 -0
  27. package/dist/src/cli/lib/output.d.ts +13 -1
  28. package/dist/src/cli/lib/output.d.ts.map +1 -1
  29. package/dist/src/cli/lib/output.js +145 -8
  30. package/dist/src/cli/lib/output.js.map +1 -1
  31. package/dist/src/cli/lib/runner.d.ts +9 -1
  32. package/dist/src/cli/lib/runner.d.ts.map +1 -1
  33. package/dist/src/cli/lib/runner.js +6 -2
  34. package/dist/src/cli/lib/runner.js.map +1 -1
  35. package/dist/src/types/test-definition.d.ts +5 -3
  36. package/dist/src/types/test-definition.d.ts.map +1 -1
  37. package/dist/src/types/test-definition.js +3 -3
  38. package/lib/api/sse.ts +36 -7
  39. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../lib/api/sse.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,GAAG,CAAC;IACV,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CA4BlD;AAED;;;;;GAKG;AACH,wBAAuB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAyC5F;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACjD,OAAO,CAAC,IAAI,CAAC,CAIf"}
1
+ {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../lib/api/sse.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,GAAG,CAAC;IACV,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAsBD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CAmClD;AAED;;;;;GAKG;AACH,wBAAuB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CA2C5F;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACjD,OAAO,CAAC,IAAI,CAAC,CAIf"}
@@ -3,6 +3,22 @@
3
3
  *
4
4
  * Used for streaming test execution progress from /vibe-qa/cli/run endpoint
5
5
  */
6
+ /**
7
+ * Find the boundary between SSE events
8
+ * Handles both LF (\n\n) and CRLF (\r\n\r\n) line endings
9
+ */
10
+ function findEventBoundary(buffer) {
11
+ // Check for CRLF first (more specific)
12
+ const crlfPos = buffer.indexOf('\r\n\r\n');
13
+ const lfPos = buffer.indexOf('\n\n');
14
+ if (crlfPos === -1 && lfPos === -1) {
15
+ return -1;
16
+ }
17
+ if (crlfPos !== -1 && (lfPos === -1 || crlfPos < lfPos)) {
18
+ return { index: crlfPos, length: 4 };
19
+ }
20
+ return { index: lfPos, length: 2 };
21
+ }
6
22
  /**
7
23
  * Parse SSE data from a chunk of text
8
24
  *
@@ -11,7 +27,8 @@
11
27
  */
12
28
  export function parseSSE(chunk) {
13
29
  const events = [];
14
- const lines = chunk.split('\n');
30
+ // Split on \n and trim \r from each line to handle both LF and CRLF
31
+ const lines = chunk.split('\n').map((line) => line.replace(/\r$/, ''));
15
32
  let currentEvent = {};
16
33
  for (const line of lines) {
17
34
  if (line.startsWith('event: ')) {
@@ -29,13 +46,18 @@ export function parseSSE(chunk) {
29
46
  else if (line.startsWith('id: ')) {
30
47
  currentEvent.id = line.slice(4).trim();
31
48
  }
32
- else if (line === '') {
49
+ else if (line === '' || line === '\r') {
33
50
  // Empty line signals end of event
34
51
  if (currentEvent.event && currentEvent.data !== undefined) {
35
52
  events.push(currentEvent);
36
53
  }
37
54
  currentEvent = {};
38
55
  }
56
+ // Lines starting with ':' are comments (e.g., pings) - ignore them
57
+ }
58
+ // Push any pending event (in case chunk doesn't end with empty line)
59
+ if (currentEvent.event && currentEvent.data !== undefined) {
60
+ events.push(currentEvent);
39
61
  }
40
62
  return events;
41
63
  }
@@ -59,15 +81,17 @@ export async function* streamSSE(response) {
59
81
  break;
60
82
  buffer += decoder.decode(value, { stream: true });
61
83
  // Find complete events (separated by double newlines)
62
- let pos = buffer.indexOf('\n\n');
84
+ // Handle both LF (\n\n) and CRLF (\r\n\r\n) line endings
85
+ let pos = findEventBoundary(buffer);
63
86
  while (pos !== -1) {
64
- const chunk = buffer.slice(0, pos + 2);
65
- buffer = buffer.slice(pos + 2);
66
- const events = parseSSE(chunk);
87
+ const { index, length } = pos;
88
+ const eventChunk = buffer.slice(0, index);
89
+ buffer = buffer.slice(index + length);
90
+ const events = parseSSE(eventChunk);
67
91
  for (const event of events) {
68
92
  yield event;
69
93
  }
70
- pos = buffer.indexOf('\n\n');
94
+ pos = findEventBoundary(buffer);
71
95
  }
72
96
  }
73
97
  // Process any remaining buffer
@@ -1 +1 @@
1
- {"version":3,"file":"sse.js","sourceRoot":"","sources":["../../../lib/api/sse.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sse.js","sourceRoot":"","sources":["../../../lib/api/sse.ts"],"names":[],"mappings":"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"}
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@desplega.ai/qa-use",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "packageManager": "bun@^1.3.4",
5
5
  "description": "QA automation tool for browser testing with MCP server support",
6
6
  "type": "module",
@@ -0,0 +1,6 @@
1
+ /**
2
+ * qa-use test export - Export cloud test to local file
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const exportCommand: Command;
6
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/test/export.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,aAAa,SAiFtB,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * qa-use test export - Export cloud test to local file
3
+ */
4
+ import { Command } from 'commander';
5
+ import * as fs from 'fs/promises';
6
+ import * as path from 'path';
7
+ import { loadConfig } from '../../lib/config.js';
8
+ import { error, success, info } from '../../lib/output.js';
9
+ import { ApiClient } from '../../../../lib/api/index.js';
10
+ export const exportCommand = new Command('export')
11
+ .description('Export a cloud test to a local file')
12
+ .argument('<test-id>', 'Cloud test ID (UUID) to export')
13
+ .option('--format <format>', 'Output format (yaml or json)', 'yaml')
14
+ .option('--output <path>', 'Output file path (default: qa-tests/<test-name>.<format>)')
15
+ .option('--no-deps', 'Exclude dependency tests')
16
+ .option('--stdout', 'Output to stdout instead of file')
17
+ .action(async (testId, options) => {
18
+ try {
19
+ const config = await loadConfig();
20
+ // Check API key
21
+ if (!config.api_key) {
22
+ console.log(error('API key not configured'));
23
+ console.log(' Run `qa-use setup` to configure');
24
+ process.exit(1);
25
+ }
26
+ // Validate format
27
+ if (!['yaml', 'json'].includes(options.format)) {
28
+ console.log(error('Invalid format. Use --format yaml or --format json'));
29
+ process.exit(1);
30
+ }
31
+ // Initialize API client
32
+ const client = new ApiClient(config.api_url);
33
+ client.setApiKey(config.api_key);
34
+ if (!options.stdout) {
35
+ console.log(info(`Exporting test ${testId}...`));
36
+ }
37
+ // Export from API
38
+ const content = await client.exportTest(testId, options.format, options.deps !== false);
39
+ // Output to stdout if requested
40
+ if (options.stdout) {
41
+ console.log(content);
42
+ return;
43
+ }
44
+ // Determine output path
45
+ let outputPath = options.output;
46
+ if (!outputPath) {
47
+ // Get test info to use name for filename
48
+ try {
49
+ const testInfo = await client.getTest(testId);
50
+ const safeName = testInfo.name
51
+ .toLowerCase()
52
+ .replace(/[^a-z0-9]+/g, '-')
53
+ .replace(/^-|-$/g, '');
54
+ const ext = options.format === 'json' ? '.json' : '.yaml';
55
+ outputPath = path.join(config.test_directory || './qa-tests', safeName + ext);
56
+ }
57
+ catch {
58
+ // Fall back to using test ID as filename
59
+ const ext = options.format === 'json' ? '.json' : '.yaml';
60
+ outputPath = path.join(config.test_directory || './qa-tests', testId + ext);
61
+ }
62
+ }
63
+ // Ensure directory exists
64
+ const dir = path.dirname(outputPath);
65
+ await fs.mkdir(dir, { recursive: true });
66
+ // Write file
67
+ await fs.writeFile(outputPath, content, 'utf-8');
68
+ console.log(success(`Exported to ${outputPath}`));
69
+ // Show summary
70
+ const lines = content.split('\n').length;
71
+ console.log(` Format: ${options.format}`);
72
+ console.log(` Lines: ${lines}`);
73
+ if (options.deps !== false) {
74
+ console.log(` Dependencies: included`);
75
+ }
76
+ }
77
+ catch (err) {
78
+ console.log(error(`Export failed: ${err}`));
79
+ process.exit(1);
80
+ }
81
+ });
82
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../../../../src/cli/commands/test/export.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/test/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,WAAW,SAAqE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/test/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,eAAO,MAAM,WAAW,SAAqE,CAAC"}
@@ -6,10 +6,14 @@ import { runCommand } from './run.js';
6
6
  import { listCommand } from './list.js';
7
7
  import { validateCommand } from './validate.js';
8
8
  import { initCommand } from './init.js';
9
+ import { exportCommand } from './export.js';
10
+ import { syncCommand } from './sync.js';
9
11
  export const testCommand = new Command('test').description('Manage and run test definitions');
10
12
  // Register subcommands
11
13
  testCommand.addCommand(runCommand);
12
14
  testCommand.addCommand(listCommand);
13
15
  testCommand.addCommand(validateCommand);
14
16
  testCommand.addCommand(initCommand);
17
+ testCommand.addCommand(exportCommand);
18
+ testCommand.addCommand(syncCommand);
15
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/cli/commands/test/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,iCAAiC,CAAC,CAAC;AAE9F,uBAAuB;AACvB,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AACnC,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AACpC,WAAW,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACxC,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/cli/commands/test/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,iCAAiC,CAAC,CAAC;AAE9F,uBAAuB;AACvB,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AACnC,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AACpC,WAAW,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACxC,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AACpC,WAAW,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AACtC,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/test/run.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,eAAO,MAAM,UAAU,SAoFnB,CAAC"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/test/run.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBpC,eAAO,MAAM,UAAU,SAmGnB,CAAC"}
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { Command } from 'commander';
5
5
  import { loadConfig } from '../../lib/config.js';
6
- import { loadTestWithDeps, loadAllTests, applyVariableOverrides } from '../../lib/loader.js';
6
+ import { loadTestWithDeps, loadAllTests, applyVariableOverrides, resolveTestPath, } from '../../lib/loader.js';
7
7
  import { runTest } from '../../lib/runner.js';
8
8
  import { error, success } from '../../lib/output.js';
9
9
  import { ApiClient } from '../../../../lib/api/index.js';
@@ -17,12 +17,14 @@ export const runCommand = new Command('run')
17
17
  .option('--id <uuid>', 'Run cloud test by ID instead of local file')
18
18
  .option('--all', 'Run all tests in test directory')
19
19
  .option('--persist', 'Save test to cloud after run')
20
- .option('--no-headless', 'Show browser window')
21
- .option('--no-autofix', 'Disable AI self-healing')
20
+ .option('--headful', 'Show browser window (default: headless)')
21
+ .option('--autofix', 'Enable AI self-healing (default: off)')
22
22
  .option('--screenshots', 'Capture screenshots at each step')
23
23
  .option('--var <key=value...>', 'Variable overrides', collectVars, {})
24
24
  .option('--app-config-id <uuid>', 'App config ID to use')
25
25
  .option('--timeout <seconds>', 'Timeout in seconds', '300')
26
+ .option('--verbose', 'Output raw SSE event data for debugging')
27
+ .option('--update-local', 'Update local test file when AI auto-fixes the test')
26
28
  .action(async (test, options) => {
27
29
  try {
28
30
  const config = await loadConfig();
@@ -36,6 +38,7 @@ export const runCommand = new Command('run')
36
38
  const client = new ApiClient(config.api_url);
37
39
  client.setApiKey(config.api_key);
38
40
  let testDefinitions;
41
+ let sourceFile;
39
42
  if (options.id) {
40
43
  // Run by cloud ID - no local definition needed
41
44
  testDefinitions = undefined;
@@ -45,11 +48,15 @@ export const runCommand = new Command('run')
45
48
  console.log('Loading all tests...');
46
49
  testDefinitions = await loadAllTests(config.test_directory || './qa-tests');
47
50
  console.log(success(`Loaded ${testDefinitions.length} tests\n`));
51
+ // Note: --update-local only works for single test runs
48
52
  }
49
53
  else if (test) {
50
54
  // Load specific test and its dependencies
51
55
  console.log(`Loading test: ${test}...`);
52
- testDefinitions = await loadTestWithDeps(test, config.test_directory || './qa-tests');
56
+ const testDir = config.test_directory || './qa-tests';
57
+ testDefinitions = await loadTestWithDeps(test, testDir);
58
+ // Track source file for --update-local support
59
+ sourceFile = resolveTestPath(test, testDir);
53
60
  console.log(success(`Loaded ${testDefinitions.length} test(s)\n`));
54
61
  }
55
62
  else {
@@ -68,9 +75,13 @@ export const runCommand = new Command('run')
68
75
  test_definitions: testDefinitions,
69
76
  test_id: options.id,
70
77
  persist: options.persist || config.defaults?.persist || false,
71
- headless: options.headless !== false && (config.defaults?.headless ?? true),
72
- allow_fix: options.autofix !== false && (config.defaults?.allow_fix ?? true),
78
+ headless: !options.headful && (config.defaults?.headless ?? true),
79
+ allow_fix: options.autofix || config.defaults?.allow_fix || false,
73
80
  capture_screenshots: options.screenshots || false,
81
+ }, {
82
+ verbose: options.verbose || false,
83
+ updateLocal: options.updateLocal || false,
84
+ sourceFile,
74
85
  });
75
86
  // Print result summary
76
87
  if (result.assets) {
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../../src/cli/commands/test/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../../src/cli/commands/test/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * qa-use test sync - Sync local and cloud tests
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const syncCommand: Command;
6
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/test/sync.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,eAAO,MAAM,WAAW,SAiCpB,CAAC"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * qa-use test sync - Sync local and cloud tests
3
+ */
4
+ import { Command } from 'commander';
5
+ import * as fs from 'fs/promises';
6
+ import * as path from 'path';
7
+ import { loadConfig } from '../../lib/config.js';
8
+ import { discoverTests, loadTestDefinition } from '../../lib/loader.js';
9
+ import { error, success, info, warning } from '../../lib/output.js';
10
+ import { ApiClient } from '../../../../lib/api/index.js';
11
+ export const syncCommand = new Command('sync')
12
+ .description('Sync local tests with cloud')
13
+ .option('--pull', 'Pull tests from cloud to local (default)')
14
+ .option('--push', 'Push local tests to cloud')
15
+ .option('--dry-run', 'Show what would be synced without making changes')
16
+ .option('--force', 'Overwrite existing files/tests without prompting')
17
+ .action(async (options) => {
18
+ try {
19
+ const config = await loadConfig();
20
+ // Check API key
21
+ if (!config.api_key) {
22
+ console.log(error('API key not configured'));
23
+ console.log(' Run `qa-use setup` to configure');
24
+ process.exit(1);
25
+ }
26
+ // Initialize API client
27
+ const client = new ApiClient(config.api_url);
28
+ client.setApiKey(config.api_key);
29
+ const testDir = config.test_directory || './qa-tests';
30
+ if (options.push) {
31
+ await pushToCloud(client, testDir, options.dryRun, options.force);
32
+ }
33
+ else {
34
+ // Default to pull
35
+ await pullFromCloud(client, testDir, options.dryRun, options.force);
36
+ }
37
+ }
38
+ catch (err) {
39
+ console.log(error(`Sync failed: ${err}`));
40
+ process.exit(1);
41
+ }
42
+ });
43
+ /**
44
+ * Pull tests from cloud to local files
45
+ */
46
+ async function pullFromCloud(client, testDir, dryRun = false, force = false) {
47
+ console.log(info('Fetching tests from cloud...\n'));
48
+ const cloudTests = await client.listTests({ limit: 100 });
49
+ if (cloudTests.length === 0) {
50
+ console.log(warning('No tests found in cloud'));
51
+ return;
52
+ }
53
+ console.log(`Found ${cloudTests.length} cloud test(s)\n`);
54
+ // Ensure test directory exists
55
+ if (!dryRun) {
56
+ await fs.mkdir(testDir, { recursive: true });
57
+ }
58
+ let pulled = 0;
59
+ let skipped = 0;
60
+ for (const test of cloudTests) {
61
+ const safeName = test.name
62
+ .toLowerCase()
63
+ .replace(/[^a-z0-9]+/g, '-')
64
+ .replace(/^-|-$/g, '');
65
+ const outputPath = path.join(testDir, safeName + '.yaml');
66
+ // Check if file exists
67
+ let exists = false;
68
+ try {
69
+ await fs.access(outputPath);
70
+ exists = true;
71
+ }
72
+ catch {
73
+ // File doesn't exist
74
+ }
75
+ if (exists && !force) {
76
+ console.log(` Skip: ${safeName}.yaml (exists, use --force to overwrite)`);
77
+ skipped++;
78
+ continue;
79
+ }
80
+ if (dryRun) {
81
+ console.log(` Would pull: ${test.name} -> ${outputPath}`);
82
+ }
83
+ else {
84
+ try {
85
+ const content = await client.exportTest(test.id, 'yaml', true);
86
+ await fs.writeFile(outputPath, content, 'utf-8');
87
+ console.log(success(` ${safeName}.yaml`));
88
+ pulled++;
89
+ }
90
+ catch (err) {
91
+ console.log(error(` Failed to export ${test.name}: ${err}`));
92
+ }
93
+ }
94
+ }
95
+ console.log('');
96
+ if (dryRun) {
97
+ console.log(info(`Dry run complete. Would pull ${cloudTests.length - skipped} test(s).`));
98
+ }
99
+ else {
100
+ console.log(success(`Pulled ${pulled} test(s), skipped ${skipped}`));
101
+ }
102
+ }
103
+ /**
104
+ * Push local tests to cloud
105
+ */
106
+ async function pushToCloud(client, testDir, dryRun = false, _force = false) {
107
+ console.log(info(`Loading local tests from ${testDir}...\n`));
108
+ const files = await discoverTests(testDir);
109
+ if (files.length === 0) {
110
+ console.log(warning('No local tests found'));
111
+ console.log(' Run `qa-use test init` to create example tests');
112
+ return;
113
+ }
114
+ console.log(`Found ${files.length} local test(s)\n`);
115
+ // Load all test definitions
116
+ const definitions = [];
117
+ for (const file of files) {
118
+ try {
119
+ const def = await loadTestDefinition(file);
120
+ definitions.push({ file, def });
121
+ }
122
+ catch (err) {
123
+ console.log(error(` Failed to load ${file}: ${err}`));
124
+ }
125
+ }
126
+ if (definitions.length === 0) {
127
+ console.log(error('No valid test definitions found'));
128
+ return;
129
+ }
130
+ if (dryRun) {
131
+ console.log(info('Dry run - would push:'));
132
+ for (const { file, def } of definitions) {
133
+ console.log(` ${def.name || path.basename(file)}`);
134
+ }
135
+ console.log('');
136
+ console.log(info(`Would import ${definitions.length} test(s)`));
137
+ return;
138
+ }
139
+ // Import to cloud
140
+ console.log('Importing to cloud...\n');
141
+ const result = await client.importTestDefinition(definitions.map((d) => d.def), { upsert: true });
142
+ if (result.success) {
143
+ for (const imported of result.imported) {
144
+ const action = imported.action === 'created' ? 'Created' : 'Updated';
145
+ console.log(success(` ${action}: ${imported.name} (${imported.id})`));
146
+ }
147
+ console.log('');
148
+ console.log(success(`Pushed ${result.imported.length} test(s)`));
149
+ }
150
+ else {
151
+ console.log(error('Import failed'));
152
+ for (const err of result.errors) {
153
+ console.log(error(` ${err.name}: ${err.error}`));
154
+ }
155
+ }
156
+ }
157
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../../../src/cli/commands/test/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Browser and tunnel management for CLI test execution
3
+ *
4
+ * Provides automatic localhost tunneling when tests target localhost URLs,
5
+ * and browser WebSocket connection for remote test execution.
6
+ */
7
+ import { TunnelManager } from '../../../lib/tunnel/index.js';
8
+ import { BrowserManager } from '../../../lib/browser/index.js';
9
+ export interface BrowserTunnelSession {
10
+ browser: BrowserManager;
11
+ tunnel: TunnelManager | null;
12
+ wsUrl: string;
13
+ publicWsUrl: string | null;
14
+ isLocalhost: boolean;
15
+ }
16
+ export interface BrowserTunnelOptions {
17
+ headless?: boolean;
18
+ apiKey?: string;
19
+ sessionIndex?: number;
20
+ }
21
+ /**
22
+ * Check if a URL points to localhost
23
+ */
24
+ export declare function isLocalhostUrl(url: string): boolean;
25
+ /**
26
+ * Get the port from a URL
27
+ */
28
+ export declare function getPortFromUrl(url: string): number;
29
+ /**
30
+ * Start browser and tunnel (if needed for localhost testing)
31
+ *
32
+ * @param testUrl - The URL being tested (to detect localhost)
33
+ * @param options - Browser and tunnel options
34
+ * @returns BrowserTunnelSession with connection details
35
+ */
36
+ export declare function startBrowserWithTunnel(testUrl: string | undefined, options?: BrowserTunnelOptions): Promise<BrowserTunnelSession>;
37
+ /**
38
+ * Stop browser and tunnel
39
+ */
40
+ export declare function stopBrowserWithTunnel(session: BrowserTunnelSession): Promise<void>;
41
+ /**
42
+ * Get the appropriate WebSocket URL for API calls
43
+ * Returns public URL if tunnel is active, otherwise local URL
44
+ */
45
+ export declare function getEffectiveWsUrl(session: BrowserTunnelSession): string;
46
+ /**
47
+ * Check if browser and tunnel are healthy
48
+ */
49
+ export declare function checkSessionHealth(session: BrowserTunnelSession): Promise<boolean>;
50
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/browser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAG/D,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAYnD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWlD;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,oBAAoB,CAAC,CAwC/B;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKxF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CAEvE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CAaxF"}