@appliqation/automation-sdk 2.1.0 → 2.1.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/README.md CHANGED
@@ -1,69 +1,174 @@
1
- # Appliqation Automation Integration SDK
1
+ # Appliqation Automation SDK
2
2
 
3
- A powerful SDK for integrating test automation results with the Appliqation portal. Supports **Playwright** (v2.0+) with built-in reporters, plus **Cypress and Jest** (coming soon).
3
+ A powerful SDK for integrating Playwright test results with the Appliqation test management portal.
4
4
 
5
- ## Features
5
+ **What it does:**
6
+ - ✅ Automatically creates test runs in Appliqation
7
+ - ✅ Handles browser authentication with JWT tokens
8
+ - ✅ Reports test results (passed/failed/skipped) to your portal
9
+ - ✅ Tracks browser, OS, and device information
10
+ - ✅ Manages test case mappings via UUIDs
6
11
 
7
- - 🎯 **Modern Architecture** - API key authentication, run matrix management
8
- - 🔧 **Built-in Reporters** - Native Playwright integration (Cypress & Jest in progress)
9
- - 🆔 **Automatic Run Management** - Creates run matrices with browser/device/OS tracking
10
- - 📊 **Batch Operations** - Efficient batch result submission
11
- - 🔄 **Retry Logic** - Built-in retry mechanism for reliability
12
- - 📝 **Flexible Logging** - Configurable logging levels
13
- - 🛡️ **Error Handling** - Comprehensive error handling and validation
14
- - 🎨 **Custom Run Titles** - Set custom test run names via environment variables or config
12
+ **Perfect for:**
13
+ - QA teams running automated regression tests
14
+ - CI/CD pipelines needing test result tracking
15
+ - Teams using Appliqation for test management
15
16
 
16
- ## 🚩 Framework Support Status
17
+ ---
17
18
 
18
- | Framework | Status | Reporter Available |
19
- |-----------|--------|-------------------|
20
- | Playwright | ✅ **Production Ready** | Yes - `@appliqation/playwright` |
21
- | Cypress | 🚧 **In Development** | Coming in v2.1.0 |
22
- | Jest | 🚧 **In Development** | Coming in v2.1.0 |
23
- | Others | ⏳ **Planned** | Use core SDK directly |
19
+ ## Prerequisites
24
20
 
25
- ## 🚀 Quick Start
21
+ Before you begin, ensure you have:
26
22
 
27
- ### Installation
23
+ 1. **Node.js 16+** installed
24
+ ```bash
25
+ node --version # Should be v16.0.0 or higher
26
+ ```
27
+
28
+ 2. **Playwright** installed in your project
29
+ ```bash
30
+ npm install @playwright/test
31
+ ```
32
+
33
+ 3. **Appliqation Account** with:
34
+ - Access to Appliqation portal
35
+ - API key (get from your project settings)
36
+ - Project key (get from your project settings)
37
+
38
+ ---
39
+
40
+ ## Quick Start
41
+
42
+ Follow these steps in order to integrate the SDK with your Playwright tests.
43
+
44
+ ### Step 1: Install the SDK
45
+
46
+ Navigate to your Playwright project and install the SDK:
28
47
 
29
48
  ```bash
30
- npm install @appliqation/automation-sdk
49
+ npm install @appliqation/automation-sdk dotenv
31
50
  ```
32
51
 
33
- ### Playwright (Recommended - Production Ready)
52
+ **Why dotenv?** The SDK uses environment variables for configuration, and dotenv loads them from your `.env` file.
53
+
54
+ ---
34
55
 
35
- Add the Appliqation reporter to your `playwright.config.js`:
56
+ ### Step 2: Create .env File
57
+
58
+ Create a `.env` file in your project root with your Appliqation credentials:
59
+
60
+ **File:** `.env`
61
+ ```bash
62
+ # IMPORTANT: No spaces around = signs, no trailing slashes on URLs
63
+
64
+ APPLIQATION_BASE_URL=https://your-domain.appliqation.com
65
+ APPLIQATION_API_KEY=appq_live_xxxxxxxxxxxxxxxxxxxx
66
+ APPLIQATION_PROJECT_KEY=your-project-key-here
67
+ APPLIQATION_ENVIRONMENT=Your-test-environment-name
68
+ APPLIQATION_RUN_TITLE=Give-name-to-your-testrun
69
+ ```
70
+
71
+ **How to get these values:**
72
+ - `APPLIQATION_BASE_URL` - Your Appliqation portal URL (no trailing slash!)
73
+ - `APPLIQATION_API_KEY` - Found in your project settings
74
+ - `APPLIQATION_PROJECT_KEY` - Found in your project settings
75
+ - `APPLIQATION_ENVIRONMENT` - Environment name (Local, Staging, Production, etc. Found in your project settings)
76
+ -
77
+
78
+ **⚠️ Add .env to .gitignore** to keep credentials secret:
79
+ ```bash
80
+ echo ".env" >> .gitignore
81
+ ```
82
+
83
+ ---
84
+
85
+ ### Step 3: Update playwright.config.js
86
+
87
+ Update your Playwright configuration to use the SDK's built-in features:
88
+
89
+ **File:** `playwright.config.js`
36
90
 
37
91
  ```javascript
38
- const { AppliqationReporter } = require('@appliqation/automation-sdk/playwright');
92
+ const { defineConfig } = require('@playwright/test');
93
+ require('dotenv').config(); // Load .env variables
94
+
95
+ // SDK configuration
96
+ const appliqationConfig = {
97
+ baseUrl: process.env.APPLIQATION_BASE_URL,
98
+ apiKey: process.env.APPLIQATION_API_KEY,
99
+ projectKey: process.env.APPLIQATION_PROJECT_KEY,
100
+ environment: process.env.APPLIQATION_ENVIRONMENT,
101
+ title: process.env.APPLIQATION_RUN_TITLE, // Custom run title (optional)
102
+
103
+ // Optional settings
104
+ autoCreateRun: true, // Automatically create run on test start
105
+ batchSubmit: true, // Batch results for efficiency
106
+ batchSize: 50, // Results per batch
107
+ logOrphans: true, // Log tests without UUID mappings
108
+ logLevel: 'INFO' // INFO, DEBUG, ERROR
109
+ };
110
+
111
+ module.exports = defineConfig({
112
+ testDir: './tests',
113
+
114
+ // SDK's built-in global setup (handles auth + run creation)
115
+ globalSetup: require.resolve('@appliqation/automation-sdk/playwright/global-setup'),
116
+ globalTeardown: require.resolve('@appliqation/automation-sdk/playwright/global-teardown'),
117
+
118
+ use: {
119
+ baseURL: process.env.APPLIQATION_BASE_URL,
120
+
121
+ // Use SDK-managed authentication state
122
+ storageState: '.auth/jwt.json',
123
+
124
+ // Ignore HTTPS errors for local development
125
+ ignoreHTTPSErrors: true,
126
+ },
39
127
 
40
- module.exports = {
41
128
  reporter: [
42
- ['list'],
43
- [AppliqationReporter, {
44
- baseUrl: process.env.APPLIQATION_BASE_URL,
45
- apiKey: process.env.APPLIQATION_API_KEY,
46
- projectKey: process.env.APPLIQATION_PROJECT_KEY,
47
- scenarioId: parseInt(process.env.APPLIQATION_SCENARIO_ID),
48
- environment: process.env.APPLIQATION_ENVIRONMENT || 'Local',
49
- title: process.env.APPLIQATION_RUN_TITLE, // Custom run title (optional)
50
- autoCreateRun: true
51
- }]
129
+ ['list'], // Console output
130
+ ['html'], // HTML report
131
+
132
+ // Appliqation reporter for result submission
133
+ ['@appliqation/automation-sdk/playwright', appliqationConfig]
134
+ ],
135
+
136
+ projects: [
137
+ {
138
+ name: 'chromium',
139
+ use: {
140
+ browserName: 'chromium',
141
+ storageState: '.auth/jwt.json' // Authenticated browser state
142
+ }
143
+ }
52
144
  ]
53
- };
145
+ });
54
146
  ```
55
147
 
56
- Add UUIDs to your tests using the `mapAppqUuid` helper:
148
+ **What this does:**
149
+ - ✅ Loads environment variables from `.env`
150
+ - ✅ Configures SDK with your credentials
151
+ - ✅ Uses SDK's built-in `global-setup.js` to handle authentication automatically
152
+ - ✅ Saves authenticated browser state to `.auth/jwt.json`
153
+ - ✅ All tests use authenticated sessions (no login required!)
154
+ - ✅ Reports results to Appliqation portal
155
+
156
+ ---
157
+
158
+ ### Step 4: Add UUIDs to Your Tests
159
+
160
+ Map your automated tests to Appliqation test cases using `mapAppqUuid()`:
161
+
162
+ **File:** `tests/example.spec.js`
57
163
 
58
164
  ```javascript
59
165
  const { test, expect } = require('@playwright/test');
60
166
  const { mapAppqUuid } = require('@appliqation/automation-sdk/utils');
61
167
 
62
168
  test('should login successfully', async ({ page }, testInfo) => {
63
- // Map test to Appliqation test case
169
+ // Map this test to Appliqation test case UUID
64
170
  mapAppqUuid(testInfo, '1154-7a17b809-0ff9-4ba1-9322-4eb2a49abfc5');
65
171
 
66
- // Your test code
67
172
  await page.goto('/login');
68
173
  await page.fill('#username', 'user@example.com');
69
174
  await page.fill('#password', 'password');
@@ -71,163 +176,594 @@ test('should login successfully', async ({ page }, testInfo) => {
71
176
 
72
177
  await expect(page).toHaveURL('/dashboard');
73
178
  });
74
- ```
75
179
 
76
- **Alternative (Manual Annotation):**
77
- ```javascript
78
- test('should login successfully', async ({ page }) => {
79
- // Add UUID annotation manually
80
- test.info().annotations.push({
81
- type: 'appliqation-uuid',
82
- description: '1154-7a17b809-0ff9-4ba1-9322-4eb2a49abfc5'
83
- });
180
+ test('should display user profile', async ({ page }, testInfo) => {
181
+ // Different test case, different UUID
182
+ mapAppqUuid(testInfo, '1154-8b28c910-1aa0-5cc2-a433-5fc6a4d82dc6');
84
183
 
85
- // Your test code...
184
+ await page.goto('/profile');
185
+ await expect(page.locator('h1')).toContainText('My Profile');
86
186
  });
87
187
  ```
88
188
 
89
- That's it! Results are automatically reported to Appliqation. 🎉
189
+ **How to get UUIDs:**
190
+ 1. Login to your Appliqation portal
191
+ 2. Navigate to your test cases
192
+ 3. Copy the UUID for each test case (format: `nid-uuid`)
193
+ 4. You can get UUID from downloading the CSV from the test scenario
90
194
 
91
- ## 📋 Configuration
195
+ **Important:**
196
+ - ⚠️ Always include `testInfo` as second parameter: `async ({ page }, testInfo) =>`
197
+ - ⚠️ Call `mapAppqUuid()` at the start of each test
198
+ - ⚠️ UUID format must be: `nid-uuid` (e.g., `1154-7a17b809-...`)
92
199
 
93
- ### Environment Variables (Recommended)
200
+ ---
94
201
 
95
- Create a `.env` file:
202
+ ### Step 5: Run Your Tests
96
203
 
97
- ```env
98
- # Appliqation SDK Configuration - API KEY BASED AUTHENTICATION
99
- # To generate an API key, go to: http://your-appliqation-instance/admin/config/appliqation/api-keys
100
- APPLIQATION_BASE_URL=http://localhost:61285
101
- APPLIQATION_API_KEY=appq_live_xxxxxxxxxxxxx
102
- APPLIQATION_PROJECT_KEY=your-project-key-here
103
- APPLIQATION_SCENARIO_ID=1154
104
- APPLIQATION_ENVIRONMENT=Local
204
+ Run your Playwright tests as normal:
205
+
206
+ ```bash
207
+ npx playwright test
208
+ ```
209
+
210
+ **What happens:**
211
+
212
+ 1. **Global Setup Runs** (once before all tests):
213
+ - Reads `.env` configuration
214
+ - Creates automation run in Appliqation portal
215
+ - Requests browser JWT token from portal
216
+ - Sets up authenticated browser session
217
+ - Saves authentication to `.auth/jwt.json`
218
+
219
+ 2. **Tests Execute**:
220
+ - Each test loads authenticated browser state
221
+ - No login required - JWT cookie already set!
222
+ - Tests run normally
223
+ - Results collected by SDK reporter
224
+
225
+ 3. **Results Submitted**:
226
+ - SDK batches results (50 per batch by default)
227
+ - Submits to Appliqation portal
228
+ - Logs any orphan tests (tests without UUIDs)
229
+
230
+ 4. **Global Teardown Runs** (once after all tests):
231
+ - Cleanup temporary files
232
+ - Log final summary
233
+
234
+ **Check your results:**
235
+ - Visit your Appliqation portal
236
+ - Navigate to the scenario you configured
237
+ - See test results in the run matrix!
105
238
 
106
- # Custom Run Title (optional) - Defaults to "Automation Run - {timestamp}" if not set
107
- # Examples:
108
- # APPLIQATION_RUN_TITLE=Sprint 24 - Regression Tests
109
- # APPLIQATION_RUN_TITLE=Nightly Build #123
110
- # APPLIQATION_RUN_TITLE=Production Smoke Tests
111
- # APPLIQATION_RUN_TITLE=
239
+ ---
112
240
 
113
- # Logging
114
- LOG_LEVEL=INFO
241
+ **That's it!** Your tests are now integrated with Appliqation.
242
+
243
+ ---
244
+
245
+ ## How It Works
246
+
247
+ Understanding the SDK's authentication and result submission flow helps troubleshoot issues.
248
+
249
+ ### Authentication & Test Execution Flow
250
+
251
+ ```
252
+ ┌─────────────────────────────────────────────────────────────────┐
253
+ │ GLOBAL SETUP (Runs Once) │
254
+ ├─────────────────────────────────────────────────────────────────┤
255
+ │ │
256
+ │ 1. Read .env configuration │
257
+ │ ├─ APPLIQATION_API_KEY │
258
+ │ ├─ APPLIQATION_PROJECT_KEY │
259
+ │ ├─ APPLIQATION_BASE_URL │
260
+ │ └─ APPLIQATION_SCENARIO_ID │
261
+ │ │ │
262
+ │ ▼ │
263
+ │ 2. Create automation run via API │
264
+ │ POST /api/automation/run/create │
265
+ │ ├─ Returns: run_id, api_token │
266
+ │ └─ Saves to: process.env.APPLIQATION_RUN_ID │
267
+ │ │ │
268
+ │ ▼ │
269
+ │ 3. Request browser JWT token │
270
+ │ POST /api/auth/jwt/browser │
271
+ │ ├─ Send: api_key │
272
+ │ └─ Returns: jwt_token, expires_in │
273
+ │ │ │
274
+ │ ▼ │
275
+ │ 4. Setup browser authentication │
276
+ │ ├─ Launch headless browser │
277
+ │ ├─ Navigate to baseURL │
278
+ │ ├─ Set cookie: appliqation_jwt = jwt_token │
279
+ │ ├─ Save storage state to: .auth/jwt.json │
280
+ │ └─ Close browser │
281
+ │ │
282
+ │ ✅ Setup complete - All tests will use authenticated state │
283
+ │ │
284
+ └─────────────────────────────────────────────────────────────────┘
285
+
286
+
287
+ ┌─────────────────────────────────────────────────────────────────┐
288
+ │ TEST EXECUTION (Per Worker) │
289
+ ├─────────────────────────────────────────────────────────────────┤
290
+ │ │
291
+ │ For each test: │
292
+ │ │
293
+ │ 1. Load storage state from .auth/jwt.json │
294
+ │ └─ Browser starts with JWT cookie already set │
295
+ │ │ │
296
+ │ ▼ │
297
+ │ 2. Run test code │
298
+ │ ├─ mapAppqUuid(testInfo, '1154-uuid-here') │
299
+ │ ├─ Execute test steps (page.goto, clicks, etc.) │
300
+ │ └─ Collect result: passed/failed/skipped │
301
+ │ │ │
302
+ │ ▼ │
303
+ │ 3. Reporter collects result │
304
+ │ ├─ Extract UUID from test.info().annotations │
305
+ │ ├─ Capture browser/OS/device metadata │
306
+ │ ├─ Add to batch queue │
307
+ │ └─ (Batch submitted when size reached or tests complete) │
308
+ │ │
309
+ └─────────────────────────────────────────────────────────────────┘
310
+
311
+
312
+ ┌─────────────────────────────────────────────────────────────────┐
313
+ │ REPORTER (After All Tests) │
314
+ ├─────────────────────────────────────────────────────────────────┤
315
+ │ │
316
+ │ 1. Batch all test results │
317
+ │ └─ Group by 50 results per batch (configurable) │
318
+ │ │ │
319
+ │ ▼ │
320
+ │ 2. Submit to portal │
321
+ │ POST /api/automation/result/batch │
322
+ │ ├─ Send: run_id, results[], api_key │
323
+ │ └─ Retry on failure (exponential backoff) │
324
+ │ │ │
325
+ │ ▼ │
326
+ │ 3. Handle orphan tests (tests without UUIDs) │
327
+ │ POST /api/automation/orphans │
328
+ │ └─ Logs tests that need UUID mapping │
329
+ │ │ │
330
+ │ ▼ │
331
+ │ ✅ All results submitted to portal │
332
+ │ │
333
+ └─────────────────────────────────────────────────────────────────┘
334
+
335
+
336
+ ┌─────────────────────────────────────────────────────────────────┐
337
+ │ GLOBAL TEARDOWN (Runs Once) │
338
+ ├─────────────────────────────────────────────────────────────────┤
339
+ │ │
340
+ │ 1. Cleanup temporary files (optional) │
341
+ │ 2. Log final summary │
342
+ │ │
343
+ │ ✅ Test run complete │
344
+ │ │
345
+ └─────────────────────────────────────────────────────────────────┘
115
346
  ```
116
347
 
117
- ### Custom Run Titles
348
+ **Key Points:**
349
+ - Authentication happens **once** in global-setup
350
+ - JWT token saved to `.auth/jwt.json`
351
+ - All test workers reuse the same authenticated state
352
+ - No per-test login required!
118
353
 
119
- You can customize the test run name in three ways:
354
+ ### SDK Architecture
120
355
 
121
- **1. Environment Variable (Recommended):**
122
- ```bash
123
- APPLIQATION_RUN_TITLE="Sprint 24 - Regression Tests" npx playwright test
124
356
  ```
357
+ ┌─────────────────────────────────────────────────────────────────┐
358
+ │ Playwright Test Suite │
359
+ │ │
360
+ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
361
+ │ │ Test File 1 │ │ Test File 2 │ │ Test File 3 │ │
362
+ │ │ │ │ │ │ │ │
363
+ │ │ mapAppqUuid()│ │ mapAppqUuid()│ │ mapAppqUuid()│ │
364
+ │ └──────────────┘ └──────────────┘ └──────────────┘ │
365
+ │ │ │ │ │
366
+ └─────────┼────────────────────┼────────────────────┼──────────────┘
367
+ │ │ │
368
+ └────────────────────┴────────────────────┘
369
+
370
+
371
+ ┌─────────────────────────────────────────┐
372
+ │ Appliqation SDK Reporter │
373
+ │ │
374
+ │ • Collects test results │
375
+ │ • Extracts UUIDs from annotations │
376
+ │ • Batches submissions │
377
+ │ • Handles browser/OS/device metadata │
378
+ └─────────────────────────────────────────┘
379
+
380
+
381
+ ┌─────────────────────────────────────────┐
382
+ │ Appliqation HTTP Client │
383
+ │ │
384
+ │ • API key authentication │
385
+ │ • Connection pooling │
386
+ │ • Exponential backoff retry │
387
+ └─────────────────────────────────────────┘
388
+
389
+
390
+ ┌─────────────────────────────────────────┐
391
+ │ Appliqation Portal API │
392
+ │ │
393
+ │ • Validates API key │
394
+ │ • Creates run matrices │
395
+ │ • Stores test results │
396
+ │ • Generates reports │
397
+ └─────────────────────────────────────────┘
398
+ ```
399
+
400
+ ### File Structure After Setup
401
+
402
+ ```
403
+ your-playwright-project/
404
+ ├── .auth/ # Auto-created by SDK global-setup
405
+ │ └── jwt.json # Browser authentication state
406
+
407
+ ├── .env # YOU CREATE THIS (Step 2)
408
+ │ ├── APPLIQATION_API_KEY=appq_live_xxxxx
409
+ │ ├── APPLIQATION_PROJECT_KEY=your-project-key
410
+ │ ├── APPLIQATION_BASE_URL=https://your-domain.com
411
+ │ ├── APPLIQATION_SCENARIO_ID=1154
412
+ │ └── APPLIQATION_ENVIRONMENT=Local
413
+
414
+ ├── playwright.config.js # YOU UPDATE THIS (Step 3)
415
+ │ ├── globalSetup: require.resolve('@appliqation/automation-sdk/playwright/global-setup')
416
+ │ ├── globalTeardown: require.resolve('@appliqation/automation-sdk/playwright/global-teardown')
417
+ │ ├── use: { storageState: '.auth/jwt.json' }
418
+ │ └── reporter: ['@appliqation/automation-sdk/playwright', config]
419
+
420
+ ├── tests/
421
+ │ ├── login.spec.js # YOUR TESTS (Step 4)
422
+ │ │ ├── const { mapAppqUuid } = require('@appliqation/automation-sdk/utils');
423
+ │ │ └── mapAppqUuid(testInfo, '1154-uuid-here');
424
+ │ │
425
+ │ └── checkout.spec.js
426
+
427
+ ├── package.json
428
+ │ └── dependencies:
429
+ │ ├── @playwright/test
430
+ │ ├── @appliqation/automation-sdk
431
+ │ └── dotenv # Required for .env loading
432
+
433
+ └── node_modules/
434
+ └── @appliqation/automation-sdk/
435
+ └── playwright/
436
+ ├── global-setup.js # SDK provides this!
437
+ ├── global-teardown.js # SDK provides this!
438
+ └── index.js # Reporter
439
+ ```
440
+
441
+ ---
442
+
443
+ ## Configuration Reference
444
+
445
+ ### Environment Variables (.env)
446
+
447
+ All environment variables and their purposes:
448
+
449
+ | Variable | Required | Description | Example |
450
+ |----------|----------|-------------|---------|
451
+ | `APPLIQATION_BASE_URL` | ✅ Yes | Your Appliqation portal URL (no trailing slash) | `https://portal.appliqation.com` |
452
+ | `APPLIQATION_API_KEY` | ✅ Yes | API key from `/admin/config/appliqation/api-keys` | `appq_live_abc123xyz...` |
453
+ | `APPLIQATION_PROJECT_KEY` | ✅ Yes | Project key from project settings | `my-project-key` |
454
+ | `APPLIQATION_SCENARIO_ID` | ✅ Yes | Scenario node ID to track | `1154` |
455
+ | `APPLIQATION_ENVIRONMENT` | ❌ No | Environment name (default: `Local`) | `Staging`, `Production` |
456
+ | `APPLIQATION_RUN_TITLE` | ❌ No | Custom run title (default: auto-generated) | `Sprint 24 - Regression` |
457
+ | `LOG_LEVEL` | ❌ No | Logging verbosity (default: `INFO`) | `DEBUG`, `ERROR` |
458
+
459
+ ### Reporter Options (playwright.config.js)
460
+
461
+ All available options for the Appliqation reporter config:
125
462
 
126
- **2. Config File (playwright.config.js):**
127
463
  ```javascript
128
- [AppliqationReporter, {
129
- // ...other config
130
- title: "Sprint 24 - Regression Tests"
131
- }]
464
+ const appliqationConfig = {
465
+ // Required
466
+ baseUrl: process.env.APPLIQATION_BASE_URL,
467
+ apiKey: process.env.APPLIQATION_API_KEY,
468
+ projectKey: process.env.APPLIQATION_PROJECT_KEY,
469
+ scenarioId: parseInt(process.env.APPLIQATION_SCENARIO_ID),
470
+
471
+ // Optional
472
+ environment: 'Local', // Environment name
473
+ title: 'My Custom Run', // Custom run title
474
+ autoCreateRun: true, // Auto-create run (default: true)
475
+ batchSubmit: true, // Batch results (default: true)
476
+ batchSize: 50, // Results per batch (default: 50)
477
+ logOrphans: true, // Log tests without UUIDs (default: true)
478
+ logLevel: 'INFO', // INFO, DEBUG, ERROR (default: INFO)
479
+ rejectUnauthorized: false // Allow self-signed certs (default: false)
480
+ };
132
481
  ```
133
482
 
134
- **3. SDK Client (Programmatic):**
483
+ **Common Configurations:**
484
+
485
+ **CI/CD Pipeline:**
135
486
  ```javascript
136
- const client = new AppliqationClient({
137
- baseUrl: 'https://your-instance.appliqation.com',
138
- apiKey: 'appq_live_xxxxxxxxxxxxx',
139
- projectKey: 'your-project-key',
140
- title: 'Sprint 24 - Regression Tests'
141
- });
487
+ {
488
+ environment: process.env.CI_ENVIRONMENT || 'CI',
489
+ title: `Build #${process.env.CI_BUILD_NUMBER}`,
490
+ logLevel: 'ERROR', // Less verbose in CI
491
+ batchSize: 100 // Larger batches for speed
492
+ }
142
493
  ```
143
494
 
144
- **Priority:** Config → Env Var → Default ("Automation Run - {timestamp}")
495
+ **Local Development:**
496
+ ```javascript
497
+ {
498
+ environment: 'Local',
499
+ logLevel: 'DEBUG', // Detailed logs
500
+ logOrphans: true, // See unmapped tests
501
+ rejectUnauthorized: false // Allow local SSL
502
+ }
503
+ ```
145
504
 
146
- ## 🔧 Framework Integration Examples
505
+ ---
147
506
 
148
- ### Playwright (Production Ready)
507
+ ## Adding Test Case UUIDs
149
508
 
150
- See Quick Start above for full Playwright integration. The reporter automatically:
151
- - Creates run matrices with browser/device/OS detection
152
- - Extracts UUIDs from test annotations
153
- - Batches and submits results
154
- - Handles orphan tests (tests without UUIDs)
509
+ Map your automated tests to Appliqation test cases to track results.
155
510
 
156
- ### Cypress 🚧 (Coming in v2.1.0)
511
+ ### Method: mapAppqUuid()
157
512
 
158
- Will work similarly to Playwright:
513
+ **Import the utility:**
514
+ ```javascript
515
+ const { mapAppqUuid } = require('@appliqation/automation-sdk/utils');
516
+ ```
159
517
 
518
+ **Use in tests:**
160
519
  ```javascript
161
- // cypress.config.js
162
- const { CypressReporter } = require('@appliqation/automation-sdk/cypress');
520
+ test('test description', async ({ page }, testInfo) => {
521
+ // ^^^^^^^^ Required parameter!
163
522
 
164
- module.exports = defineConfig({
165
- e2e: {
166
- setupNodeEvents(on, config) {
167
- CypressReporter(on, {
168
- baseUrl: process.env.APPLIQATION_BASE_URL,
169
- apiKey: process.env.APPLIQATION_API_KEY,
170
- projectKey: process.env.APPLIQATION_PROJECT_KEY,
171
- scenarioId: parseInt(process.env.APPLIQATION_SCENARIO_ID),
172
- environment: process.env.APPLIQATION_ENVIRONMENT || 'Local',
173
- title: process.env.APPLIQATION_RUN_TITLE
174
- });
175
- }
176
- }
523
+ // Map to test case UUID
524
+ mapAppqUuid(testInfo, '1154-7a17b809-0ff9-4ba1-9322-4eb2a49abfc5');
525
+
526
+ // Your test code...
177
527
  });
178
528
  ```
179
529
 
530
+ **Important:**
531
+ - ⚠️ Always include `testInfo` as second parameter
532
+ - ⚠️ UUID format: `nid-uuid` (e.g., `1154-abc123...`)
533
+ - ⚠️ Get UUIDs from Appliqation portal test cases
534
+
535
+ ### Getting UUIDs from Portal
536
+
537
+ 1. Login to Appliqation portal
538
+ 2. Navigate to **Test Cases** section
539
+ 3. Open the test case you want to map
540
+ 4. Copy the UUID (shown in test case details)
541
+ 5. Use format: `nid-uuid` where:
542
+ - `nid` = Test case node ID (e.g., `1154`)
543
+ - `uuid` = Test case UUID (e.g., `7a17b809-0ff9-4ba1-9322-4eb2a49abfc5`)
544
+
545
+ ### What About Tests Without UUIDs?
546
+
547
+ Tests without `mapAppqUuid()` calls are called **orphan tests**. The SDK will:
548
+ - ✅ Still run them normally
549
+ - ✅ Collect results
550
+ - ✅ Log them separately (if `logOrphans: true`)
551
+ - ❌ Won't report to portal (no UUID to map to)
552
+
553
+ **Check orphan logs to see which tests need UUID mapping.**
554
+
555
+ ---
556
+
557
+ ## Troubleshooting
558
+
559
+ ### Common Issues and Solutions
560
+
561
+ #### ❌ Error: "APPLIQATION_API_KEY is required"
562
+
563
+ **Cause:** `.env` file not loaded or missing variable
564
+
565
+ **Fix:**
566
+ 1. Verify `.env` file exists in project root
567
+ 2. Check variable name spelling (no typos!)
568
+ 3. Ensure `require('dotenv').config()` at top of `playwright.config.js`
569
+ 4. No spaces around `=` sign:
570
+ ```bash
571
+ # ❌ Wrong
572
+ APPLIQATION_API_KEY = appq_live_xxx
573
+
574
+ # ✅ Correct
575
+ APPLIQATION_API_KEY=appq_live_xxx
576
+ ```
577
+
578
+ ---
579
+
580
+ #### ❌ Tests redirecting to login page (authentication failed)
581
+
582
+ **Cause:** JWT authentication not working, storage state not loading
583
+
584
+ **Fix:**
585
+ 1. Verify `globalSetup` configured correctly:
586
+ ```javascript
587
+ globalSetup: require.resolve('@appliqation/automation-sdk/playwright/global-setup')
588
+ ```
589
+
590
+ 2. Check `.auth/jwt.json` file exists after global-setup runs
591
+
592
+ 3. Verify all projects use storage state:
593
+ ```javascript
594
+ projects: [{
595
+ name: 'chromium',
596
+ use: { storageState: '.auth/jwt.json' } // Must be set!
597
+ }]
598
+ ```
599
+
600
+ 4. Check `.env` has correct `APPLIQATION_BASE_URL` (no trailing slash):
601
+ ```bash
602
+ # ❌ Wrong
603
+ APPLIQATION_BASE_URL=https://portal.com/
604
+
605
+ # ✅ Correct
606
+ APPLIQATION_BASE_URL=https://portal.com
607
+ ```
608
+
609
+ ---
610
+
611
+ #### ❌ Error: "testInfo is not defined"
612
+
613
+ **Cause:** Missing `testInfo` parameter in test function
614
+
615
+ **Fix:**
180
616
  ```javascript
181
- // Add UUID to tests
182
- it('should login successfully', { uuid: '1154-7a17b809-0ff9-4ba1-9322-4eb2a49abfc5' }, () => {
183
- cy.visit('/login');
184
- cy.get('#username').type('user@example.com');
185
- cy.get('#password').type('password');
186
- cy.get('#login-button').click();
187
- cy.url().should('include', '/dashboard');
617
+ // Wrong - missing testInfo
618
+ test('my test', async ({ page }) => {
619
+ mapAppqUuid(testInfo, 'uuid-here'); // testInfo undefined!
620
+ });
621
+
622
+ // ✅ Correct - include testInfo
623
+ test('my test', async ({ page }, testInfo) => {
624
+ mapAppqUuid(testInfo, 'uuid-here');
188
625
  });
189
626
  ```
190
627
 
191
- ### Jest 🚧 (Coming in v2.1.0)
628
+ ---
629
+
630
+ #### ❌ Error: "Invalid UUID format"
192
631
 
193
- Will work similarly to Playwright:
632
+ **Cause:** UUID not in `nid-uuid` format
194
633
 
634
+ **Fix:**
195
635
  ```javascript
196
- // jest.config.js
197
- const { JestReporter } = require('@appliqation/automation-sdk/jest');
198
-
199
- module.exports = {
200
- reporters: [
201
- 'default',
202
- [JestReporter, {
203
- baseUrl: process.env.APPLIQATION_BASE_URL,
204
- apiKey: process.env.APPLIQATION_API_KEY,
205
- projectKey: process.env.APPLIQATION_PROJECT_KEY,
206
- scenarioId: parseInt(process.env.APPLIQATION_SCENARIO_ID),
207
- environment: process.env.APPLIQATION_ENVIRONMENT || 'Local',
208
- title: process.env.APPLIQATION_RUN_TITLE
209
- }]
210
- ]
636
+ // ❌ Wrong formats
637
+ mapAppqUuid(testInfo, '7a17b809-0ff9-4ba1-9322-4eb2a49abfc5'); // Missing nid
638
+ mapAppqUuid(testInfo, '1154'); // Missing UUID
639
+ mapAppqUuid(testInfo, 'test-case-123'); // Wrong format
640
+
641
+ // ✅ Correct format
642
+ mapAppqUuid(testInfo, '1154-7a17b809-0ff9-4ba1-9322-4eb2a49abfc5');
643
+ ```
644
+
645
+ ---
646
+
647
+ #### ❌ Error: "Module 'dotenv' not found"
648
+
649
+ **Cause:** `dotenv` package not installed
650
+
651
+ **Fix:**
652
+ ```bash
653
+ npm install dotenv
654
+ ```
655
+
656
+ ---
657
+
658
+ #### ❌ Results not appearing in portal
659
+
660
+ **Possible causes:**
661
+
662
+ 1. **Orphan tests** - Tests don't have `mapAppqUuid()` calls
663
+ - **Fix:** Add UUID mapping to all tests
664
+ - Enable `logOrphans: true` to see which tests are orphans
665
+
666
+ 2. **Wrong scenario ID** - Results sent to different scenario
667
+ - **Fix:** Verify `APPLIQATION_SCENARIO_ID` matches portal
668
+
669
+ 3. **API key invalid** - Authentication failed
670
+ - **Fix:** Regenerate API key from portal
671
+
672
+ 4. **Network issues** - Portal unreachable
673
+ - **Fix:** Check `APPLIQATION_BASE_URL` is accessible
674
+
675
+ ---
676
+
677
+ ### Debug Mode
678
+
679
+ Enable detailed logging to troubleshoot issues:
680
+
681
+ **In .env:**
682
+ ```bash
683
+ LOG_LEVEL=DEBUG
684
+ ```
685
+
686
+ **Or in config:**
687
+ ```javascript
688
+ const appliqationConfig = {
689
+ // ... other config
690
+ logLevel: 'DEBUG'
211
691
  };
212
692
  ```
213
693
 
694
+ **Debug output shows:**
695
+ - ✅ API requests and responses
696
+ - ✅ Authentication flow details
697
+ - ✅ Result submission batches
698
+ - ✅ Orphan test detection
699
+ - ✅ Error stack traces
700
+
701
+ ---
702
+
703
+ ### Test Connection
704
+
705
+ Verify SDK can reach your portal:
706
+
707
+ **Create test file:** `test-connection.js`
214
708
  ```javascript
215
- // Add UUID to tests
216
- test('should login successfully', async () => {
217
- // Add UUID metadata
218
- expect.getState().currentTestName = '1154-7a17b809-0ff9-4ba1-9322-4eb2a49abfc5';
219
-
220
- // Your test code
221
- const loginSuccess = await performLogin();
222
- expect(loginSuccess).toBe(true);
709
+ const AppliqationClient = require('@appliqation/automation-sdk');
710
+ require('dotenv').config();
711
+
712
+ async function testConnection() {
713
+ const client = new AppliqationClient({
714
+ baseUrl: process.env.APPLIQATION_BASE_URL,
715
+ apiKey: process.env.APPLIQATION_API_KEY,
716
+ projectKey: process.env.APPLIQATION_PROJECT_KEY
717
+ });
718
+
719
+ const result = await client.testConnection();
720
+ console.log('Connection test:', result);
721
+ }
722
+
723
+ testConnection();
724
+ ```
725
+
726
+ **Run:**
727
+ ```bash
728
+ node test-connection.js
729
+ ```
730
+
731
+ **Expected output:**
732
+ ```
733
+ Connection test: { success: true, message: 'Connected to Appliqation portal' }
734
+ ```
735
+
736
+ ---
737
+
738
+ ## Advanced Features
739
+
740
+ ### Custom Playwright Fixture (Auto JWT Refresh)
741
+
742
+ For long-running test suites, use the SDK's custom fixture to automatically refresh JWT tokens:
743
+
744
+ **File:** `playwright.config.js`
745
+ ```javascript
746
+ const { test: base } = require('@playwright/test');
747
+ const { createAppliqationFixture } = require('@appliqation/automation-sdk/playwright');
748
+
749
+ // Extend Playwright's base test with SDK fixture
750
+ const test = createAppliqationFixture(base, {
751
+ baseUrl: process.env.APPLIQATION_BASE_URL,
752
+ apiKey: process.env.APPLIQATION_API_KEY
223
753
  });
754
+
755
+ module.exports = { test };
224
756
  ```
225
757
 
226
- ## 📊 Advanced Usage (Direct SDK)
758
+ **What it does:**
759
+ - ✅ Checks JWT expiry before each test
760
+ - ✅ Automatically refreshes if < 5 minutes remaining
761
+ - ✅ Updates `.auth/jwt.json` with new token
762
+ - ✅ Prevents authentication failures in long test runs
227
763
 
228
- For custom integrations or frameworks without built-in reporters, use the core SDK directly:
764
+ ### Using Core SDK Directly
229
765
 
230
- ### Core SDK Usage
766
+ For custom integrations or non-Playwright frameworks:
231
767
 
232
768
  ```javascript
233
769
  const AppliqationClient = require('@appliqation/automation-sdk');
@@ -236,15 +772,14 @@ const AppliqationClient = require('@appliqation/automation-sdk');
236
772
  const client = new AppliqationClient({
237
773
  baseUrl: process.env.APPLIQATION_BASE_URL,
238
774
  apiKey: process.env.APPLIQATION_API_KEY,
239
- projectKey: process.env.APPLIQATION_PROJECT_KEY,
240
- title: 'My Custom Test Run'
775
+ projectKey: process.env.APPLIQATION_PROJECT_KEY
241
776
  });
242
777
 
243
- // Create run matrix
778
+ // Create run
244
779
  const run = await client.createRun({
245
780
  scenarioId: 1154,
246
781
  environment: 'Production',
247
- browsers: ['Chrome', 'Firefox'],
782
+ browsers: ['Chrome'],
248
783
  device: 'Desktop',
249
784
  os: 'Windows 11'
250
785
  });
@@ -253,7 +788,7 @@ console.log('Run created:', run.runId);
253
788
 
254
789
  // Submit single result
255
790
  await client.submitResult(run.runId, {
256
- uuid: '124-d1f9559c-b978-43cc-9c76-fd539c717cb4',
791
+ uuid: '1154-7a17b809-0ff9-4ba1-9322-4eb2a49abfc5',
257
792
  status: 'passed',
258
793
  browser: 'Chrome',
259
794
  comment: 'Test passed successfully'
@@ -261,181 +796,82 @@ await client.submitResult(run.runId, {
261
796
 
262
797
  // Submit batch results
263
798
  const results = [
264
- { uuid: '124-test1-uuid', runId: run.runId, status: 'passed', browser: 'Chrome' },
265
- { uuid: '124-test2-uuid', runId: run.runId, status: 'failed', browser: 'Chrome', comment: 'Button missing' },
266
- { uuid: '124-test3-uuid', runId: run.runId, status: 'skipped', browser: 'Chrome' }
799
+ { uuid: '1154-uuid-1', runId: run.runId, status: 'passed', browser: 'Chrome' },
800
+ { uuid: '1154-uuid-2', runId: run.runId, status: 'failed', browser: 'Chrome' }
267
801
  ];
268
802
 
269
803
  const summary = await client.submitBatch(results);
270
804
  console.log(`Submitted: ${summary.success}/${summary.total} successful`);
271
805
  ```
272
806
 
273
- ### Run Matrix Management
274
-
275
- ```javascript
276
- // Create multiple runs for cross-browser testing
277
- const configs = [
278
- { scenarioId: 1154, environment: 'Staging', browsers: ['Chrome'], device: 'Desktop', os: 'Windows 11' },
279
- { scenarioId: 1154, environment: 'Staging', browsers: ['Firefox'], device: 'Desktop', os: 'Windows 11' },
280
- { scenarioId: 1154, environment: 'Staging', browsers: ['Safari'], device: 'Desktop', os: 'macOS' }
281
- ];
282
-
283
- const result = await client.createMultipleRuns(configs);
284
- console.log(`Created ${result.summary.success} runs`);
807
+ ### Custom Run Titles
285
808
 
286
- // Add browser to existing run
287
- await client.addBrowser(run.runId, 'Edge');
809
+ Set custom titles for test runs:
288
810
 
289
- // Get run details
290
- const runData = await client.getRun(run.runId);
291
- console.log(runData);
811
+ **Method 1: Environment Variable**
812
+ ```bash
813
+ APPLIQATION_RUN_TITLE="Sprint 24 - Regression Tests" npx playwright test
292
814
  ```
293
815
 
294
- ## 🔍 API Reference
295
-
296
- ### AppliqationClient Class
297
-
298
- **Constructor:**
816
+ **Method 2: Config File**
299
817
  ```javascript
300
- new AppliqationClient(config)
301
- ```
302
- - `config.baseUrl` (string) - Appliqation instance URL
303
- - `config.apiKey` (string) - API key (appq_live_xxxxx)
304
- - `config.projectKey` (string) - Project key
305
- - `config.username` (string, optional) - Username for legacy CSRF auth
306
- - `config.password` (string, optional) - Password for legacy CSRF auth
307
- - `config.title` (string, optional) - Custom run title
308
- - `config.options` (object, optional):
309
- - `timeout` (number) - Request timeout in ms (default: 30000)
310
- - `retries` (number) - Retry attempts (default: 3)
311
- - `logOrphans` (boolean) - Log orphan tests (default: true)
312
- - `logLevel` (string) - Logging level (default: 'info')
313
-
314
- **Methods:**
315
-
316
- **createRun(options)** - Create test run matrix
317
- - `options.scenarioId` (number) - Scenario node ID
318
- - `options.testSetId` (number) - Test set node ID (alternative to scenarioId)
319
- - `options.environment` (string) - Environment name (default: 'Local')
320
- - `options.browsers` (array) - Browser names (default: ['Chrome'])
321
- - `options.device` (string) - Device type
322
- - `options.os` (string) - Operating system
323
- - `options.title` (string) - Custom run title
324
- - Returns: `{ runId, token, timestamp, metadata }`
325
-
326
- **submitResult(runId, result)** - Submit single test result
327
- - `runId` (string) - Run ID
328
- - `result.uuid` (string) - Test case UUID (format: nid-uuid)
329
- - `result.status` (string) - 'passed', 'failed', 'skipped'
330
- - `result.browser` (string) - Browser name
331
- - `result.comment` (string, optional) - Additional comments
332
- - `result.environment` (string, optional) - Environment override
333
-
334
- **submitBatch(results, options)** - Submit batch of results
335
- - `results` (array) - Array of result objects
336
- - `options.batchSize` (number) - Results per batch (default: 50)
337
- - `options.onProgress` (function) - Progress callback
338
- - `options.retryFailures` (boolean) - Retry failed submissions (default: true)
339
- - Returns: `{ success, failed, total, invalidResults }`
340
-
341
- **logOrphanTests(runId, orphanTests)** - Log tests without UUID mappings
342
- **addBrowser(runId, browser)** - Add browser to existing run
343
- **getRun(runId)** - Get run matrix data
344
- **testConnection()** - Test connectivity to Appliqation
345
- **validateUuid(uuid)** - Validate UUID format
346
- **extractNid(uuid)** - Extract NID from UUID
347
- **parseUuid(uuid)** - Validate and extract UUID components
348
-
349
- ## 🆔 Getting Test UUIDs
350
-
351
- 1. Login to your Appliqation portal
352
- 2. Navigate to your test cases
353
- 3. Download/copy the UUIDs for the test cases you want to automate
354
- 4. Use these UUIDs in your `reportResult()` calls
818
+ const appliqationConfig = {
819
+ // ... other config
820
+ title: "Sprint 24 - Regression Tests"
821
+ };
822
+ ```
355
823
 
356
- The UUIDs follow the format: `nid-uuid` (e.g., `124-d1f9559c-b978-43cc-9c76-fd539c717cb4`)
824
+ **Method 3: Programmatic (Core SDK)**
825
+ ```javascript
826
+ const client = new AppliqationClient({
827
+ // ... other config
828
+ title: "Sprint 24 - Regression Tests"
829
+ });
830
+ ```
357
831
 
358
- ## 🏃‍♂️ Run Matrix Integration
832
+ **Priority:** Config > Env Var > Default (`"Automation Run - {timestamp}"`)
359
833
 
360
- Each test run in Appliqation has a unique `run_id`. The SDK will:
834
+ ---
361
835
 
362
- 1. **Auto-generate** a run ID if not provided
363
- 2. **Use environment variable** `RUN_ID` if set
364
- 3. **Accept custom run ID** in configuration
836
+ ## API Reference
365
837
 
366
- All test results reported with the same `run_id` will appear together in your Appliqation run matrix.
838
+ ### Quick Reference
367
839
 
368
- ## 🐛 Error Handling
840
+ Most commonly used SDK exports:
369
841
 
842
+ **Reporter (for playwright.config.js):**
370
843
  ```javascript
371
- try {
372
- const response = await reportResult('124-test-uuid', 'pass');
373
- if (response.success) {
374
- console.log('✅ Result reported successfully');
375
- } else {
376
- console.error('❌ Failed to report:', response.error);
377
- }
378
- } catch (error) {
379
- console.error('❌ SDK Error:', error.message);
380
- }
844
+ ['@appliqation/automation-sdk/playwright', config]
381
845
  ```
382
846
 
383
- ## 🔧 Troubleshooting
384
-
385
- ### Common Issues
386
-
387
- 1. **Authentication Failed**
388
- ```
389
- Error: APPLIQATION_USERNAME environment variable is required
390
- ```
391
- **Solution**: Set your credentials in `.env` file or pass to `init()`
392
-
393
- 2. **Invalid UUID Format**
394
- ```
395
- Error: uuid must be in format: nid-uuid
396
- ```
397
- **Solution**: Ensure UUID follows `124-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` format
398
-
399
- 3. **Connection Issues**
400
- ```javascript
401
- // Test your connection
402
- const sdk = new AppliqationSDK();
403
- await sdk.init({ /* config */ });
404
- const result = await sdk.testConnection();
405
- console.log(result);
406
- ```
407
-
408
- ### Debug Mode
847
+ **Global Setup/Teardown:**
848
+ ```javascript
849
+ require.resolve('@appliqation/automation-sdk/playwright/global-setup')
850
+ require.resolve('@appliqation/automation-sdk/playwright/global-teardown')
851
+ ```
409
852
 
853
+ **Utilities:**
410
854
  ```javascript
411
- await init({
412
- // ... other config
413
- logLevel: 'DEBUG' // See detailed logs
414
- });
855
+ const { mapAppqUuid } = require('@appliqation/automation-sdk/utils');
415
856
  ```
416
857
 
417
- ## 📝 Migration from v0.x
858
+ **Core Client:**
859
+ ```javascript
860
+ const AppliqationClient = require('@appliqation/automation-sdk');
861
+ ```
418
862
 
419
- If you're upgrading from the old `drupal-test-results-sdk`:
863
+ ### Full API Documentation
420
864
 
421
- ```javascript
422
- // Old way
423
- const { DrupalTestResultsSDK } = require('drupal-test-results-sdk');
424
- const sdk = new DrupalTestResultsSDK(config);
425
- await sdk.insertResult(payload);
865
+ For complete API reference including all methods, parameters, and return types, see the source code documentation in the `/src` directory.
426
866
 
427
- // New way
428
- const { init, reportResult } = require('@appliqation/automation-sdk');
429
- await init(config);
430
- await reportResult(uuid, status, options);
431
- ```
867
+ ---
432
868
 
433
- ## 🤝 Support
869
+ ## Support
434
870
 
435
871
  - 📧 **Email**: support@appliqation.com
436
- - 📖 **Documentation**: [Appliqation Docs](https://docs.appliqation.com)
437
- - 🐛 **Issues**: [GitHub Issues](https://github.com/your-repo/issues)
872
+ - 📖 **Documentation**: https://docs.appliqation.com
873
+ - 🐛 **Issues**: https://github.com/appliqation/automation-sdk-js/issues
438
874
 
439
- ## 📄 License
875
+ ## License
440
876
 
441
877
  MIT License - see LICENSE file for details.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appliqation/automation-sdk",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "description": "Appliqation Automation SDK with API key authentication, custom run titles, and framework-specific reporters",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -13,6 +13,14 @@
13
13
  "require": "./src/reporters/playwright/index.js",
14
14
  "import": "./src/reporters/playwright/index.js"
15
15
  },
16
+ "./playwright/global-setup": {
17
+ "require": "./src/playwright/global-setup.js",
18
+ "import": "./src/playwright/global-setup.js"
19
+ },
20
+ "./playwright/fixture": {
21
+ "require": "./src/playwright/fixture.js",
22
+ "import": "./src/playwright/fixture.js"
23
+ },
16
24
  "./cypress": {
17
25
  "require": "./src/reporters/cypress/index.js",
18
26
  "import": "./src/reporters/cypress/index.js"
@@ -140,12 +140,13 @@ function extractSDKConfig(config) {
140
140
  * Get JWT token from Appliqation API
141
141
  *
142
142
  * @param {Object} sdkConfig - SDK configuration
143
- * @returns {Promise<Object>} JWT data { jwt_token, run_id }
143
+ * @returns {Promise<Object>} JWT data { jwt_token, run_id, user_id, project_id }
144
144
  */
145
145
  async function getJWTToken(sdkConfig) {
146
- const endpoint = `${sdkConfig.baseUrl.replace(/\/$/, '')}/api/automation/run/create`;
146
+ // STEP 1: Create automation run
147
+ const createRunEndpoint = `${sdkConfig.baseUrl.replace(/\/$/, '')}/api/automation/run/create`;
147
148
 
148
- const payload = {
149
+ const runPayload = {
149
150
  project_key: sdkConfig.projectKey,
150
151
  scenario_id: sdkConfig.scenarioId || 0,
151
152
  environment: sdkConfig.environment,
@@ -156,7 +157,7 @@ async function getJWTToken(sdkConfig) {
156
157
  };
157
158
 
158
159
  try {
159
- const response = await axios.post(endpoint, payload, {
160
+ const runResponse = await axios.post(createRunEndpoint, runPayload, {
160
161
  headers: {
161
162
  'Content-Type': 'application/json',
162
163
  'X-API-Key': sdkConfig.apiKey,
@@ -167,14 +168,39 @@ async function getJWTToken(sdkConfig) {
167
168
  validateStatus: (status) => status < 500,
168
169
  });
169
170
 
170
- if (response.status !== 200 && response.status !== 201) {
171
- throw new Error(`API returned status ${response.status}: ${response.data?.message || 'Unknown error'}`);
171
+ if (runResponse.status !== 200 && runResponse.status !== 201) {
172
+ throw new Error(`Run creation failed: ${runResponse.status} - ${runResponse.data?.message || 'Unknown error'}`);
173
+ }
174
+
175
+ const runId = runResponse.data.run_id;
176
+
177
+ // STEP 2: Get browser session JWT token
178
+ const jwtEndpoint = `${sdkConfig.baseUrl.replace(/\/$/, '')}/api/auth/jwt/browser`;
179
+
180
+ const jwtPayload = {
181
+ api_key: sdkConfig.apiKey
182
+ };
183
+
184
+ const jwtResponse = await axios.post(jwtEndpoint, jwtPayload, {
185
+ headers: {
186
+ 'Content-Type': 'application/json',
187
+ },
188
+ httpsAgent: new https.Agent({
189
+ rejectUnauthorized: false, // Allow self-signed certs in dev
190
+ }),
191
+ validateStatus: (status) => status < 500,
192
+ });
193
+
194
+ if (jwtResponse.status !== 200) {
195
+ throw new Error(`JWT generation failed: ${jwtResponse.status} - ${jwtResponse.data?.message || 'Unknown error'}`);
172
196
  }
173
197
 
174
198
  return {
175
- jwt_token: response.data.jwt_token,
176
- run_id: response.data.run_id,
177
- metadata: response.data.metadata,
199
+ jwt_token: jwtResponse.data.jwt_token,
200
+ run_id: runId,
201
+ user_id: jwtResponse.data.user_id,
202
+ project_id: jwtResponse.data.project_id,
203
+ expires_in: jwtResponse.data.expires_in,
178
204
  };
179
205
 
180
206
  } catch (error) {
@@ -197,25 +223,40 @@ async function setupBrowserWithJWT(sdkConfig, jwtToken) {
197
223
  headless: true,
198
224
  });
199
225
 
200
- const context = await browser.newContext({
201
- ignoreHTTPSErrors: true, // Allow self-signed certs in dev
202
- });
226
+ try {
227
+ // Extract domain from baseUrl for cookie
228
+ const baseUrl = sdkConfig.baseUrl.replace(/\/$/, '');
229
+ const urlObj = new URL(baseUrl);
230
+ const domain = urlObj.hostname;
231
+
232
+ // Create context with JWT cookie BEFORE navigating
233
+ const context = await browser.newContext({
234
+ ignoreHTTPSErrors: true, // Allow self-signed certs in dev
235
+ });
203
236
 
204
- const page = await context.newPage();
237
+ // Set JWT cookie
238
+ await context.addCookies([{
239
+ name: 'appliqation_jwt',
240
+ value: jwtToken,
241
+ domain: domain,
242
+ path: '/',
243
+ httpOnly: true,
244
+ secure: baseUrl.startsWith('https'),
245
+ sameSite: 'Lax'
246
+ }]);
205
247
 
206
- try {
207
- // Navigate to app with JWT token in query parameter
208
- const appUrl = sdkConfig.appUrl.replace(/\/$/, '');
209
- const separator = appUrl.includes('?') ? '&' : '?';
210
- const urlWithToken = `${appUrl}${separator}qonsole_token=${encodeURIComponent(jwtToken)}`;
248
+ console.log(` ✓ JWT cookie set for domain: ${domain}`);
211
249
 
212
- console.log(` Navigating to: ${appUrl}...`);
213
- await page.goto(urlWithToken, {
250
+ const page = await context.newPage();
251
+
252
+ // Navigate to app (no query parameter needed)
253
+ console.log(` Navigating to: ${baseUrl}...`);
254
+ await page.goto(baseUrl, {
214
255
  waitUntil: 'networkidle',
215
256
  timeout: 30000,
216
257
  });
217
258
 
218
- // Wait a bit for session to be established
259
+ // Wait for authentication to be processed
219
260
  await page.waitForTimeout(2000);
220
261
 
221
262
  // Verify authentication worked
@@ -224,14 +265,16 @@ async function setupBrowserWithJWT(sdkConfig, jwtToken) {
224
265
  throw new Error('JWT authentication failed - redirected to login page');
225
266
  }
226
267
 
227
- // Save authenticated state
268
+ console.log(' ✓ Browser authenticated successfully');
269
+
270
+ // Save authenticated state with cookie
228
271
  const authDir = path.resolve('.auth');
229
272
  if (!fs.existsSync(authDir)) {
230
273
  fs.mkdirSync(authDir, { recursive: true });
231
274
  }
232
275
 
233
276
  await context.storageState({ path: '.auth/jwt.json' });
234
- console.log(' ✓ Authenticated state saved');
277
+ console.log(' ✓ Authenticated state saved to .auth/jwt.json');
235
278
 
236
279
  } catch (error) {
237
280
  throw new Error(`Browser setup failed: ${error.message}`);