@desplega.ai/qa-use 2.1.7 → 2.2.2
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/lib/api/browser-types.d.ts +175 -0
- package/dist/lib/api/browser-types.d.ts.map +1 -0
- package/dist/lib/api/browser-types.js +5 -0
- package/dist/lib/api/browser-types.js.map +1 -0
- package/dist/lib/api/browser.d.ts +66 -0
- package/dist/lib/api/browser.d.ts.map +1 -0
- package/dist/lib/api/browser.js +223 -0
- package/dist/lib/api/browser.js.map +1 -0
- package/dist/package.json +2 -1
- package/dist/src/cli/commands/browser/back.d.ts +6 -0
- package/dist/src/cli/commands/browser/back.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/back.js +42 -0
- package/dist/src/cli/commands/browser/back.js.map +1 -0
- package/dist/src/cli/commands/browser/check.d.ts +6 -0
- package/dist/src/cli/commands/browser/check.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/check.js +62 -0
- package/dist/src/cli/commands/browser/check.js.map +1 -0
- package/dist/src/cli/commands/browser/click.d.ts +6 -0
- package/dist/src/cli/commands/browser/click.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/click.js +63 -0
- package/dist/src/cli/commands/browser/click.js.map +1 -0
- package/dist/src/cli/commands/browser/close.d.ts +6 -0
- package/dist/src/cli/commands/browser/close.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/close.js +44 -0
- package/dist/src/cli/commands/browser/close.js.map +1 -0
- package/dist/src/cli/commands/browser/create.d.ts +6 -0
- package/dist/src/cli/commands/browser/create.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/create.js +281 -0
- package/dist/src/cli/commands/browser/create.js.map +1 -0
- package/dist/src/cli/commands/browser/fill.d.ts +6 -0
- package/dist/src/cli/commands/browser/fill.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/fill.js +83 -0
- package/dist/src/cli/commands/browser/fill.js.map +1 -0
- package/dist/src/cli/commands/browser/forward.d.ts +6 -0
- package/dist/src/cli/commands/browser/forward.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/forward.js +42 -0
- package/dist/src/cli/commands/browser/forward.js.map +1 -0
- package/dist/src/cli/commands/browser/get-blocks.d.ts +6 -0
- package/dist/src/cli/commands/browser/get-blocks.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/get-blocks.js +35 -0
- package/dist/src/cli/commands/browser/get-blocks.js.map +1 -0
- package/dist/src/cli/commands/browser/goto.d.ts +6 -0
- package/dist/src/cli/commands/browser/goto.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/goto.js +53 -0
- package/dist/src/cli/commands/browser/goto.js.map +1 -0
- package/dist/src/cli/commands/browser/hover.d.ts +6 -0
- package/dist/src/cli/commands/browser/hover.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/hover.js +63 -0
- package/dist/src/cli/commands/browser/hover.js.map +1 -0
- package/dist/src/cli/commands/browser/index.d.ts +9 -0
- package/dist/src/cli/commands/browser/index.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/index.js +71 -0
- package/dist/src/cli/commands/browser/index.js.map +1 -0
- package/dist/src/cli/commands/browser/list.d.ts +6 -0
- package/dist/src/cli/commands/browser/list.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/list.js +85 -0
- package/dist/src/cli/commands/browser/list.js.map +1 -0
- package/dist/src/cli/commands/browser/press.d.ts +6 -0
- package/dist/src/cli/commands/browser/press.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/press.js +67 -0
- package/dist/src/cli/commands/browser/press.js.map +1 -0
- package/dist/src/cli/commands/browser/reload.d.ts +6 -0
- package/dist/src/cli/commands/browser/reload.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/reload.js +42 -0
- package/dist/src/cli/commands/browser/reload.js.map +1 -0
- package/dist/src/cli/commands/browser/run.d.ts +6 -0
- package/dist/src/cli/commands/browser/run.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/run.js +618 -0
- package/dist/src/cli/commands/browser/run.js.map +1 -0
- package/dist/src/cli/commands/browser/screenshot.d.ts +6 -0
- package/dist/src/cli/commands/browser/screenshot.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/screenshot.js +72 -0
- package/dist/src/cli/commands/browser/screenshot.js.map +1 -0
- package/dist/src/cli/commands/browser/scroll-into-view.d.ts +6 -0
- package/dist/src/cli/commands/browser/scroll-into-view.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/scroll-into-view.js +64 -0
- package/dist/src/cli/commands/browser/scroll-into-view.js.map +1 -0
- package/dist/src/cli/commands/browser/scroll.d.ts +6 -0
- package/dist/src/cli/commands/browser/scroll.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/scroll.js +63 -0
- package/dist/src/cli/commands/browser/scroll.js.map +1 -0
- package/dist/src/cli/commands/browser/select.d.ts +6 -0
- package/dist/src/cli/commands/browser/select.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/select.js +83 -0
- package/dist/src/cli/commands/browser/select.js.map +1 -0
- package/dist/src/cli/commands/browser/snapshot.d.ts +6 -0
- package/dist/src/cli/commands/browser/snapshot.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/snapshot.js +72 -0
- package/dist/src/cli/commands/browser/snapshot.js.map +1 -0
- package/dist/src/cli/commands/browser/status.d.ts +6 -0
- package/dist/src/cli/commands/browser/status.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/status.js +91 -0
- package/dist/src/cli/commands/browser/status.js.map +1 -0
- package/dist/src/cli/commands/browser/stream.d.ts +6 -0
- package/dist/src/cli/commands/browser/stream.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/stream.js +135 -0
- package/dist/src/cli/commands/browser/stream.js.map +1 -0
- package/dist/src/cli/commands/browser/tunnel.d.ts +13 -0
- package/dist/src/cli/commands/browser/tunnel.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/tunnel.js +225 -0
- package/dist/src/cli/commands/browser/tunnel.js.map +1 -0
- package/dist/src/cli/commands/browser/type.d.ts +6 -0
- package/dist/src/cli/commands/browser/type.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/type.js +61 -0
- package/dist/src/cli/commands/browser/type.js.map +1 -0
- package/dist/src/cli/commands/browser/uncheck.d.ts +6 -0
- package/dist/src/cli/commands/browser/uncheck.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/uncheck.js +62 -0
- package/dist/src/cli/commands/browser/uncheck.js.map +1 -0
- package/dist/src/cli/commands/browser/url.d.ts +6 -0
- package/dist/src/cli/commands/browser/url.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/url.js +40 -0
- package/dist/src/cli/commands/browser/url.js.map +1 -0
- package/dist/src/cli/commands/browser/wait-for-load.d.ts +6 -0
- package/dist/src/cli/commands/browser/wait-for-load.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/wait-for-load.js +50 -0
- package/dist/src/cli/commands/browser/wait-for-load.js.map +1 -0
- package/dist/src/cli/commands/browser/wait-for-selector.d.ts +6 -0
- package/dist/src/cli/commands/browser/wait-for-selector.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/wait-for-selector.js +52 -0
- package/dist/src/cli/commands/browser/wait-for-selector.js.map +1 -0
- package/dist/src/cli/commands/browser/wait.d.ts +6 -0
- package/dist/src/cli/commands/browser/wait.d.ts.map +1 -0
- package/dist/src/cli/commands/browser/wait.js +60 -0
- package/dist/src/cli/commands/browser/wait.js.map +1 -0
- package/dist/src/cli/commands/test/run.d.ts.map +1 -1
- package/dist/src/cli/commands/test/run.js +38 -7
- package/dist/src/cli/commands/test/run.js.map +1 -1
- package/dist/src/cli/index.js +2 -0
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/lib/browser-sessions.d.ts +72 -0
- package/dist/src/cli/lib/browser-sessions.d.ts.map +1 -0
- package/dist/src/cli/lib/browser-sessions.js +184 -0
- package/dist/src/cli/lib/browser-sessions.js.map +1 -0
- package/lib/api/browser-types.ts +278 -0
- package/lib/api/browser.test.ts +378 -0
- package/lib/api/browser.ts +279 -0
- package/package.json +2 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* qa-use browser wait-for-load - Wait for page load state
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { BrowserApiClient } from '../../../../lib/api/browser.js';
|
|
6
|
+
import { resolveSessionId, touchSession } from '../../lib/browser-sessions.js';
|
|
7
|
+
import { loadConfig } from '../../lib/config.js';
|
|
8
|
+
import { success, error } from '../../lib/output.js';
|
|
9
|
+
export const waitForLoadCommand = new Command('wait-for-load')
|
|
10
|
+
.description('Wait for page load state')
|
|
11
|
+
.option('-s, --session-id <id>', 'Session ID (auto-resolved if only one session)')
|
|
12
|
+
.option('--state <state>', 'Load state to wait for (load|domcontentloaded|networkidle)', 'load')
|
|
13
|
+
.option('--timeout <ms>', 'Timeout in milliseconds', '30000')
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
try {
|
|
16
|
+
const config = await loadConfig();
|
|
17
|
+
if (!config.api_key) {
|
|
18
|
+
console.log(error('API key not configured. Run `qa-use setup` first.'));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const client = new BrowserApiClient(config.api_url);
|
|
22
|
+
client.setApiKey(config.api_key);
|
|
23
|
+
const resolved = await resolveSessionId({
|
|
24
|
+
explicitId: options.sessionId,
|
|
25
|
+
client,
|
|
26
|
+
});
|
|
27
|
+
const state = options.state;
|
|
28
|
+
if (!['load', 'domcontentloaded', 'networkidle'].includes(state)) {
|
|
29
|
+
console.log(error('Invalid state. Must be: load, domcontentloaded, or networkidle'));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
const result = await client.executeAction(resolved.id, {
|
|
33
|
+
type: 'wait_for_load',
|
|
34
|
+
state,
|
|
35
|
+
});
|
|
36
|
+
if (result.success) {
|
|
37
|
+
console.log(success(`Page reached ${state} state`));
|
|
38
|
+
await touchSession(resolved.id);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
console.log(error(result.error || 'Wait for load failed'));
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
console.log(error(err instanceof Error ? err.message : 'Failed to wait for load'));
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=wait-for-load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait-for-load.js","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/wait-for-load.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAQrD,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,OAAO,CAAC,eAAe,CAAC;KAC3D,WAAW,CAAC,0BAA0B,CAAC;KACvC,MAAM,CAAC,uBAAuB,EAAE,gDAAgD,CAAC;KACjF,MAAM,CAAC,iBAAiB,EAAE,4DAA4D,EAAE,MAAM,CAAC;KAC/F,MAAM,CAAC,gBAAgB,EAAE,yBAAyB,EAAE,OAAO,CAAC;KAC5D,MAAM,CAAC,KAAK,EAAE,OAA2B,EAAE,EAAE;IAC5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEjC,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC;YACtC,UAAU,EAAE,OAAO,CAAC,SAAS;YAC7B,MAAM;SACP,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,OAAO,CAAC,KAAoD,CAAC;QAC3E,IAAI,CAAC,CAAC,MAAM,EAAE,kBAAkB,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACjE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC,CAAC;YACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE;YACrD,IAAI,EAAE,eAAe;YACrB,KAAK;SACN,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACpD,MAAM,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,sBAAsB,CAAC,CAAC,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC;QACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait-for-selector.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/wait-for-selector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,eAAO,MAAM,sBAAsB,SA6C/B,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* qa-use browser wait-for-selector - Wait for CSS selector to reach a state
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { BrowserApiClient } from '../../../../lib/api/browser.js';
|
|
6
|
+
import { resolveSessionId, touchSession } from '../../lib/browser-sessions.js';
|
|
7
|
+
import { loadConfig } from '../../lib/config.js';
|
|
8
|
+
import { success, error } from '../../lib/output.js';
|
|
9
|
+
export const waitForSelectorCommand = new Command('wait-for-selector')
|
|
10
|
+
.description('Wait for CSS selector to reach a state')
|
|
11
|
+
.argument('<selector>', 'CSS selector to wait for')
|
|
12
|
+
.option('-s, --session-id <id>', 'Session ID (auto-resolved if only one session)')
|
|
13
|
+
.option('--state <state>', 'State to wait for (visible|hidden|attached|detached)', 'visible')
|
|
14
|
+
.option('--timeout <ms>', 'Timeout in milliseconds', '30000')
|
|
15
|
+
.action(async (selector, options) => {
|
|
16
|
+
try {
|
|
17
|
+
const config = await loadConfig();
|
|
18
|
+
if (!config.api_key) {
|
|
19
|
+
console.log(error('API key not configured. Run `qa-use setup` first.'));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const client = new BrowserApiClient(config.api_url);
|
|
23
|
+
client.setApiKey(config.api_key);
|
|
24
|
+
const resolved = await resolveSessionId({
|
|
25
|
+
explicitId: options.sessionId,
|
|
26
|
+
client,
|
|
27
|
+
});
|
|
28
|
+
const state = options.state;
|
|
29
|
+
if (!['visible', 'hidden', 'attached', 'detached'].includes(state)) {
|
|
30
|
+
console.log(error('Invalid state. Must be: visible, hidden, attached, or detached'));
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
const result = await client.executeAction(resolved.id, {
|
|
34
|
+
type: 'wait_for_selector',
|
|
35
|
+
selector,
|
|
36
|
+
state,
|
|
37
|
+
});
|
|
38
|
+
if (result.success) {
|
|
39
|
+
console.log(success(`Selector "${selector}" is ${state}`));
|
|
40
|
+
await touchSession(resolved.id);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.log(error(result.error || 'Wait for selector failed'));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
console.log(error(err instanceof Error ? err.message : 'Failed to wait for selector'));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=wait-for-selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait-for-selector.js","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/wait-for-selector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAQrD,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,OAAO,CAAC,mBAAmB,CAAC;KACnE,WAAW,CAAC,wCAAwC,CAAC;KACrD,QAAQ,CAAC,YAAY,EAAE,0BAA0B,CAAC;KAClD,MAAM,CAAC,uBAAuB,EAAE,gDAAgD,CAAC;KACjF,MAAM,CAAC,iBAAiB,EAAE,sDAAsD,EAAE,SAAS,CAAC;KAC5F,MAAM,CAAC,gBAAgB,EAAE,yBAAyB,EAAE,OAAO,CAAC;KAC5D,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,OAA+B,EAAE,EAAE;IAClE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEjC,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC;YACtC,UAAU,EAAE,OAAO,CAAC,SAAS;YAC7B,MAAM;SACP,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,OAAO,CAAC,KAAuD,CAAC;QAC9E,IAAI,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACnE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC,CAAC;YACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE;YACrD,IAAI,EAAE,mBAAmB;YACzB,QAAQ;YACR,KAAK;SACN,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,QAAQ,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC;YAC3D,MAAM,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,0BAA0B,CAAC,CAAC,CAAC;YAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC;QACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/wait.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,WAAW,SAsDpB,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* qa-use browser wait - Wait for a fixed duration
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { BrowserApiClient } from '../../../../lib/api/browser.js';
|
|
6
|
+
import { resolveSessionId, touchSession } from '../../lib/browser-sessions.js';
|
|
7
|
+
import { loadConfig } from '../../lib/config.js';
|
|
8
|
+
import { success, error } from '../../lib/output.js';
|
|
9
|
+
export const waitCommand = new Command('wait')
|
|
10
|
+
.description('Wait for a specified duration')
|
|
11
|
+
.argument('<ms>', 'Duration to wait in milliseconds')
|
|
12
|
+
.option('-s, --session-id <id>', 'Session ID (auto-resolved if only one session)')
|
|
13
|
+
.action(async (msStr, options) => {
|
|
14
|
+
try {
|
|
15
|
+
// Load configuration
|
|
16
|
+
const config = await loadConfig();
|
|
17
|
+
if (!config.api_key) {
|
|
18
|
+
console.log(error('API key not configured. Run `qa-use setup` first.'));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
// Parse duration
|
|
22
|
+
const durationMs = parseInt(msStr, 10);
|
|
23
|
+
if (isNaN(durationMs) || durationMs <= 0) {
|
|
24
|
+
console.log(error('Duration must be a positive number in milliseconds'));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
if (durationMs > 60000) {
|
|
28
|
+
console.log(error('Maximum wait duration is 60000ms (1 minute)'));
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
// Create client and set API key
|
|
32
|
+
const client = new BrowserApiClient(config.api_url);
|
|
33
|
+
client.setApiKey(config.api_key);
|
|
34
|
+
// Resolve session ID
|
|
35
|
+
const resolved = await resolveSessionId({
|
|
36
|
+
explicitId: options.sessionId,
|
|
37
|
+
client,
|
|
38
|
+
});
|
|
39
|
+
// Execute wait action
|
|
40
|
+
const result = await client.executeAction(resolved.id, {
|
|
41
|
+
type: 'wait',
|
|
42
|
+
duration_ms: durationMs,
|
|
43
|
+
});
|
|
44
|
+
if (result.success) {
|
|
45
|
+
// Format duration for display
|
|
46
|
+
const displayDuration = durationMs >= 1000 ? `${durationMs / 1000}s` : `${durationMs}ms`;
|
|
47
|
+
console.log(success(`Waited ${displayDuration}`));
|
|
48
|
+
await touchSession(resolved.id);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log(error(result.error || 'Wait failed'));
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
console.log(error(err instanceof Error ? err.message : 'Failed to wait'));
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=wait.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/wait.ts"],"names":[],"mappings":"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"}
|
|
@@ -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;AAgCpC,eAAO,MAAM,UAAU,
|
|
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;AAgCpC,eAAO,MAAM,UAAU,SAiMnB,CAAC"}
|
|
@@ -19,7 +19,9 @@ export const runCommand = new Command('run')
|
|
|
19
19
|
.option('--id <uuid>', 'Run cloud test by ID instead of local file')
|
|
20
20
|
.option('--all', 'Run all tests in test directory')
|
|
21
21
|
.option('--persist', 'Save test to cloud after run')
|
|
22
|
-
.option('--
|
|
22
|
+
.option('--tunnel', 'Start local browser with tunnel (required for localhost URLs)')
|
|
23
|
+
.option('--headful', 'Show browser window (use with --tunnel)')
|
|
24
|
+
.option('--ws-url <url>', 'Use existing tunneled browser (from `browser create --tunnel`)')
|
|
23
25
|
.option('--autofix', 'Enable AI self-healing (default: off)')
|
|
24
26
|
.option('--screenshots', 'Capture screenshots at each step')
|
|
25
27
|
.option('--download', 'Download all assets (screenshots, recordings, HAR) to /tmp/qa-use/downloads/')
|
|
@@ -73,19 +75,48 @@ export const runCommand = new Command('run')
|
|
|
73
75
|
applyVariableOverrides(testDefinitions, options.var);
|
|
74
76
|
console.log(success(`Applied ${Object.keys(options.var).length} variable overrides\n`));
|
|
75
77
|
}
|
|
76
|
-
//
|
|
78
|
+
// Determine ws_url: from --ws-url flag, --tunnel (starts new browser), or none (backend browser)
|
|
77
79
|
let browserSession = null;
|
|
80
|
+
let wsUrl = options.wsUrl;
|
|
78
81
|
try {
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
// Validate flag combinations
|
|
83
|
+
if (options.wsUrl && (options.tunnel || options.headful)) {
|
|
84
|
+
console.log(error('Cannot use --ws-url with --tunnel or --headful'));
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
// Check if running in development mode (localhost API)
|
|
88
|
+
const isDevelopment = process.env.NODE_ENV === 'development' ||
|
|
89
|
+
config.api_url?.includes('localhost') ||
|
|
90
|
+
config.api_url?.includes('127.0.0.1');
|
|
91
|
+
// Handle --headful without --tunnel
|
|
92
|
+
if (options.headful && !options.tunnel) {
|
|
93
|
+
if (isDevelopment) {
|
|
94
|
+
// In development, allow --headful alone for backwards compatibility
|
|
95
|
+
console.log('⚠️ Note: --headful without --tunnel is deprecated. Use --tunnel --headful instead.');
|
|
96
|
+
options.tunnel = true; // Implicitly enable tunnel
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
console.log(error('--headful requires --tunnel flag'));
|
|
100
|
+
console.log(' Use: qa-use test run <name> --tunnel --headful');
|
|
101
|
+
console.log(' Or for headless local browser: qa-use test run <name> --tunnel');
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (options.tunnel) {
|
|
106
|
+
const headless = !options.headful;
|
|
107
|
+
console.log(`Starting local browser with tunnel (${headless ? 'headless' : 'visible'})...`);
|
|
81
108
|
console.log('⏳ First run may take a moment while the tunnel establishes connection');
|
|
82
109
|
browserSession = await startBrowserWithTunnel(undefined, {
|
|
83
|
-
headless
|
|
110
|
+
headless,
|
|
84
111
|
apiKey: config.api_key,
|
|
85
112
|
sessionIndex: 0,
|
|
86
113
|
});
|
|
114
|
+
wsUrl = getEffectiveWsUrl(browserSession);
|
|
87
115
|
console.log(success('Browser ready, running test...'));
|
|
88
116
|
}
|
|
117
|
+
else if (options.wsUrl) {
|
|
118
|
+
console.log(`Using existing tunneled browser: ${options.wsUrl}`);
|
|
119
|
+
}
|
|
89
120
|
// Clear any previous screenshots and downloads
|
|
90
121
|
clearStepScreenshots();
|
|
91
122
|
clearDownloadedFiles();
|
|
@@ -95,10 +126,10 @@ export const runCommand = new Command('run')
|
|
|
95
126
|
test_id: options.id,
|
|
96
127
|
persist: options.persist || config.defaults?.persist || false,
|
|
97
128
|
// When using ws_url, headless flag is irrelevant (backend uses our browser)
|
|
98
|
-
headless:
|
|
129
|
+
headless: wsUrl ? true : (config.defaults?.headless ?? true),
|
|
99
130
|
allow_fix: options.autofix || config.defaults?.allow_fix || false,
|
|
100
131
|
capture_screenshots: options.screenshots || options.download || false,
|
|
101
|
-
ws_url:
|
|
132
|
+
ws_url: wsUrl,
|
|
102
133
|
}, {
|
|
103
134
|
verbose: options.verbose || false,
|
|
104
135
|
updateLocal: options.updateLocal || false,
|
|
@@ -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":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,sBAAsB,EACtB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EACL,KAAK,EACL,OAAO,EACP,uBAAuB,EACvB,oBAAoB,EACpB,2BAA2B,EAC3B,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,GAElB,MAAM,sBAAsB,CAAC;AAE9B,SAAS,WAAW,CAAC,KAAa,EAAE,QAAgC;IAClE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC;KACzC,WAAW,CAAC,uBAAuB,CAAC;KACpC,QAAQ,CAAC,QAAQ,EAAE,sCAAsC,CAAC;KAC1D,MAAM,CAAC,aAAa,EAAE,4CAA4C,CAAC;KACnE,MAAM,CAAC,OAAO,EAAE,iCAAiC,CAAC;KAClD,MAAM,CAAC,WAAW,EAAE,8BAA8B,CAAC;KACnD,MAAM,CAAC,UAAU,EAAE,+DAA+D,CAAC;KACnF,MAAM,CAAC,WAAW,EAAE,yCAAyC,CAAC;KAC9D,MAAM,CAAC,gBAAgB,EAAE,gEAAgE,CAAC;KAC1F,MAAM,CAAC,WAAW,EAAE,uCAAuC,CAAC;KAC5D,MAAM,CAAC,eAAe,EAAE,kCAAkC,CAAC;KAC3D,MAAM,CACL,YAAY,EACZ,8EAA8E,CAC/E;KACA,MAAM,CAAC,sBAAsB,EAAE,oBAAoB,EAAE,WAAW,EAAE,EAAE,CAAC;KACrE,MAAM,CAAC,wBAAwB,EAAE,sBAAsB,CAAC;KACxD,MAAM,CAAC,qBAAqB,EAAE,oBAAoB,EAAE,KAAK,CAAC;KAC1D,MAAM,CAAC,WAAW,EAAE,yCAAyC,CAAC;KAC9D,MAAM,CAAC,gBAAgB,EAAE,oDAAoD,CAAC;KAC9E,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IAC9B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAElC,gBAAgB;QAChB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC;YAC7C,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,wBAAwB;QACxB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEjC,IAAI,eAAe,CAAC;QACpB,IAAI,UAA8B,CAAC;QAEnC,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;YACf,+CAA+C;YAC/C,eAAe,GAAG,SAAS,CAAC;QAC9B,CAAC;aAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YACvB,4BAA4B;YAC5B,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YACpC,eAAe,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,cAAc,IAAI,YAAY,CAAC,CAAC;YAC5E,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,eAAe,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC;YACjE,uDAAuD;QACzD,CAAC;aAAM,IAAI,IAAI,EAAE,CAAC;YAChB,0CAA0C;YAC1C,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,KAAK,CAAC,CAAC;YACxC,MAAM,OAAO,GAAG,MAAM,CAAC,cAAc,IAAI,YAAY,CAAC;YACtD,eAAe,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACxD,+CAA+C;YAC/C,UAAU,GAAG,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,eAAe,CAAC,MAAM,YAAY,CAAC,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,2BAA2B;QAC3B,IAAI,eAAe,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3D,sBAAsB,CAAC,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;YACrD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,uBAAuB,CAAC,CAAC,CAAC;QAC1F,CAAC;QAED,iGAAiG;QACjG,IAAI,cAAc,GAAgC,IAAI,CAAC;QACvD,IAAI,KAAK,GAAuB,OAAO,CAAC,KAAK,CAAC;QAE9C,IAAI,CAAC;YACH,6BAA6B;YAC7B,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC,CAAC;gBACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,uDAAuD;YACvD,MAAM,aAAa,GACjB,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;gBACtC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC;gBACrC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;YAExC,oCAAoC;YACpC,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBACvC,IAAI,aAAa,EAAE,CAAC;oBAClB,oEAAoE;oBACpE,OAAO,CAAC,GAAG,CACT,qFAAqF,CACtF,CAAC;oBACF,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,2BAA2B;gBACpD,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC;oBACvD,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;oBAChE,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;oBAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;YACH,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;gBAClC,OAAO,CAAC,GAAG,CACT,uCAAuC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,MAAM,CAC/E,CAAC;gBACF,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;gBACrF,cAAc,GAAG,MAAM,sBAAsB,CAAC,SAAS,EAAE;oBACvD,QAAQ;oBACR,MAAM,EAAE,MAAM,CAAC,OAAO;oBACtB,YAAY,EAAE,CAAC;iBAChB,CAAC,CAAC;gBACH,KAAK,GAAG,iBAAiB,CAAC,cAAc,CAAC,CAAC;gBAC1C,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC,CAAC;YACzD,CAAC;iBAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,oCAAoC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;YACnE,CAAC;YAED,+CAA+C;YAC/C,oBAAoB,EAAE,CAAC;YACvB,oBAAoB,EAAE,CAAC;YAEvB,kCAAkC;YAClC,MAAM,MAAM,GAAG,MAAM,OAAO,CAC1B,MAAM,EACN;gBACE,gBAAgB,EAAE,eAAe;gBACjC,OAAO,EAAE,OAAO,CAAC,EAAE;gBACnB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,OAAO,IAAI,KAAK;gBAC7D,4EAA4E;gBAC5E,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,IAAI,IAAI,CAAC;gBAC5D,SAAS,EAAE,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,SAAS,IAAI,KAAK;gBACjE,mBAAmB,EAAE,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,QAAQ,IAAI,KAAK;gBACrE,MAAM,EAAE,KAAK;aACd,EACD;gBACE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK;gBACjC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,KAAK;gBACzC,UAAU;gBACV,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK;gBACnC,eAAe,EAAE,uBAAuB;gBACxC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,SAAS;aAC9C,CACF,CAAC;YAEF,kDAAkD;YAClD,IAAI,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBACvD,MAAM,gBAAgB,GAAG,MAAM,cAAc,CAC3C,MAAM,CAAC,MAAM,EACb,uBAAuB,EACvB,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,SAAS,EACrC,MAAM,CAAC,MAAM,EACb,UAAU,CACX,CAAC;gBACF,6CAA6C;gBAC7C,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;oBACrC,iBAAiB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC;YAED,uBAAuB;YACvB,uBAAuB,EAAE,CAAC;YAE1B,wCAAwC;YACxC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACrB,2BAA2B,EAAE,CAAC;YAChC,CAAC;YAED,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACzB,IAAI,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;oBAChC,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC;gBAC7D,CAAC;gBACD,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBAC1B,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;YAED,6BAA6B;YAC7B,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,6BAA6B;YAC7B,IAAI,cAAc,EAAE,CAAC;gBACnB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;gBACjD,MAAM,qBAAqB,CAAC,cAAc,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,0BAA0B,GAAG,EAAE,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
package/dist/src/cli/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { setupCommand } from './commands/setup.js';
|
|
|
8
8
|
import { infoCommand } from './commands/info.js';
|
|
9
9
|
import { testCommand } from './commands/test/index.js';
|
|
10
10
|
import { mcpCommand } from './commands/mcp.js';
|
|
11
|
+
import { browserCommand } from './commands/browser/index.js';
|
|
11
12
|
// Get version from package.json
|
|
12
13
|
const require = createRequire(import.meta.url);
|
|
13
14
|
const { version } = require('../../package.json');
|
|
@@ -18,6 +19,7 @@ program.addCommand(setupCommand);
|
|
|
18
19
|
program.addCommand(infoCommand);
|
|
19
20
|
program.addCommand(testCommand);
|
|
20
21
|
program.addCommand(mcpCommand);
|
|
22
|
+
program.addCommand(browserCommand);
|
|
21
23
|
// Parse command line arguments
|
|
22
24
|
program.parse();
|
|
23
25
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":";AAEA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":";AAEA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,gCAAgC;AAChC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAElD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,oCAAoC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAE1F,oBAAoB;AACpB,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AAEnC,+BAA+B;AAC/B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser session persistence utilities
|
|
3
|
+
*
|
|
4
|
+
* Stores active browser sessions in ~/.qa-use.json under "browser_sessions" key.
|
|
5
|
+
* Provides session resolution logic for commands that need a session ID.
|
|
6
|
+
*/
|
|
7
|
+
import type { BrowserApiClient } from '../../../lib/api/browser.js';
|
|
8
|
+
export interface StoredSession {
|
|
9
|
+
id: string;
|
|
10
|
+
created_at: string;
|
|
11
|
+
last_updated: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Load all stored sessions from config file
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadStoredSessions(): Promise<StoredSession[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Store a new session or update an existing one
|
|
19
|
+
*/
|
|
20
|
+
export declare function storeSession(session: StoredSession): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Remove a session from storage by ID
|
|
23
|
+
*/
|
|
24
|
+
export declare function removeStoredSession(id: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Update the last_updated timestamp for a session
|
|
27
|
+
*/
|
|
28
|
+
export declare function touchSession(id: string): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Check if a session is stale (last_updated > 1 hour ago)
|
|
31
|
+
*/
|
|
32
|
+
export declare function isSessionStale(session: StoredSession): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Clean up stale sessions from storage
|
|
35
|
+
* Note: This only removes from local storage, does not close sessions on API
|
|
36
|
+
*/
|
|
37
|
+
export declare function cleanStaleSessions(): Promise<StoredSession[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Get non-stale sessions
|
|
40
|
+
*/
|
|
41
|
+
export declare function getActiveSessions(): Promise<StoredSession[]>;
|
|
42
|
+
export interface SessionResolutionOptions {
|
|
43
|
+
/** Explicit session ID from -s/--session-id flag */
|
|
44
|
+
explicitId?: string;
|
|
45
|
+
/** The BrowserApiClient to use for verification */
|
|
46
|
+
client: BrowserApiClient;
|
|
47
|
+
/** Whether to verify the session exists on the API (default: true) */
|
|
48
|
+
verify?: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface ResolvedSession {
|
|
51
|
+
id: string;
|
|
52
|
+
source: 'explicit' | 'stored';
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolve which session ID to use based on provided flags and stored sessions.
|
|
56
|
+
*
|
|
57
|
+
* Resolution rules:
|
|
58
|
+
* 1. If explicitId is provided, use that session
|
|
59
|
+
* 2. Otherwise, check stored sessions:
|
|
60
|
+
* - Filter out stale sessions
|
|
61
|
+
* - If exactly one active session, use it
|
|
62
|
+
* - If multiple active sessions, throw error listing them
|
|
63
|
+
* - If no active sessions, throw error with create suggestion
|
|
64
|
+
*
|
|
65
|
+
* @throws Error if no session can be resolved or verification fails
|
|
66
|
+
*/
|
|
67
|
+
export declare function resolveSessionId(options: SessionResolutionOptions): Promise<ResolvedSession>;
|
|
68
|
+
/**
|
|
69
|
+
* Create a new stored session entry
|
|
70
|
+
*/
|
|
71
|
+
export declare function createStoredSession(id: string): StoredSession;
|
|
72
|
+
//# sourceMappingURL=browser-sessions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-sessions.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/browser-sessions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAMpE,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AA6CD;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAGnE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBxE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMnE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS5D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAI9D;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAWnE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAGlE;AAMD,MAAM,WAAW,wBAAwB;IACvC,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,MAAM,EAAE,gBAAgB,CAAC;IACzB,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC;CAC/B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,eAAe,CAAC,CAsD1B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,CAO7D"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser session persistence utilities
|
|
3
|
+
*
|
|
4
|
+
* Stores active browser sessions in ~/.qa-use.json under "browser_sessions" key.
|
|
5
|
+
* Provides session resolution logic for commands that need a session ID.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
import { homedir } from 'os';
|
|
10
|
+
// ==========================================
|
|
11
|
+
// Configuration
|
|
12
|
+
// ==========================================
|
|
13
|
+
const CONFIG_PATH = join(homedir(), '.qa-use.json');
|
|
14
|
+
const STALE_THRESHOLD_MS = 60 * 60 * 1000; // 1 hour
|
|
15
|
+
// ==========================================
|
|
16
|
+
// Config File Operations
|
|
17
|
+
// ==========================================
|
|
18
|
+
/**
|
|
19
|
+
* Load the config file from ~/.qa-use.json
|
|
20
|
+
*/
|
|
21
|
+
function loadConfig() {
|
|
22
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const content = readFileSync(CONFIG_PATH, 'utf-8');
|
|
27
|
+
return JSON.parse(content);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Save the config file to ~/.qa-use.json
|
|
35
|
+
*/
|
|
36
|
+
function saveConfig(config) {
|
|
37
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
38
|
+
}
|
|
39
|
+
// ==========================================
|
|
40
|
+
// Session Storage Operations
|
|
41
|
+
// ==========================================
|
|
42
|
+
/**
|
|
43
|
+
* Load all stored sessions from config file
|
|
44
|
+
*/
|
|
45
|
+
export async function loadStoredSessions() {
|
|
46
|
+
const config = loadConfig();
|
|
47
|
+
return config.browser_sessions || [];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Store a new session or update an existing one
|
|
51
|
+
*/
|
|
52
|
+
export async function storeSession(session) {
|
|
53
|
+
const config = loadConfig();
|
|
54
|
+
const sessions = config.browser_sessions || [];
|
|
55
|
+
// Find existing session with same ID
|
|
56
|
+
const existingIndex = sessions.findIndex((s) => s.id === session.id);
|
|
57
|
+
if (existingIndex >= 0) {
|
|
58
|
+
// Update existing session
|
|
59
|
+
sessions[existingIndex] = session;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Add new session
|
|
63
|
+
sessions.push(session);
|
|
64
|
+
}
|
|
65
|
+
config.browser_sessions = sessions;
|
|
66
|
+
saveConfig(config);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Remove a session from storage by ID
|
|
70
|
+
*/
|
|
71
|
+
export async function removeStoredSession(id) {
|
|
72
|
+
const config = loadConfig();
|
|
73
|
+
const sessions = config.browser_sessions || [];
|
|
74
|
+
config.browser_sessions = sessions.filter((s) => s.id !== id);
|
|
75
|
+
saveConfig(config);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Update the last_updated timestamp for a session
|
|
79
|
+
*/
|
|
80
|
+
export async function touchSession(id) {
|
|
81
|
+
const config = loadConfig();
|
|
82
|
+
const sessions = config.browser_sessions || [];
|
|
83
|
+
const session = sessions.find((s) => s.id === id);
|
|
84
|
+
if (session) {
|
|
85
|
+
session.last_updated = new Date().toISOString();
|
|
86
|
+
saveConfig(config);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if a session is stale (last_updated > 1 hour ago)
|
|
91
|
+
*/
|
|
92
|
+
export function isSessionStale(session) {
|
|
93
|
+
const lastUpdated = new Date(session.last_updated).getTime();
|
|
94
|
+
const now = Date.now();
|
|
95
|
+
return now - lastUpdated > STALE_THRESHOLD_MS;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Clean up stale sessions from storage
|
|
99
|
+
* Note: This only removes from local storage, does not close sessions on API
|
|
100
|
+
*/
|
|
101
|
+
export async function cleanStaleSessions() {
|
|
102
|
+
const config = loadConfig();
|
|
103
|
+
const sessions = config.browser_sessions || [];
|
|
104
|
+
const stale = sessions.filter(isSessionStale);
|
|
105
|
+
const active = sessions.filter((s) => !isSessionStale(s));
|
|
106
|
+
config.browser_sessions = active;
|
|
107
|
+
saveConfig(config);
|
|
108
|
+
return stale;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get non-stale sessions
|
|
112
|
+
*/
|
|
113
|
+
export async function getActiveSessions() {
|
|
114
|
+
const sessions = await loadStoredSessions();
|
|
115
|
+
return sessions.filter((s) => !isSessionStale(s));
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Resolve which session ID to use based on provided flags and stored sessions.
|
|
119
|
+
*
|
|
120
|
+
* Resolution rules:
|
|
121
|
+
* 1. If explicitId is provided, use that session
|
|
122
|
+
* 2. Otherwise, check stored sessions:
|
|
123
|
+
* - Filter out stale sessions
|
|
124
|
+
* - If exactly one active session, use it
|
|
125
|
+
* - If multiple active sessions, throw error listing them
|
|
126
|
+
* - If no active sessions, throw error with create suggestion
|
|
127
|
+
*
|
|
128
|
+
* @throws Error if no session can be resolved or verification fails
|
|
129
|
+
*/
|
|
130
|
+
export async function resolveSessionId(options) {
|
|
131
|
+
const { explicitId, client, verify = true } = options;
|
|
132
|
+
let sessionId;
|
|
133
|
+
let source;
|
|
134
|
+
if (explicitId) {
|
|
135
|
+
// Use explicit session ID
|
|
136
|
+
sessionId = explicitId;
|
|
137
|
+
source = 'explicit';
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
// Get non-stale stored sessions
|
|
141
|
+
const activeSessions = await getActiveSessions();
|
|
142
|
+
if (activeSessions.length === 0) {
|
|
143
|
+
throw new Error('No active session found. Run `qa-use browser create` to create a new session.');
|
|
144
|
+
}
|
|
145
|
+
if (activeSessions.length > 1) {
|
|
146
|
+
const sessionList = activeSessions.map((s) => ` - ${s.id}`).join('\n');
|
|
147
|
+
throw new Error(`Multiple active sessions found. Please specify one with -s/--session-id:\n${sessionList}`);
|
|
148
|
+
}
|
|
149
|
+
// Exactly one active session
|
|
150
|
+
sessionId = activeSessions[0].id;
|
|
151
|
+
source = 'stored';
|
|
152
|
+
}
|
|
153
|
+
// Verify session exists on API if requested
|
|
154
|
+
if (verify) {
|
|
155
|
+
try {
|
|
156
|
+
await client.getSession(sessionId);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
// If session not found on API, remove from local storage
|
|
160
|
+
await removeStoredSession(sessionId);
|
|
161
|
+
if (source === 'stored') {
|
|
162
|
+
throw new Error(`Stored session ${sessionId} is no longer active. Run \`qa-use browser create\` to create a new session.`);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
throw new Error(`Session ${sessionId} not found.`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Update last_updated timestamp since we just verified it
|
|
169
|
+
await touchSession(sessionId);
|
|
170
|
+
}
|
|
171
|
+
return { id: sessionId, source };
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Create a new stored session entry
|
|
175
|
+
*/
|
|
176
|
+
export function createStoredSession(id) {
|
|
177
|
+
const now = new Date().toISOString();
|
|
178
|
+
return {
|
|
179
|
+
id,
|
|
180
|
+
created_at: now,
|
|
181
|
+
last_updated: now,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=browser-sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-sessions.js","sourceRoot":"","sources":["../../../../src/cli/lib/browser-sessions.ts"],"names":[],"mappings":"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"}
|