@bugbug-io/sdk 13.39.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +576 -0
- package/dist/constants/sdk-error-codes.d.ts +35 -0
- package/dist/constants/sdk-error-codes.d.ts.map +1 -0
- package/dist/index.d.ts +87 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3844 -0
- package/dist/modules/auth/auth.d.ts +11 -0
- package/dist/modules/auth/auth.d.ts.map +1 -0
- package/dist/modules/auth/auth.types.d.ts +34 -0
- package/dist/modules/auth/auth.types.d.ts.map +1 -0
- package/dist/modules/auth/auth.utils.d.ts +4 -0
- package/dist/modules/auth/auth.utils.d.ts.map +1 -0
- package/dist/modules/components/components.d.ts +43 -0
- package/dist/modules/components/components.d.ts.map +1 -0
- package/dist/modules/config/config.d.ts +48 -0
- package/dist/modules/config/config.d.ts.map +1 -0
- package/dist/modules/groups/groups.d.ts +62 -0
- package/dist/modules/groups/groups.d.ts.map +1 -0
- package/dist/modules/profiles/profiles.d.ts +71 -0
- package/dist/modules/profiles/profiles.d.ts.map +1 -0
- package/dist/modules/project/project.d.ts +58 -0
- package/dist/modules/project/project.d.ts.map +1 -0
- package/dist/modules/projectArtifacts/projectArtifacts.d.ts +8 -0
- package/dist/modules/projectArtifacts/projectArtifacts.d.ts.map +1 -0
- package/dist/modules/projectArtifacts/projectArtifacts.types.d.ts +14 -0
- package/dist/modules/projectArtifacts/projectArtifacts.types.d.ts.map +1 -0
- package/dist/modules/projects/projects.d.ts +36 -0
- package/dist/modules/projects/projects.d.ts.map +1 -0
- package/dist/modules/projects/projects.types.d.ts +6 -0
- package/dist/modules/projects/projects.types.d.ts.map +1 -0
- package/dist/modules/stepRuns/stepRuns.d.ts +22 -0
- package/dist/modules/stepRuns/stepRuns.d.ts.map +1 -0
- package/dist/modules/steps/steps.d.ts +47 -0
- package/dist/modules/steps/steps.d.ts.map +1 -0
- package/dist/modules/steps/steps.utils.d.ts +11 -0
- package/dist/modules/steps/steps.utils.d.ts.map +1 -0
- package/dist/modules/suites/suites.d.ts +153 -0
- package/dist/modules/suites/suites.d.ts.map +1 -0
- package/dist/modules/suites/suites.types.d.ts +31 -0
- package/dist/modules/suites/suites.types.d.ts.map +1 -0
- package/dist/modules/tests/tests.d.ts +253 -0
- package/dist/modules/tests/tests.d.ts.map +1 -0
- package/dist/modules/tests/tests.types.d.ts +34 -0
- package/dist/modules/tests/tests.types.d.ts.map +1 -0
- package/dist/modules/tests/tests.utils.d.ts +11 -0
- package/dist/modules/tests/tests.utils.d.ts.map +1 -0
- package/dist/modules/variables/variables.d.ts +14 -0
- package/dist/modules/variables/variables.d.ts.map +1 -0
- package/dist/modules/variables/variables.types.d.ts +7 -0
- package/dist/modules/variables/variables.types.d.ts.map +1 -0
- package/dist/modules/visualRegression/visualRegression.constants.d.ts +7 -0
- package/dist/modules/visualRegression/visualRegression.constants.d.ts.map +1 -0
- package/dist/modules/visualRegression/visualRegression.d.ts +69 -0
- package/dist/modules/visualRegression/visualRegression.d.ts.map +1 -0
- package/dist/modules/visualRegression/visualRegression.types.d.ts +12 -0
- package/dist/modules/visualRegression/visualRegression.types.d.ts.map +1 -0
- package/dist/sdk.d.ts +126 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/services/apiClient/apiClient.d.ts +167 -0
- package/dist/services/apiClient/apiClient.d.ts.map +1 -0
- package/dist/services/apiClient/apiClient.types.d.ts +19 -0
- package/dist/services/apiClient/apiClient.types.d.ts.map +1 -0
- package/dist/services/apiClient/apiClient.utils.d.ts +32 -0
- package/dist/services/apiClient/apiClient.utils.d.ts.map +1 -0
- package/dist/services/rateLimiter/rateLimiter.constants.d.ts +5 -0
- package/dist/services/rateLimiter/rateLimiter.constants.d.ts.map +1 -0
- package/dist/services/rateLimiter/rateLimiter.d.ts +49 -0
- package/dist/services/rateLimiter/rateLimiter.d.ts.map +1 -0
- package/dist/services/rateLimiter/rateLimiter.types.d.ts +34 -0
- package/dist/services/rateLimiter/rateLimiter.types.d.ts.map +1 -0
- package/dist/testUtils/fakeFactory.d.ts +15 -0
- package/dist/testUtils/fakeFactory.d.ts.map +1 -0
- package/dist/testUtils/setup.d.ts +2 -0
- package/dist/testUtils/setup.d.ts.map +1 -0
- package/dist/types/config.d.ts +121 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/errors.d.ts +162 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/sdk.d.ts +28 -0
- package/dist/types/sdk.d.ts.map +1 -0
- package/dist/utils/pagination.d.ts +10 -0
- package/dist/utils/pagination.d.ts.map +1 -0
- package/dist/utils/polling.d.ts +20 -0
- package/dist/utils/polling.d.ts.map +1 -0
- package/package.json +83 -0
package/README.md
ADDED
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
# BugBug SDK
|
|
6
|
+
|
|
7
|
+
**TypeScript SDK for BugBug**
|
|
8
|
+
|
|
9
|
+
A comprehensive TypeScript SDK for interacting with the [BugBug](https://bugbug.io) API, featuring rate limiting, error handling, and built-in progress watching utilities.
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Easy to use** - Simple factory function and intuitive API
|
|
16
|
+
- **Type-safe** - Full TypeScript support with comprehensive type definitions
|
|
17
|
+
- **Rate limiting** - Built-in exponential backoff and request throttling
|
|
18
|
+
- **Error handling** - Comprehensive error types and automatic retries
|
|
19
|
+
- **Request cancellation** - AbortController support for all requests
|
|
20
|
+
- **Progress watching utilities** - Built-in polling for test and suite completion
|
|
21
|
+
- **Verbose logging** - Detailed request/response logging for debugging
|
|
22
|
+
- **Metrics collection** - Optional telemetry and performance tracking
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @bugbug-io/sdk
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { createBugBug } from '@bugbug-io/sdk';
|
|
34
|
+
|
|
35
|
+
const bugbug = createBugBug({
|
|
36
|
+
apiToken: 'your-api-token',
|
|
37
|
+
verbose: true, // Enable detailed logging
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Run a test and watch progress until completion
|
|
41
|
+
const result = await bugbug.tests.startRun('my-test', {
|
|
42
|
+
watchProgress: true,
|
|
43
|
+
onProgress: (run) => console.log(`Status: ${run.status}`),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
console.log('Test completed:', result.status);
|
|
47
|
+
|
|
48
|
+
// Get recent test runs
|
|
49
|
+
const recentTests = await bugbug.tests.getRecentRuns({ hours: 24 });
|
|
50
|
+
|
|
51
|
+
// Run a suite
|
|
52
|
+
const suiteResult = await bugbug.suites.startRun('suite-id', {
|
|
53
|
+
watchProgress: true,
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Configuration
|
|
58
|
+
|
|
59
|
+
### Basic Configuration
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
const bugbug = createBugBug({
|
|
63
|
+
apiToken: 'your-api-token',
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Advanced Configuration
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const bugbug = createBugBug({
|
|
71
|
+
apiToken: 'your-api-token',
|
|
72
|
+
apiUrl: 'https://app.bugbug.io/api/v2', // Full API base URL. Default: https://app.bugbug.io/api/v2
|
|
73
|
+
verbose: false, // Enable detailed logging
|
|
74
|
+
logLevel: 'info', // 'debug' | 'info' | 'warn' | 'error'
|
|
75
|
+
timeout: 30000, // Request timeout in milliseconds
|
|
76
|
+
|
|
77
|
+
// Rate limiting configuration
|
|
78
|
+
rateLimit: {
|
|
79
|
+
maxRequests: 100, // Max requests per window
|
|
80
|
+
windowMs: 60000, // Time window in milliseconds
|
|
81
|
+
exponentialBackoff: {
|
|
82
|
+
baseDelay: 1000, // Base delay for retries (ms)
|
|
83
|
+
maxDelay: 30000, // Maximum delay (ms)
|
|
84
|
+
maxRetries: 3, // Maximum retry attempts on rate-limit
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
> **Note on `apiUrl`:** The SDK treats `apiUrl` as the **full API base URL** and does not auto-append `/api/v2` or rewrite the value in any way. Pass a complete URL like `https://app.bugbug.io/api/v2`. Host-only values will route to the wrong endpoint.
|
|
91
|
+
|
|
92
|
+
## API Reference
|
|
93
|
+
|
|
94
|
+
### Auth
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import {
|
|
98
|
+
BUGBUG_CLI_OAUTH_CLIENT_ID,
|
|
99
|
+
BUGBUG_OAUTH_CODE_CHALLENGE_METHOD,
|
|
100
|
+
createOAuthCodeChallenge,
|
|
101
|
+
createOAuthCodeVerifier,
|
|
102
|
+
createOAuthState,
|
|
103
|
+
createBugBug,
|
|
104
|
+
} from '@bugbug-io/sdk';
|
|
105
|
+
|
|
106
|
+
const bugbug = createBugBug({ apiToken: 'placeholder' });
|
|
107
|
+
const codeVerifier = createOAuthCodeVerifier();
|
|
108
|
+
const authorize = await bugbug.auth.getAuth({
|
|
109
|
+
clientId: BUGBUG_CLI_OAUTH_CLIENT_ID,
|
|
110
|
+
redirectUri: 'http://127.0.0.1:48123/callback',
|
|
111
|
+
codeChallenge: createOAuthCodeChallenge(codeVerifier),
|
|
112
|
+
codeChallengeMethod: BUGBUG_OAUTH_CODE_CHALLENGE_METHOD,
|
|
113
|
+
state: createOAuthState(),
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`auth.getAuth` and `auth.exchangeCode` call root `/auth/...` endpoints and do
|
|
118
|
+
not send the configured API token. `auth.identity` validates the configured token.
|
|
119
|
+
|
|
120
|
+
### Tests
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// List all tests
|
|
124
|
+
const tests = await bugbug.tests.list({
|
|
125
|
+
page: 1,
|
|
126
|
+
pageSize: 50,
|
|
127
|
+
query: 'search-term',
|
|
128
|
+
ordering: 'name', // 'name' | '-name' | 'created' | '-created'
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Get a specific test
|
|
132
|
+
const test = await bugbug.tests.get('test-id');
|
|
133
|
+
|
|
134
|
+
// Run a test by name or UUID (fire-and-forget; returns the run state)
|
|
135
|
+
const runState = await bugbug.tests.startRun('test-id-or-name', {
|
|
136
|
+
profileName: 'Production',
|
|
137
|
+
variables: [
|
|
138
|
+
{ key: 'username', value: 'testuser' },
|
|
139
|
+
{ key: 'password', value: 'testpass' },
|
|
140
|
+
],
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Run a test and watch progress until completion (returns full TestRun)
|
|
144
|
+
const completedRun = await bugbug.tests.startRun('test-id-or-name', {
|
|
145
|
+
watchProgress: true,
|
|
146
|
+
pollInterval: 2000, // Check every 2 seconds
|
|
147
|
+
timeout: 300000, // 5 minute timeout
|
|
148
|
+
onProgress: (state) => console.log(`Status: ${state.status}`),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Poll an existing run until it finishes
|
|
152
|
+
const run = await bugbug.tests.watchRunProgress(
|
|
153
|
+
runState.id,
|
|
154
|
+
(state) => console.log(`Status: ${state.status}`),
|
|
155
|
+
{ pollInterval: 2000, timeout: 300000 },
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// Get run details / lightweight progress
|
|
159
|
+
const runDetails = await bugbug.tests.getRun('run-id');
|
|
160
|
+
const status = await bugbug.tests.getRunProgress('run-id');
|
|
161
|
+
|
|
162
|
+
// Recent runs, logs, screenshots, JUnit report
|
|
163
|
+
const recentTests = await bugbug.tests.getRecentRuns({ hours: 24 });
|
|
164
|
+
const logs = await bugbug.tests.getRunLogs('run-id');
|
|
165
|
+
const screenshots = await bugbug.tests.getRunScreenshots('run-id');
|
|
166
|
+
const junitXml = await bugbug.tests.downloadRunJunitReport('run-id');
|
|
167
|
+
|
|
168
|
+
// Stop a running test
|
|
169
|
+
await bugbug.tests.stopRun('run-id');
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Suites
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
// List all suites
|
|
176
|
+
const suites = await bugbug.suites.list();
|
|
177
|
+
|
|
178
|
+
// Get a specific suite
|
|
179
|
+
const suite = await bugbug.suites.get('suite-id');
|
|
180
|
+
|
|
181
|
+
// Run a suite (fire-and-forget; returns the run state)
|
|
182
|
+
const runState = await bugbug.suites.startRun('suite-id', {
|
|
183
|
+
profileName: 'Production',
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Run a suite and watch progress until completion (returns full SuiteRun)
|
|
187
|
+
const completedRun = await bugbug.suites.startRun('suite-id', {
|
|
188
|
+
watchProgress: true,
|
|
189
|
+
onProgress: (state) => console.log(`Status: ${state.status}`),
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Poll an existing suite run until it finishes
|
|
193
|
+
const run = await bugbug.suites.watchRunProgress(runState.id, (state) =>
|
|
194
|
+
console.log(`Status: ${state.status}`),
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
// Run details, recent runs, and JUnit report
|
|
198
|
+
const runDetails = await bugbug.suites.getRun('run-id');
|
|
199
|
+
const recentSuites = await bugbug.suites.getRecentRuns({ hours: 24 });
|
|
200
|
+
const junitXml = await bugbug.suites.downloadRunJunitReport('run-id');
|
|
201
|
+
|
|
202
|
+
// Stop a running suite
|
|
203
|
+
await bugbug.suites.stopRun('run-id');
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Profiles
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
// List all profiles
|
|
210
|
+
const profiles = await bugbug.profiles.list();
|
|
211
|
+
|
|
212
|
+
// Get a specific profile
|
|
213
|
+
const profile = await bugbug.profiles.get('profile-id');
|
|
214
|
+
|
|
215
|
+
// Find profile by name
|
|
216
|
+
const profile = await bugbug.profiles.findByName('Production');
|
|
217
|
+
|
|
218
|
+
// Get all profiles (handles pagination)
|
|
219
|
+
const allProfiles = await bugbug.profiles.getAll();
|
|
220
|
+
|
|
221
|
+
// Get default profile
|
|
222
|
+
const defaultProfile = await bugbug.profiles.getDefault();
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Configuration & System Info
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
// Get IP addresses for whitelisting
|
|
229
|
+
const ips = await bugbug.config.getIpAddresses();
|
|
230
|
+
|
|
231
|
+
// Test connectivity
|
|
232
|
+
const isConnected = await bugbug.testConnection();
|
|
233
|
+
|
|
234
|
+
// Get system information (IP addresses + connectivity probe)
|
|
235
|
+
const systemInfo = await bugbug.config.getSystemInfo();
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Groups (Components)
|
|
239
|
+
|
|
240
|
+
Groups represent reusable test components or test building blocks.
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
// List all groups
|
|
244
|
+
const groups = await bugbug.groups.list({
|
|
245
|
+
query: 'login',
|
|
246
|
+
page: 1,
|
|
247
|
+
pageSize: 50,
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Get a specific group
|
|
251
|
+
const group = await bugbug.groups.get('group-id');
|
|
252
|
+
|
|
253
|
+
// Create a new group
|
|
254
|
+
const newGroup = await bugbug.groups.create({
|
|
255
|
+
name: 'Login Component',
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// Update a group
|
|
259
|
+
const updatedGroup = await bugbug.groups.update('group-id', {
|
|
260
|
+
name: 'Updated Login Component',
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Partially update a group
|
|
264
|
+
const patchedGroup = await bugbug.groups.partialUpdate('group-id', {
|
|
265
|
+
name: 'Patched Name',
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// Delete a group
|
|
269
|
+
await bugbug.groups.delete('group-id');
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Components
|
|
273
|
+
|
|
274
|
+
Components are reusable test building blocks that can be shared across multiple tests.
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
// List all components
|
|
278
|
+
const components = await bugbug.components.list({
|
|
279
|
+
query: 'login',
|
|
280
|
+
page: 1,
|
|
281
|
+
pageSize: 50,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// The response has a nested structure
|
|
285
|
+
const { results } = components;
|
|
286
|
+
const componentsList = results.results; // Array of components
|
|
287
|
+
|
|
288
|
+
// See which tests use a component
|
|
289
|
+
const usage = await bugbug.components.getUsage('component-id');
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Steps
|
|
293
|
+
|
|
294
|
+
Steps represent individual actions within tests or groups.
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
// ✅ NEW: Get steps through their parent group
|
|
298
|
+
const group = await bugbug.groups.get('group-id');
|
|
299
|
+
const steps = group.steps; // Array of steps in this group
|
|
300
|
+
|
|
301
|
+
// ✅ Get a specific step by ID
|
|
302
|
+
const step = await bugbug.steps.get('step-id');
|
|
303
|
+
|
|
304
|
+
// ✅ List groups to find steps
|
|
305
|
+
const groups = await bugbug.groups.list({ query: 'login' });
|
|
306
|
+
groups.results.forEach((group) => {
|
|
307
|
+
console.log(`Group: ${group.name}, Steps: ${group.steps?.length || 0}`);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Create a new step
|
|
311
|
+
const newStep = await bugbug.steps.create({
|
|
312
|
+
type: 'click',
|
|
313
|
+
name: 'Click Login Button',
|
|
314
|
+
groupId: 'group-id',
|
|
315
|
+
isActive: true,
|
|
316
|
+
runTimeout: 30,
|
|
317
|
+
interactionPosition: 'center',
|
|
318
|
+
selectorsPresets: [],
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Update a step
|
|
322
|
+
const updatedStep = await bugbug.steps.update('step-id', {
|
|
323
|
+
type: 'click',
|
|
324
|
+
name: 'Updated Step',
|
|
325
|
+
groupId: 'group-id',
|
|
326
|
+
interactionPosition: 'center',
|
|
327
|
+
selectorsPresets: [],
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// Partially update a step
|
|
331
|
+
const patchedStep = await bugbug.steps.partialUpdate('step-id', {
|
|
332
|
+
type: 'click',
|
|
333
|
+
name: 'Patched Step Name',
|
|
334
|
+
runTimeout: 60,
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// Delete a step
|
|
338
|
+
await bugbug.steps.delete('step-id');
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Step Runs
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
// Get details of a single step run (selectors, errors, screenshots)
|
|
345
|
+
const stepRun = await bugbug.stepRuns.get('step-run-id');
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Project
|
|
349
|
+
|
|
350
|
+
The `project` module operates on the single project the API token is scoped to.
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
// Get settings for the authenticated project
|
|
354
|
+
const settings = await bugbug.project.getSettings();
|
|
355
|
+
|
|
356
|
+
// Export the project as a ZIP archive (Uint8Array)
|
|
357
|
+
const zipBytes = await bugbug.project.export();
|
|
358
|
+
|
|
359
|
+
// Import a project from ZIP bytes
|
|
360
|
+
await bugbug.project.import(zipBytes);
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Projects
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
// List the projects available to the current credentials
|
|
367
|
+
const projects = await bugbug.projects.list();
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Visual Regression
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
// List reference screenshots for a step
|
|
374
|
+
const refs = await bugbug.visualRegression.listReferenceScreenshots({
|
|
375
|
+
stepId: 'step-id',
|
|
376
|
+
page: 1,
|
|
377
|
+
pageSize: 50,
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// Get a single reference screenshot
|
|
381
|
+
const ref = await bugbug.visualRegression.getReferenceScreenshot('ref-id');
|
|
382
|
+
|
|
383
|
+
// Create, update, and delete reference screenshots
|
|
384
|
+
const created = await bugbug.visualRegression.createReferenceScreenshot({
|
|
385
|
+
stepId: 'step-id',
|
|
386
|
+
screenshot: 'https://example.com/reference.png',
|
|
387
|
+
});
|
|
388
|
+
await bugbug.visualRegression.updateReferenceScreenshot('ref-id', { isActive: false });
|
|
389
|
+
await bugbug.visualRegression.deleteReferenceScreenshot('ref-id');
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Tests - Extended CRUD Operations
|
|
393
|
+
|
|
394
|
+
In addition to running tests, you can now create, update, and delete tests programmatically.
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
// Create a new test
|
|
398
|
+
const newTest = await bugbug.tests.create({
|
|
399
|
+
name: 'My New Test',
|
|
400
|
+
screenSizeType: 'desktop',
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// Update a test
|
|
404
|
+
const updatedTest = await bugbug.tests.update('test-id', {
|
|
405
|
+
name: 'Updated Test Name',
|
|
406
|
+
isActive: true,
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// Partially update a test
|
|
410
|
+
const patchedTest = await bugbug.tests.partialUpdate('test-id', {
|
|
411
|
+
name: 'Patched Test Name',
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
// Delete a test
|
|
415
|
+
await bugbug.tests.delete('test-id');
|
|
416
|
+
|
|
417
|
+
// Link a component (group) to a test
|
|
418
|
+
await bugbug.tests.linkComponent('test-id', {
|
|
419
|
+
groupId: 'group-id',
|
|
420
|
+
atIndex: 0, // Optional: insert at specific position
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
// Unlink a component from a test
|
|
424
|
+
await bugbug.tests.unlinkComponent('test-id', 'group-id');
|
|
425
|
+
|
|
426
|
+
// Get test run logs
|
|
427
|
+
const logs = await bugbug.tests.getRunLogs('run-id');
|
|
428
|
+
|
|
429
|
+
// Download JUnit report
|
|
430
|
+
const junitXml = await bugbug.tests.downloadRunJunitReport('run-id');
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## High-Level Methods
|
|
434
|
+
|
|
435
|
+
### Running Tests with Progress Watching
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
// Run test and watch progress until completion
|
|
439
|
+
const result = await bugbug.tests.startRun('test-name-or-id', {
|
|
440
|
+
watchProgress: true,
|
|
441
|
+
profileName: 'Production',
|
|
442
|
+
timeout: 600000, // 10 minutes
|
|
443
|
+
onProgress: (run) => {
|
|
444
|
+
console.log(`Test ${run.id}: ${run.status}`);
|
|
445
|
+
},
|
|
446
|
+
});
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Running Suites with Progress Watching
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
// Run suite and watch progress until completion
|
|
453
|
+
const result = await bugbug.suites.startRun('suite-id', {
|
|
454
|
+
watchProgress: true,
|
|
455
|
+
profileName: 'Production',
|
|
456
|
+
onProgress: (run) => {
|
|
457
|
+
console.log(`Suite ${run.id}: ${run.status} (${run.test_runs?.length || 0} tests)`);
|
|
458
|
+
},
|
|
459
|
+
});
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
## Error Handling
|
|
463
|
+
|
|
464
|
+
The SDK provides comprehensive error types for different scenarios:
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
import {
|
|
468
|
+
BugBugError,
|
|
469
|
+
AuthenticationError,
|
|
470
|
+
AuthorizationError,
|
|
471
|
+
ValidationError,
|
|
472
|
+
NotFoundError,
|
|
473
|
+
RateLimitError,
|
|
474
|
+
NetworkError,
|
|
475
|
+
CancellationError,
|
|
476
|
+
TimeoutError,
|
|
477
|
+
} from '@bugbug-io/sdk';
|
|
478
|
+
|
|
479
|
+
try {
|
|
480
|
+
const result = await bugbug.tests.startRun('test-id');
|
|
481
|
+
} catch (error) {
|
|
482
|
+
if (error instanceof AuthenticationError) {
|
|
483
|
+
console.error('Invalid API token');
|
|
484
|
+
} else if (error instanceof RateLimitError) {
|
|
485
|
+
console.error(`Rate limited. Retry after ${error.retryAfter}ms`);
|
|
486
|
+
} else if (error instanceof TimeoutError) {
|
|
487
|
+
console.error(`Request timed out after ${error.timeout}ms`);
|
|
488
|
+
} else if (error instanceof NetworkError) {
|
|
489
|
+
console.error('Network error occurred');
|
|
490
|
+
} else {
|
|
491
|
+
console.error('Unknown error:', error.message);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
## Request Cancellation
|
|
497
|
+
|
|
498
|
+
All requests support cancellation using AbortController:
|
|
499
|
+
|
|
500
|
+
```typescript
|
|
501
|
+
const controller = new AbortController();
|
|
502
|
+
|
|
503
|
+
// Cancel the request after 5 seconds
|
|
504
|
+
setTimeout(() => controller.abort(), 5000);
|
|
505
|
+
|
|
506
|
+
try {
|
|
507
|
+
const result = await bugbug.tests.list({
|
|
508
|
+
signal: controller.signal,
|
|
509
|
+
});
|
|
510
|
+
} catch (error) {
|
|
511
|
+
if (error instanceof CancellationError) {
|
|
512
|
+
console.log('Request was cancelled');
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
## Rate Limiting
|
|
518
|
+
|
|
519
|
+
The SDK applies rate limiting with exponential backoff automatically, based on the
|
|
520
|
+
`rateLimit` configuration (see [Advanced Configuration](#advanced-configuration)).
|
|
521
|
+
On HTTP 429 responses it backs off and retries up to `maxRetries`, throwing a
|
|
522
|
+
`RateLimitError` once retries are exhausted.
|
|
523
|
+
|
|
524
|
+
## Client Methods
|
|
525
|
+
|
|
526
|
+
The top-level client exposes a few helpers alongside the resource modules:
|
|
527
|
+
|
|
528
|
+
```typescript
|
|
529
|
+
// Read the resolved config (apiToken, apiUrl, etc.)
|
|
530
|
+
const config = bugbug.getConfig();
|
|
531
|
+
|
|
532
|
+
// Update config at runtime
|
|
533
|
+
bugbug.updateConfig({ apiUrl: 'https://app.bugbug.io/api/v2' });
|
|
534
|
+
|
|
535
|
+
// Switch the active project (shorthand for updateConfig({ projectId }))
|
|
536
|
+
bugbug.setProject('project-id');
|
|
537
|
+
|
|
538
|
+
// Probe connectivity to the API
|
|
539
|
+
const connectivity = await bugbug.testConnection();
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
## TypeScript Support
|
|
543
|
+
|
|
544
|
+
The SDK is built with TypeScript and provides comprehensive type definitions:
|
|
545
|
+
|
|
546
|
+
```typescript
|
|
547
|
+
import type { Test, TestRun, Suite, SuiteRun } from '@bugbug-io/sdk';
|
|
548
|
+
|
|
549
|
+
// All API responses are properly typed
|
|
550
|
+
const test: Test = await bugbug.tests.get('test-id');
|
|
551
|
+
const run: TestRun = await bugbug.tests.startRun(test.id, { watchProgress: true });
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
## Environment Variables
|
|
555
|
+
|
|
556
|
+
You can also configure the SDK using environment variables:
|
|
557
|
+
|
|
558
|
+
```bash
|
|
559
|
+
BUGBUG_API_TOKEN=your-api-token
|
|
560
|
+
BUGBUG_API_URL=https://app.bugbug.io/api/v2
|
|
561
|
+
BUGBUG_VERBOSE=true
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
```typescript
|
|
565
|
+
import { createBugBug } from '@bugbug-io/sdk';
|
|
566
|
+
|
|
567
|
+
const bugbug = createBugBug({
|
|
568
|
+
apiToken: process.env.BUGBUG_API_TOKEN!,
|
|
569
|
+
apiUrl: process.env.BUGBUG_API_URL,
|
|
570
|
+
verbose: process.env.BUGBUG_VERBOSE === 'true',
|
|
571
|
+
});
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
## License
|
|
575
|
+
|
|
576
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK transport-level error codes.
|
|
3
|
+
*
|
|
4
|
+
* Each `BugBugError` (and subclass) carries one of these codes in its `code`
|
|
5
|
+
* field. Distinct from step-execution codes in `step-error-codes.ts`, which
|
|
6
|
+
* describe runtime failures inside a test/suite run.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SDK_ERROR_CODES: {
|
|
9
|
+
readonly AUTHENTICATION_ERROR: "AUTHENTICATION_ERROR";
|
|
10
|
+
readonly AUTHORIZATION_ERROR: "AUTHORIZATION_ERROR";
|
|
11
|
+
readonly VALIDATION_ERROR: "VALIDATION_ERROR";
|
|
12
|
+
readonly CONFIGURATION_ERROR: "CONFIGURATION_ERROR";
|
|
13
|
+
readonly MISSING_PROJECT_ID_ERROR: "MISSING_PROJECT_ID_ERROR";
|
|
14
|
+
readonly NOT_FOUND_ERROR: "NOT_FOUND_ERROR";
|
|
15
|
+
readonly RATE_LIMIT_ERROR: "RATE_LIMIT_ERROR";
|
|
16
|
+
readonly TIMEOUT_ERROR: "TIMEOUT_ERROR";
|
|
17
|
+
readonly NETWORK_ERROR: "NETWORK_ERROR";
|
|
18
|
+
readonly CANCELLATION_ERROR: "CANCELLATION_ERROR";
|
|
19
|
+
readonly INTERNAL_SERVER_ERROR: "INTERNAL_SERVER_ERROR";
|
|
20
|
+
readonly SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE";
|
|
21
|
+
readonly UNEXPECTED_RESPONSE: "UNEXPECTED_RESPONSE";
|
|
22
|
+
readonly HTTP_ERROR: "HTTP_ERROR";
|
|
23
|
+
};
|
|
24
|
+
export type SdkErrorCode = (typeof SDK_ERROR_CODES)[keyof typeof SDK_ERROR_CODES];
|
|
25
|
+
/**
|
|
26
|
+
* Synthetic HTTP status codes used when no real response is available.
|
|
27
|
+
*
|
|
28
|
+
* - `0` — no request was sent or no response was received (network/DNS/config).
|
|
29
|
+
* - `408` — RFC 7231 Request Timeout: client-side timeout fired before response.
|
|
30
|
+
* - `499` — nginx convention for client-cancelled requests.
|
|
31
|
+
*/
|
|
32
|
+
export declare const STATUS_NO_RESPONSE = 0;
|
|
33
|
+
export declare const STATUS_CLIENT_TIMEOUT = 408;
|
|
34
|
+
export declare const STATUS_CLIENT_CANCELLED = 499;
|
|
35
|
+
//# sourceMappingURL=sdk-error-codes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-error-codes.d.ts","sourceRoot":"","sources":["../../src/constants/sdk-error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;CAelB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAElF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,uBAAuB,MAAM,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BugBug SDK - TypeScript SDK for BugBug API
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { createBugBug } from '@bugbug-io/sdk';
|
|
7
|
+
*
|
|
8
|
+
* const sdk = createBugBug({
|
|
9
|
+
* apiToken: 'your-api-token',
|
|
10
|
+
* verbose: true
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* // Run a test
|
|
14
|
+
* const result = await sdk.tests.startRun('my-test', {
|
|
15
|
+
* watchProgress: true,
|
|
16
|
+
* onProgress: (run) => console.log(`Status: ${run.status}`)
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Get recent test runs
|
|
20
|
+
* const recentTests = await sdk.tests.getRecentRuns({ hours: 24 });
|
|
21
|
+
*
|
|
22
|
+
* // Run a suite
|
|
23
|
+
* const suiteResult = await sdk.suites.startRun('suite-id', {
|
|
24
|
+
* watchProgress: true
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import type { BugBugConfig } from './types/config';
|
|
29
|
+
import { BugBugSDK } from './sdk';
|
|
30
|
+
/**
|
|
31
|
+
* Factory function that creates a new {@link BugBugSDK} instance.
|
|
32
|
+
*
|
|
33
|
+
* Prefer this over `new BugBugSDK(...)` — it keeps call sites concise and is the
|
|
34
|
+
* documented entry point for the SDK.
|
|
35
|
+
*
|
|
36
|
+
* @param config - SDK configuration (API token, base URL, rate limits, etc.)
|
|
37
|
+
* @returns A fully initialized SDK instance with all modules ready to use
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* import { createBugBug } from '@bugbug-io/sdk';
|
|
42
|
+
*
|
|
43
|
+
* const sdk = createBugBug({ apiToken: process.env.BUGBUG_API_TOKEN! });
|
|
44
|
+
*
|
|
45
|
+
* const result = await sdk.tests.startRun('my-test', { watchProgress: true });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function createBugBug(config: BugBugConfig): BugBugSDK;
|
|
49
|
+
export { BugBugSDK } from './sdk';
|
|
50
|
+
export type { BugBugConfig, RequestOptions, WaitOptions, RequestHook, RequestErrorHook, } from './types/config';
|
|
51
|
+
export type { RateLimitConfig } from './services/rateLimiter/rateLimiter.types';
|
|
52
|
+
export { TestsModule } from './modules/tests/tests';
|
|
53
|
+
export type { ImportTestOptions, ListTestRunsOptions, ListTestsOptions, RunTestBaseOptions, RunTestNoWatchProgressOptions, RunTestWatchProgressOptions, } from './modules/tests/tests.types';
|
|
54
|
+
export { SuitesModule } from './modules/suites/suites';
|
|
55
|
+
export type { ListSuiteRunsOptions, ListSuitesOptions, RunSuiteBaseOptions, RunSuiteNoWatchProgressOptions, RunSuiteWatchProgressOptions, } from './modules/suites/suites.types';
|
|
56
|
+
export { ProfilesModule } from './modules/profiles/profiles';
|
|
57
|
+
export { ConfigModule } from './modules/config/config';
|
|
58
|
+
export { GroupsModule } from './modules/groups/groups';
|
|
59
|
+
export { ComponentsModule } from './modules/components/components';
|
|
60
|
+
export { StepsModule } from './modules/steps/steps';
|
|
61
|
+
export { StepRunsModule } from './modules/stepRuns/stepRuns';
|
|
62
|
+
export { ProjectModule } from './modules/project/project';
|
|
63
|
+
export { ProjectArtifactsModule } from './modules/projectArtifacts/projectArtifacts';
|
|
64
|
+
export type { ProjectArtifact, UploadProjectArtifactOptions, } from './modules/projectArtifacts/projectArtifacts.types';
|
|
65
|
+
export { ProjectsModule } from './modules/projects/projects';
|
|
66
|
+
export type { Project, ProjectsListResponse, ProjectsListQuery, } from './modules/projects/projects.types';
|
|
67
|
+
export { VariablesModule } from './modules/variables/variables';
|
|
68
|
+
export type { CreateVariableOptions, UpdateVariableOptions, } from './modules/variables/variables.types';
|
|
69
|
+
export { VisualRegressionModule } from './modules/visualRegression/visualRegression';
|
|
70
|
+
export { VISUAL_REGRESSION_RESOLUTION_ACTIONS, VISUAL_REGRESSION_RESOLUTION_TYPE_BY_ACTION, } from './modules/visualRegression/visualRegression.constants';
|
|
71
|
+
export type { VisualRegressionResolutionAction } from './modules/visualRegression/visualRegression.constants';
|
|
72
|
+
export type { VisualRegressionResolutionType, VisualRegressionResolveResponse, VisualRegressionResolveResult, } from './modules/visualRegression/visualRegression.types';
|
|
73
|
+
export { AuthModule } from './modules/auth/auth';
|
|
74
|
+
export type { AuthAuthorizeParams, AuthAuthorizeResponse, AuthIdentity, AuthTokenRequest, AuthTokenResponse, } from './modules/auth/auth.types';
|
|
75
|
+
export { BUGBUG_CLI_OAUTH_CLIENT_ID, BUGBUG_MCP_OAUTH_CLIENT_ID, BUGBUG_OAUTH_CODE_CHALLENGE_METHOD, } from './modules/auth/auth.types';
|
|
76
|
+
export { createOAuthCodeChallenge, createOAuthCodeVerifier, createOAuthState, } from './modules/auth/auth.utils';
|
|
77
|
+
export { ASSERTION_STEP_TYPES, VISUAL_REGRESSION_STEP_TYPES, isAssertionStepType, isVisualRegressionStepType, } from './modules/steps/steps.utils';
|
|
78
|
+
export { BugBugError, AuthenticationError, AuthorizationError, ValidationError, ConfigurationError, MissingProjectIdError, NotFoundError, RateLimitError, TimeoutError, NetworkError, CancellationError, InternalServerError, ServiceUnavailableError, UnexpectedResponseError, HttpError, isBugBugError, isAuthenticationError, isAuthorizationError, isValidationError, isConfigurationError, isMissingProjectIdError, isNotFoundError, isRateLimitError, isTimeoutError, isNetworkError, isCancellationError, isInternalServerError, isServiceUnavailableError, isUnexpectedResponseError, isHttpError, } from './types/errors';
|
|
79
|
+
export type { RequestOrigin } from './types/errors';
|
|
80
|
+
export { SDK_ERROR_CODES } from './constants/sdk-error-codes';
|
|
81
|
+
export type { SdkErrorCode } from './constants/sdk-error-codes';
|
|
82
|
+
export type { ComponentsListQuery, ComponentsListResponse, DebugArtifact, DebugArtifactByType, DebugArtifactType, DebugArtifactsListResponse, Group, GroupCreateRequest, GroupPartialUpdateRequest, GroupUpdateRequest, GroupsListQuery, GroupsListResponse, ImportFormat, InsertGroup, InsertGroupResponse, IpAddressesResponse, Profile, ProfilesListQuery, ProfilesListResponse, ProjectSettings, RunMode, RunSuiteRequest, RunSuiteResponse, RunTestRequest, RunTestResponse, Screenshot, Selector, SelectorsGroup, SelectorsPreset, ScreenSizeType, Status, StepCreateRequest, StepDetails, StepPatchRequest, StepRunDetails, StepSource, StepType, StepUpdateRequest, Suite, SuiteCreateRequest, SuitePartialUpdateRequest, SuiteRun, SuiteRunScreenshotsResponse, SuiteRunsListQuery, SuiteRunState, SuiteRunsListResponse, SuiteSummary, SuiteUpdateRequest, SuitesListQuery, SuitesListResponse, Test, TestCreateRequest, TestRun, TestRunScreenshotsResponse, TestRunsListQuery, TestRunState, TestRunsListResponse, TestSummary, TestUpdateRequest, TestsListQuery, TestsListResponse, UnlinkComponentRequest, UnlinkComponentResponse, UpdateStepPositionRequest, UpdateStepPositionResponse, UpdateStepWaitingCondition, Variable, CreatedVariable, CreateVariableRequest, UpdateVariableRequest, VariablesListResponse, VisualRegressionRefScreenshot, VisualRegressionRefScreenshotCreate, VisualRegressionRefScreenshotPatch, VisualRegressionResolveRequest, VisualRegressionRefScreenshotsListQuery, VisualRegressionRefScreenshotUpdate, VisualRegressionRefScreenshotsListResponse, StepErrorCode, } from '@bugbug-io/api-schema';
|
|
83
|
+
export { CursorSchema, DebugArtifactByTypeSchema, PageSizeSchema, RUN_MODES, RunModeSchema, SelectorsPresetSchema, ScreenSizeTypeSchema, StatusSchema, StepCreateSchema, StepErrorCodeSchema, StepSchema, StepTypeSchema, StepUpdateSchema, UuidSchema, } from '@bugbug-io/api-schema/schemas';
|
|
84
|
+
export { STEP_ERROR_CODES } from '@bugbug-io/api-schema';
|
|
85
|
+
export type { ConnectivityStatus, SdkSystemInfo } from './types/sdk';
|
|
86
|
+
export { isCompletedStatus, isEditingStatus, isFailedStatus, isPassedStatus, isRunningStatus, } from './types/sdk';
|
|
87
|
+
//# sourceMappingURL=index.d.ts.map
|