@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,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the Browser API (/browsers/v1/)
|
|
3
|
+
*/
|
|
4
|
+
export type BrowserSessionStatus = 'starting' | 'active' | 'closing' | 'closed';
|
|
5
|
+
export type ViewportType = 'desktop' | 'mobile' | 'tablet';
|
|
6
|
+
export interface CreateBrowserSessionOptions {
|
|
7
|
+
headless?: boolean;
|
|
8
|
+
viewport?: ViewportType;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
ws_url?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface BrowserSession {
|
|
13
|
+
id: string;
|
|
14
|
+
status: BrowserSessionStatus;
|
|
15
|
+
created_at: string;
|
|
16
|
+
updated_at?: string;
|
|
17
|
+
current_url?: string;
|
|
18
|
+
viewport?: ViewportType;
|
|
19
|
+
headless?: boolean;
|
|
20
|
+
timeout?: number;
|
|
21
|
+
}
|
|
22
|
+
export type BrowserActionType = 'goto' | 'back' | 'forward' | 'reload' | 'click' | 'fill' | 'type' | 'press' | 'hover' | 'scroll' | 'scroll_into_view' | 'select' | 'check' | 'uncheck' | 'wait' | 'wait_for_selector' | 'wait_for_load' | 'snapshot' | 'screenshot';
|
|
23
|
+
export type ScrollDirection = 'up' | 'down' | 'left' | 'right';
|
|
24
|
+
export interface GotoAction {
|
|
25
|
+
type: 'goto';
|
|
26
|
+
url: string;
|
|
27
|
+
}
|
|
28
|
+
export interface BackAction {
|
|
29
|
+
type: 'back';
|
|
30
|
+
}
|
|
31
|
+
export interface ForwardAction {
|
|
32
|
+
type: 'forward';
|
|
33
|
+
}
|
|
34
|
+
export interface ReloadAction {
|
|
35
|
+
type: 'reload';
|
|
36
|
+
}
|
|
37
|
+
export interface ClickAction {
|
|
38
|
+
type: 'click';
|
|
39
|
+
ref?: string;
|
|
40
|
+
text?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface FillAction {
|
|
43
|
+
type: 'fill';
|
|
44
|
+
ref?: string;
|
|
45
|
+
text?: string;
|
|
46
|
+
value: string;
|
|
47
|
+
}
|
|
48
|
+
export interface TypeAction {
|
|
49
|
+
type: 'type';
|
|
50
|
+
ref: string;
|
|
51
|
+
text: string;
|
|
52
|
+
}
|
|
53
|
+
export interface PressAction {
|
|
54
|
+
type: 'press';
|
|
55
|
+
key: string;
|
|
56
|
+
}
|
|
57
|
+
export interface HoverAction {
|
|
58
|
+
type: 'hover';
|
|
59
|
+
ref?: string;
|
|
60
|
+
text?: string;
|
|
61
|
+
}
|
|
62
|
+
export interface ScrollAction {
|
|
63
|
+
type: 'scroll';
|
|
64
|
+
direction: ScrollDirection;
|
|
65
|
+
amount?: number;
|
|
66
|
+
}
|
|
67
|
+
export interface SelectAction {
|
|
68
|
+
type: 'select';
|
|
69
|
+
ref?: string;
|
|
70
|
+
text?: string;
|
|
71
|
+
value: string;
|
|
72
|
+
}
|
|
73
|
+
export interface CheckAction {
|
|
74
|
+
type: 'check';
|
|
75
|
+
ref?: string;
|
|
76
|
+
text?: string;
|
|
77
|
+
}
|
|
78
|
+
export interface UncheckAction {
|
|
79
|
+
type: 'uncheck';
|
|
80
|
+
ref?: string;
|
|
81
|
+
text?: string;
|
|
82
|
+
}
|
|
83
|
+
export interface ScrollIntoViewAction {
|
|
84
|
+
type: 'scroll_into_view';
|
|
85
|
+
ref?: string;
|
|
86
|
+
text?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface WaitAction {
|
|
89
|
+
type: 'wait';
|
|
90
|
+
duration_ms: number;
|
|
91
|
+
}
|
|
92
|
+
export interface WaitForSelectorAction {
|
|
93
|
+
type: 'wait_for_selector';
|
|
94
|
+
selector: string;
|
|
95
|
+
state?: 'visible' | 'hidden' | 'attached' | 'detached';
|
|
96
|
+
}
|
|
97
|
+
export interface WaitForLoadAction {
|
|
98
|
+
type: 'wait_for_load';
|
|
99
|
+
state?: 'load' | 'domcontentloaded' | 'networkidle';
|
|
100
|
+
}
|
|
101
|
+
export interface SnapshotAction {
|
|
102
|
+
type: 'snapshot';
|
|
103
|
+
}
|
|
104
|
+
export interface ScreenshotAction {
|
|
105
|
+
type: 'screenshot';
|
|
106
|
+
}
|
|
107
|
+
export type BrowserAction = GotoAction | BackAction | ForwardAction | ReloadAction | ClickAction | FillAction | TypeAction | PressAction | HoverAction | ScrollAction | ScrollIntoViewAction | SelectAction | CheckAction | UncheckAction | WaitAction | WaitForSelectorAction | WaitForLoadAction | SnapshotAction | ScreenshotAction;
|
|
108
|
+
export interface ActionResult {
|
|
109
|
+
success: boolean;
|
|
110
|
+
error?: string;
|
|
111
|
+
data?: unknown;
|
|
112
|
+
}
|
|
113
|
+
export interface SnapshotResult {
|
|
114
|
+
snapshot: string;
|
|
115
|
+
url?: string;
|
|
116
|
+
}
|
|
117
|
+
export interface UrlResult {
|
|
118
|
+
url: string;
|
|
119
|
+
}
|
|
120
|
+
export interface BlocksResult {
|
|
121
|
+
blocks: unknown[];
|
|
122
|
+
}
|
|
123
|
+
export type WebSocketEventType = 'action_started' | 'action_completed' | 'status_changed' | 'error' | 'closed';
|
|
124
|
+
export interface WebSocketEvent {
|
|
125
|
+
type: WebSocketEventType;
|
|
126
|
+
data?: unknown;
|
|
127
|
+
timestamp?: string;
|
|
128
|
+
}
|
|
129
|
+
export interface ActionStartedEvent extends WebSocketEvent {
|
|
130
|
+
type: 'action_started';
|
|
131
|
+
data: {
|
|
132
|
+
action_type: BrowserActionType;
|
|
133
|
+
action_id?: string;
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
export interface ActionCompletedEvent extends WebSocketEvent {
|
|
137
|
+
type: 'action_completed';
|
|
138
|
+
data: {
|
|
139
|
+
action_id?: string;
|
|
140
|
+
success: boolean;
|
|
141
|
+
error?: string;
|
|
142
|
+
result?: unknown;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export interface StatusChangedEvent extends WebSocketEvent {
|
|
146
|
+
type: 'status_changed';
|
|
147
|
+
data: {
|
|
148
|
+
status: BrowserSessionStatus;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
export interface ErrorEvent extends WebSocketEvent {
|
|
152
|
+
type: 'error';
|
|
153
|
+
data: {
|
|
154
|
+
message: string;
|
|
155
|
+
code?: string;
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
export interface ClosedEvent extends WebSocketEvent {
|
|
159
|
+
type: 'closed';
|
|
160
|
+
data?: {
|
|
161
|
+
reason?: string;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
export interface PingMessage {
|
|
165
|
+
type: 'ping';
|
|
166
|
+
}
|
|
167
|
+
export interface ActionMessage {
|
|
168
|
+
type: 'action';
|
|
169
|
+
data: BrowserAction;
|
|
170
|
+
}
|
|
171
|
+
export interface GetStatusMessage {
|
|
172
|
+
type: 'get_status';
|
|
173
|
+
}
|
|
174
|
+
export type ClientMessage = PingMessage | ActionMessage | GetStatusMessage;
|
|
175
|
+
//# sourceMappingURL=browser-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-types.d.ts","sourceRoot":"","sources":["../../../lib/api/browser-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-types.js","sourceRoot":"","sources":["../../../lib/api/browser-types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BrowserApiClient - Client for the desplega.ai Browser API (/browsers/v1/)
|
|
3
|
+
*/
|
|
4
|
+
import type { BrowserSession, BrowserAction, ActionResult, SnapshotResult, CreateBrowserSessionOptions, BrowserSessionStatus } from './browser-types.js';
|
|
5
|
+
import type { ExtendedStep } from '../../src/types/test-definition.js';
|
|
6
|
+
export declare class BrowserApiClient {
|
|
7
|
+
private readonly client;
|
|
8
|
+
private apiKey;
|
|
9
|
+
constructor(baseUrl?: string);
|
|
10
|
+
setApiKey(apiKey: string): void;
|
|
11
|
+
getApiKey(): string | null;
|
|
12
|
+
getBaseUrl(): string;
|
|
13
|
+
/**
|
|
14
|
+
* Create a new browser session
|
|
15
|
+
*/
|
|
16
|
+
createSession(options?: CreateBrowserSessionOptions): Promise<BrowserSession>;
|
|
17
|
+
/**
|
|
18
|
+
* List all sessions for the organization
|
|
19
|
+
*/
|
|
20
|
+
listSessions(): Promise<BrowserSession[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Get a specific session by ID
|
|
23
|
+
*/
|
|
24
|
+
getSession(sessionId: string): Promise<BrowserSession>;
|
|
25
|
+
/**
|
|
26
|
+
* Delete/close a session
|
|
27
|
+
*/
|
|
28
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Wait for a session to reach a specific status
|
|
31
|
+
* @param sessionId - The session ID to wait for
|
|
32
|
+
* @param targetStatus - The status to wait for (default: 'active')
|
|
33
|
+
* @param timeoutMs - Maximum time to wait in milliseconds (default: 30000)
|
|
34
|
+
* @param pollIntervalMs - Polling interval in milliseconds (default: 1000)
|
|
35
|
+
*/
|
|
36
|
+
waitForStatus(sessionId: string, targetStatus?: BrowserSessionStatus, timeoutMs?: number, pollIntervalMs?: number): Promise<BrowserSession>;
|
|
37
|
+
/**
|
|
38
|
+
* Execute a browser action
|
|
39
|
+
*/
|
|
40
|
+
executeAction(sessionId: string, action: BrowserAction): Promise<ActionResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Get the ARIA accessibility tree snapshot
|
|
43
|
+
*/
|
|
44
|
+
getSnapshot(sessionId: string): Promise<SnapshotResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Get a screenshot of the current page
|
|
47
|
+
* @returns Buffer containing PNG image data
|
|
48
|
+
*/
|
|
49
|
+
getScreenshot(sessionId: string): Promise<Buffer>;
|
|
50
|
+
/**
|
|
51
|
+
* Get the current page URL
|
|
52
|
+
*/
|
|
53
|
+
getUrl(sessionId: string): Promise<string>;
|
|
54
|
+
/**
|
|
55
|
+
* Get recorded blocks (test steps) from the session
|
|
56
|
+
* @returns Array of ExtendedStep objects
|
|
57
|
+
*/
|
|
58
|
+
getBlocks(sessionId: string): Promise<ExtendedStep[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Get the WebSocket URL for streaming events
|
|
61
|
+
*/
|
|
62
|
+
getStreamUrl(sessionId: string): string;
|
|
63
|
+
private handleError;
|
|
64
|
+
}
|
|
65
|
+
export type { BrowserSession, BrowserAction, ActionResult, SnapshotResult, UrlResult, CreateBrowserSessionOptions, BrowserSessionStatus, } from './browser-types.js';
|
|
66
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../lib/api/browser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,YAAY,EACZ,cAAc,EAGd,2BAA2B,EAC3B,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAEvE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,MAAM,CAAuB;gBAEzB,OAAO,CAAC,EAAE,MAAM;IAmB5B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK/B,SAAS,IAAI,MAAM,GAAG,IAAI;IAI1B,UAAU,IAAI,MAAM;IAQpB;;OAEG;IACG,aAAa,CAAC,OAAO,GAAE,2BAAgC,GAAG,OAAO,CAAC,cAAc,CAAC;IAevF;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAU/C;;OAEG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAS5D;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrD;;;;;;OAMG;IACG,aAAa,CACjB,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,oBAA+B,EAC7C,SAAS,GAAE,MAAc,EACzB,cAAc,GAAE,MAAa,GAC5B,OAAO,CAAC,cAAc,CAAC;IA0B1B;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAapF;;OAEG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAS7D;;;OAGG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWvD;;OAEG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUhD;;;OAGG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAc3D;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAWvC,OAAO,CAAC,WAAW;CA4BpB;AAGD,YAAY,EACV,cAAc,EACd,aAAa,EACb,YAAY,EACZ,cAAc,EACd,SAAS,EACT,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BrowserApiClient - Client for the desplega.ai Browser API (/browsers/v1/)
|
|
3
|
+
*/
|
|
4
|
+
import axios from 'axios';
|
|
5
|
+
import { getEnv } from '../env/index.js';
|
|
6
|
+
export class BrowserApiClient {
|
|
7
|
+
client;
|
|
8
|
+
apiKey = null;
|
|
9
|
+
constructor(baseUrl) {
|
|
10
|
+
// Use environment variable if available, otherwise use provided baseUrl, finally fall back to production
|
|
11
|
+
const apiUrl = getEnv('QA_USE_API_URL') || baseUrl || 'https://api.desplega.ai';
|
|
12
|
+
this.client = axios.create({
|
|
13
|
+
baseURL: `${apiUrl}/browsers/v1`,
|
|
14
|
+
timeout: 60000, // Longer timeout for browser operations
|
|
15
|
+
headers: {
|
|
16
|
+
'Content-Type': 'application/json',
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
// Auto-load API key from environment or config file if available
|
|
20
|
+
const envApiKey = getEnv('QA_USE_API_KEY');
|
|
21
|
+
if (envApiKey) {
|
|
22
|
+
this.setApiKey(envApiKey);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
setApiKey(apiKey) {
|
|
26
|
+
this.apiKey = apiKey;
|
|
27
|
+
this.client.defaults.headers['Authorization'] = `Bearer ${apiKey}`;
|
|
28
|
+
}
|
|
29
|
+
getApiKey() {
|
|
30
|
+
return this.apiKey;
|
|
31
|
+
}
|
|
32
|
+
getBaseUrl() {
|
|
33
|
+
return this.client.defaults.baseURL || 'https://api.desplega.ai/browsers/v1';
|
|
34
|
+
}
|
|
35
|
+
// ==========================================
|
|
36
|
+
// Session Management
|
|
37
|
+
// ==========================================
|
|
38
|
+
/**
|
|
39
|
+
* Create a new browser session
|
|
40
|
+
*/
|
|
41
|
+
async createSession(options = {}) {
|
|
42
|
+
try {
|
|
43
|
+
const response = await this.client.post('/sessions', {
|
|
44
|
+
headless: options.headless ?? true,
|
|
45
|
+
viewport: options.viewport ?? 'desktop',
|
|
46
|
+
timeout: options.timeout ?? 300,
|
|
47
|
+
...(options.ws_url && { ws_url: options.ws_url }),
|
|
48
|
+
});
|
|
49
|
+
return response.data;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
throw this.handleError(error, 'create session');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* List all sessions for the organization
|
|
57
|
+
*/
|
|
58
|
+
async listSessions() {
|
|
59
|
+
try {
|
|
60
|
+
const response = await this.client.get('/sessions');
|
|
61
|
+
// API may return { sessions: [...] } or just [...]
|
|
62
|
+
return Array.isArray(response.data) ? response.data : response.data.sessions || [];
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
throw this.handleError(error, 'list sessions');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get a specific session by ID
|
|
70
|
+
*/
|
|
71
|
+
async getSession(sessionId) {
|
|
72
|
+
try {
|
|
73
|
+
const response = await this.client.get(`/sessions/${sessionId}`);
|
|
74
|
+
return response.data;
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
throw this.handleError(error, 'get session');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Delete/close a session
|
|
82
|
+
*/
|
|
83
|
+
async deleteSession(sessionId) {
|
|
84
|
+
try {
|
|
85
|
+
await this.client.delete(`/sessions/${sessionId}`);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
throw this.handleError(error, 'delete session');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Wait for a session to reach a specific status
|
|
93
|
+
* @param sessionId - The session ID to wait for
|
|
94
|
+
* @param targetStatus - The status to wait for (default: 'active')
|
|
95
|
+
* @param timeoutMs - Maximum time to wait in milliseconds (default: 30000)
|
|
96
|
+
* @param pollIntervalMs - Polling interval in milliseconds (default: 1000)
|
|
97
|
+
*/
|
|
98
|
+
async waitForStatus(sessionId, targetStatus = 'active', timeoutMs = 30000, pollIntervalMs = 1000) {
|
|
99
|
+
const startTime = Date.now();
|
|
100
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
101
|
+
const session = await this.getSession(sessionId);
|
|
102
|
+
if (session.status === targetStatus) {
|
|
103
|
+
return session;
|
|
104
|
+
}
|
|
105
|
+
// If session is closed or failed, throw error
|
|
106
|
+
if (session.status === 'closed') {
|
|
107
|
+
throw new Error(`Session ${sessionId} is closed`);
|
|
108
|
+
}
|
|
109
|
+
// Wait before polling again
|
|
110
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
111
|
+
}
|
|
112
|
+
throw new Error(`Timeout waiting for session ${sessionId} to reach status "${targetStatus}"`);
|
|
113
|
+
}
|
|
114
|
+
// ==========================================
|
|
115
|
+
// Actions
|
|
116
|
+
// ==========================================
|
|
117
|
+
/**
|
|
118
|
+
* Execute a browser action
|
|
119
|
+
*/
|
|
120
|
+
async executeAction(sessionId, action) {
|
|
121
|
+
try {
|
|
122
|
+
const response = await this.client.post(`/sessions/${sessionId}/action`, action);
|
|
123
|
+
return response.data;
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
throw this.handleError(error, `execute action "${action.type}"`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// ==========================================
|
|
130
|
+
// Inspection
|
|
131
|
+
// ==========================================
|
|
132
|
+
/**
|
|
133
|
+
* Get the ARIA accessibility tree snapshot
|
|
134
|
+
*/
|
|
135
|
+
async getSnapshot(sessionId) {
|
|
136
|
+
try {
|
|
137
|
+
const response = await this.client.get(`/sessions/${sessionId}/snapshot`);
|
|
138
|
+
return response.data;
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
throw this.handleError(error, 'get snapshot');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get a screenshot of the current page
|
|
146
|
+
* @returns Buffer containing PNG image data
|
|
147
|
+
*/
|
|
148
|
+
async getScreenshot(sessionId) {
|
|
149
|
+
try {
|
|
150
|
+
const response = await this.client.get(`/sessions/${sessionId}/screenshot`, {
|
|
151
|
+
responseType: 'arraybuffer',
|
|
152
|
+
});
|
|
153
|
+
return Buffer.from(response.data);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
throw this.handleError(error, 'get screenshot');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get the current page URL
|
|
161
|
+
*/
|
|
162
|
+
async getUrl(sessionId) {
|
|
163
|
+
try {
|
|
164
|
+
const response = await this.client.get(`/sessions/${sessionId}/url`);
|
|
165
|
+
const result = response.data;
|
|
166
|
+
return result.url;
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
throw this.handleError(error, 'get URL');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get recorded blocks (test steps) from the session
|
|
174
|
+
* @returns Array of ExtendedStep objects
|
|
175
|
+
*/
|
|
176
|
+
async getBlocks(sessionId) {
|
|
177
|
+
try {
|
|
178
|
+
const response = await this.client.get(`/sessions/${sessionId}/blocks`);
|
|
179
|
+
const result = response.data;
|
|
180
|
+
return (result.blocks || []);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
throw this.handleError(error, 'get blocks');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// ==========================================
|
|
187
|
+
// WebSocket Streaming
|
|
188
|
+
// ==========================================
|
|
189
|
+
/**
|
|
190
|
+
* Get the WebSocket URL for streaming events
|
|
191
|
+
*/
|
|
192
|
+
getStreamUrl(sessionId) {
|
|
193
|
+
// Convert HTTP URL to WebSocket URL
|
|
194
|
+
const baseUrl = this.getBaseUrl();
|
|
195
|
+
const wsUrl = baseUrl.replace(/^http/, 'ws');
|
|
196
|
+
return `${wsUrl}/sessions/${sessionId}/stream`;
|
|
197
|
+
}
|
|
198
|
+
// ==========================================
|
|
199
|
+
// Error Handling
|
|
200
|
+
// ==========================================
|
|
201
|
+
handleError(error, operation) {
|
|
202
|
+
if (axios.isAxiosError(error)) {
|
|
203
|
+
const statusCode = error.response?.status;
|
|
204
|
+
const errorData = error.response?.data;
|
|
205
|
+
if (statusCode === 404) {
|
|
206
|
+
return new Error(`Session not found`);
|
|
207
|
+
}
|
|
208
|
+
if (statusCode === 401) {
|
|
209
|
+
return new Error(`Unauthorized. Please check your API key.`);
|
|
210
|
+
}
|
|
211
|
+
if (statusCode === 403) {
|
|
212
|
+
return new Error(`Forbidden. You don't have permission for this operation.`);
|
|
213
|
+
}
|
|
214
|
+
const message = errorData?.message || errorData?.detail || `HTTP ${statusCode}: Failed to ${operation}`;
|
|
215
|
+
return new Error(message);
|
|
216
|
+
}
|
|
217
|
+
if (error instanceof Error) {
|
|
218
|
+
return error;
|
|
219
|
+
}
|
|
220
|
+
return new Error(`Unknown error during ${operation}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../lib/api/browser.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.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"packageManager": "bun@^1.3.4",
|
|
5
5
|
"description": "QA automation tool for browser testing with MCP server support",
|
|
6
6
|
"type": "module",
|
|
@@ -95,6 +95,7 @@
|
|
|
95
95
|
"express": "^4.21.2",
|
|
96
96
|
"glob": "^13.0.0",
|
|
97
97
|
"playwright": "1.55.0",
|
|
98
|
+
"ws": "^8.19.0",
|
|
98
99
|
"yaml": "^2.8.2"
|
|
99
100
|
}
|
|
100
101
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"back.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/back.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,WAAW,SAkCpB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* qa-use browser back - Navigate back in browser history
|
|
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 backCommand = new Command('back')
|
|
10
|
+
.description('Navigate back in browser history')
|
|
11
|
+
.option('-s, --session-id <id>', 'Session ID (auto-resolved if only one session)')
|
|
12
|
+
.action(async (options) => {
|
|
13
|
+
try {
|
|
14
|
+
const config = await loadConfig();
|
|
15
|
+
if (!config.api_key) {
|
|
16
|
+
console.log(error('API key not configured. Run `qa-use setup` first.'));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const client = new BrowserApiClient(config.api_url);
|
|
20
|
+
client.setApiKey(config.api_key);
|
|
21
|
+
const resolved = await resolveSessionId({
|
|
22
|
+
explicitId: options.sessionId,
|
|
23
|
+
client,
|
|
24
|
+
});
|
|
25
|
+
const result = await client.executeAction(resolved.id, {
|
|
26
|
+
type: 'back',
|
|
27
|
+
});
|
|
28
|
+
if (result.success) {
|
|
29
|
+
console.log(success('Navigated back'));
|
|
30
|
+
await touchSession(resolved.id);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.log(error(result.error || 'Navigation failed'));
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
console.log(error(err instanceof Error ? err.message : 'Failed to navigate back'));
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=back.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"back.js","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/back.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;AAMrD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,kCAAkC,CAAC;KAC/C,MAAM,CAAC,uBAAuB,EAAE,gDAAgD,CAAC;KACjF,MAAM,CAAC,KAAK,EAAE,OAAoB,EAAE,EAAE;IACrC,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,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE;YACrD,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;YACvC,MAAM,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,mBAAmB,CAAC,CAAC,CAAC;YACxD,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":"check.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/check.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,eAAO,MAAM,YAAY,SAiDrB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* qa-use browser check - Check a checkbox by ref or semantic text
|
|
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
|
+
/**
|
|
10
|
+
* Normalize ref by stripping leading @ if present
|
|
11
|
+
*/
|
|
12
|
+
function normalizeRef(ref) {
|
|
13
|
+
return ref.startsWith('@') ? ref.slice(1) : ref;
|
|
14
|
+
}
|
|
15
|
+
export const checkCommand = new Command('check')
|
|
16
|
+
.description('Check a checkbox by ref or semantic description')
|
|
17
|
+
.argument('[ref]', 'Element ref from snapshot (e.g., "e3" or "@e3")')
|
|
18
|
+
.option('-s, --session-id <id>', 'Session ID (auto-resolved if only one session)')
|
|
19
|
+
.option('-t, --text <description>', 'Semantic element description (AI-based, slower)')
|
|
20
|
+
.action(async (ref, options) => {
|
|
21
|
+
try {
|
|
22
|
+
// Validate that either ref or --text is provided
|
|
23
|
+
if (!ref && !options.text) {
|
|
24
|
+
console.log(error('Either <ref> argument or --text option is required'));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
const config = await loadConfig();
|
|
28
|
+
if (!config.api_key) {
|
|
29
|
+
console.log(error('API key not configured. Run `qa-use setup` first.'));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
const client = new BrowserApiClient(config.api_url);
|
|
33
|
+
client.setApiKey(config.api_key);
|
|
34
|
+
const resolved = await resolveSessionId({
|
|
35
|
+
explicitId: options.sessionId,
|
|
36
|
+
client,
|
|
37
|
+
});
|
|
38
|
+
// Build action with either ref or text
|
|
39
|
+
const action = { type: 'check' };
|
|
40
|
+
if (ref) {
|
|
41
|
+
action.ref = normalizeRef(ref);
|
|
42
|
+
}
|
|
43
|
+
else if (options.text) {
|
|
44
|
+
action.text = options.text;
|
|
45
|
+
}
|
|
46
|
+
const result = await client.executeAction(resolved.id, action);
|
|
47
|
+
if (result.success) {
|
|
48
|
+
const target = ref ? `checkbox ${normalizeRef(ref)}` : `"${options.text}"`;
|
|
49
|
+
console.log(success(`Checked ${target}`));
|
|
50
|
+
await touchSession(resolved.id);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
console.log(error(result.error || 'Check failed'));
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
console.log(error(err instanceof Error ? err.message : 'Failed to check checkbox'));
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/check.ts"],"names":[],"mappings":"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"}
|