wdio-lambdatest-service-sdk 5.1.5 → 5.1.7

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,6 +1,6 @@
1
- # WDIO LambdaTest Service
1
+ # WDIO LambdaTest CLI
2
2
 
3
- WebdriverIO service and CLI for running Appium and browser tests on [LambdaTest](https://www.lambdatest.com). This SDK handles authentication, test status updates on the LambdaTest dashboard, and provides an interactive CLI to generate and setup WDIO configs that connect directly to LambdaTest automation.
3
+ CLI for running WebdriverIO and Appium tests on [LambdaTest](https://www.lambdatest.com). Use the CLI to generate or update WDIO configs that connect to LambdaTest (auth, capabilities, test status updates).
4
4
 
5
5
  ---
6
6
 
@@ -8,14 +8,14 @@ WebdriverIO service and CLI for running Appium and browser tests on [LambdaTest]
8
8
 
9
9
  - [Features](#features)
10
10
  - [Installation](#installation)
11
- - [Try the SDK / CLI with the Sample Project](#try-the-sdk--cli-with-the-sample-project)
11
+ - [Generate Config (recommended)](#generate-config-recommended)
12
+ - [CLI Commands](#cli-commands)
13
+ - [Try the CLI with the Sample Project](#try-the-cli-with-the-sample-project)
12
14
  - [Steps to Run the Sample Project](#steps-to-run-the-sample-project)
13
15
  - [Specs Folder & Code Design](#specs-folder--code-design)
14
- - [Generate Config That Connects to LT Automation](#generate-config-that-connects-to-lt-automation)
15
- - [CLI Commands](#cli-commands)
16
- - [Automated Setup](#automated-setup)
17
- - [Config Generator](#config-generator)
16
+ - [Setup Command](#setup-command)
18
17
  - [Manual Configuration](#manual-configuration)
18
+ - [Troubleshooting](#troubleshooting)
19
19
  - [Development](#development)
20
20
  - [License](#license)
21
21
 
@@ -23,11 +23,10 @@ WebdriverIO service and CLI for running Appium and browser tests on [LambdaTest]
23
23
 
24
24
  ## Features
25
25
 
26
- - **Authentication**: Pass `username` and `accessKey` in the service options or via the CLI.
27
- - **Test Status Updates**: Automatically marks tests as Passed/Failed on the LambdaTest dashboard using Lambda Hooks.
28
- - **Logs**: Clean, colorful status logs in the terminal.
29
- - **CLI**: Interactive config generator and setup tool (Commander, Chalk, Inquirer; runs with Node.js or Bun).
30
- - **Multi-select**: Choose multiple test types, device types, platforms, and app/website targets in one config.
26
+ - **CLI**: Interactive config generator (`wdio-lt generate`) and setup (`wdio-lt setup`) for existing projects.
27
+ - **Generate**: Multi-select for test type, device type, platform, app/website; creates `LT_Test/<name>.conf.js` ready to run.
28
+ - **Setup**: Injects LambdaTest service into existing `*.conf.js` files.
29
+ - **Auth & status**: Generated/setup configs use your credentials and report test status to the LambdaTest dashboard.
31
30
 
32
31
  ---
33
32
 
@@ -36,320 +35,273 @@ WebdriverIO service and CLI for running Appium and browser tests on [LambdaTest]
36
35
  Works with **Node.js** (≥18) or **Bun** (≥1.0). No Bun required.
37
36
 
38
37
  ```bash
39
- # With npm (Node.js)
40
- npm install wdio-lambdatest-service --save-dev
38
+ # Install the CLI (npm)
39
+ npm i wdio-lambdatest-service-sdk --save-dev
41
40
 
42
- # With Bun (optional)
43
- bun add wdio-lambdatest-service --dev
41
+ # Or with Bun
42
+ bun add wdio-lambdatest-service-sdk --dev
44
43
  ```
45
44
 
46
45
  ### Peer dependency conflict (ERESOLVE)
47
46
 
48
- If you see `ERESOLVE unable to resolve dependency tree` because your project uses **WebdriverIO 5 or 6** and the installed package expects a different major version, use one of these:
49
-
50
- **Option 1 – Install and allow peer mismatch (recommended):**
47
+ If you see `ERESOLVE unable to resolve dependency tree` (e.g. WebdriverIO 5 or 6), use:
51
48
 
52
49
  ```bash
53
- npm install wdio-lambdatest-service --save-dev --legacy-peer-deps
50
+ npm i wdio-lambdatest-service-sdk --save-dev --legacy-peer-deps
54
51
  ```
55
52
 
56
- **Option 2 – Force install:**
53
+ Or:
57
54
 
58
55
  ```bash
59
- npm install wdio-lambdatest-service --save-dev --force
56
+ npm i wdio-lambdatest-service-sdk --save-dev --force
60
57
  ```
61
58
 
62
- This package declares support for **@wdio/cli** and **webdriverio** `^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0`. If you are on an older published version of the service that had stricter peer deps, upgrade to the latest version or use `--legacy-peer-deps` until you can upgrade.
63
-
64
59
  ---
65
60
 
66
- ## Try the SDK / CLI with the Sample Project
61
+ ## Generate Config (recommended)
67
62
 
68
- To verify the SDK and CLI work end-to-end, clone the official LambdaTest sample project and run tests using this service.
63
+ Use the CLI to generate a WDIO config that is already wired to LambdaTest.
69
64
 
70
- ### 1. Clone the Sample Repository
65
+ ### 1. Install the CLI
71
66
 
72
67
  ```bash
73
- git clone https://github.com/LambdaTest/LT-appium-nodejs-webdriverio
74
- cd LT-appium-nodejs-webdriverio
68
+ npm i wdio-lambdatest-service-sdk --save-dev
75
69
  ```
76
70
 
77
- This repo contains:
78
-
79
- - **android-sample/** – WebdriverIO + Appium configs and scripts for Android (real/virtual).
80
- - **ios-sample/** – WebdriverIO + Appium configs and scripts for iOS.
81
- - **specs/** – Shared test specs (e.g. `android-test.js`, `ios-test.js`) used by both samples.
82
-
83
- ### 2. Install the WDIO LambdaTest Service (SDK)
84
-
85
- From the **repo root** (or from inside `android-sample` / `ios-sample` if you prefer):
71
+ ### 2. Run the generator
86
72
 
87
73
  ```bash
88
- # From repo root – install SDK as dev dependency
89
- npm install ./wdio-lambdatest-service --save-dev
90
- # or, if the SDK is published:
91
- npm install wdio-lambdatest-service
74
+ npx wdio-lt generate
92
75
  ```
93
76
 
94
- ### 3. Set LambdaTest Credentials
95
-
96
- Export your [LambdaTest](https://accounts.lambdatest.com) username and access key:
97
-
98
- **Linux / macOS:**
77
+ Or with Bun:
99
78
 
100
79
  ```bash
101
- export LT_USERNAME="your_username"
102
- export LT_ACCESS_KEY="your_access_key"
80
+ bunx wdio-lt generate
103
81
  ```
104
82
 
105
- **Windows (CMD):**
83
+ ### 3. Follow the prompts
106
84
 
107
- ```cmd
108
- set LT_USERNAME=your_username
109
- set LT_ACCESS_KEY=your_access_key
110
- ```
85
+ - **Test name** – Build name and config filename.
86
+ - **LambdaTest Username & Access Key** – Or use `LT_USERNAME` / `LT_ACCESS_KEY`.
87
+ - **Test type(s)** – App Testing and/or Browser Testing (multi-select).
88
+ - **Device type(s)** – Real / Virtual (multi-select).
89
+ - **Platform(s)** – Android / iOS (multi-select).
90
+ - **What to test** – Application (Native App) / Website (Mobile Browser) (multi-select).
91
+ - **App ID(s)** – Per platform if native app (e.g. `lt://proverbial-android`).
92
+ - **Parallel threads** – 0 for sequential.
93
+ - **Spec file path** – e.g. `../specs/android-test.js` (relative to config dir).
111
94
 
112
- **Windows (PowerShell):**
95
+ ### 4. Output
113
96
 
114
- ```powershell
115
- $env:LT_USERNAME = "your_username"
116
- $env:LT_ACCESS_KEY = "your_access_key"
117
- ```
97
+ - **Config:** `LT_Test/<TestName>.conf.js`
98
+ - **Script in** `LT_Test/package.json`: `test:<TestName>`
118
99
 
119
- ### 4. Run the Sample Project
100
+ ### 5. Run
120
101
 
121
- See [Steps to Run the Sample Project](#steps-to-run-the-sample-project) below for detailed run commands (single/parallel, Android/iOS).
102
+ ```bash
103
+ cd LT_Test
104
+ npm run test:<TestName>
105
+ ```
122
106
 
123
107
  ---
124
108
 
125
- ## Steps to Run the Sample Project
109
+ ## CLI Commands
126
110
 
127
- After cloning [LT-appium-nodejs-webdriverio](https://github.com/LambdaTest/LT-appium-nodejs-webdriverio) and setting credentials:
111
+ | Command | Description |
112
+ |--------|-------------|
113
+ | `wdio-lt generate` | Interactively generate a new WDIO config for LambdaTest |
114
+ | `wdio-lt init` | Alias for `generate` |
115
+ | `wdio-lt setup [path]` | Inject LambdaTest service into existing WDIO config files |
116
+ | `wdio-lt --help` | Show help |
117
+ | `wdio-lt --version` | Show version |
128
118
 
129
- ### Android
119
+ ### Full usage (all commands)
120
+
121
+ **With npx (Node.js):**
130
122
 
131
123
  ```bash
132
- cd android-sample
133
- npm install
134
- # Single test
135
- npm run SingleAndroidApp
136
- # Or run parallel (if defined in package.json)
137
- npm run parallel
124
+ # Show help and version
125
+ npx wdio-lt --help
126
+ npx wdio-lt -h
127
+ npx wdio-lt --version
128
+ npx wdio-lt -v
129
+
130
+ # Generate – create a new WDIO config (interactive)
131
+ npx wdio-lt generate
132
+ npx wdio-lt gen
133
+ npx wdio-lt init
134
+
135
+ # Setup – inject LambdaTest service into existing configs
136
+ npx wdio-lt setup
137
+ npx wdio-lt setup .
138
+ npx wdio-lt setup ./android-sample
139
+ npx wdio-lt setup ./path/to/your/project
138
140
  ```
139
141
 
140
- ### iOS
142
+ **With Bun:**
141
143
 
142
144
  ```bash
143
- cd ios-sample
144
- npm install
145
- # Single test (script name may vary, e.g. SingleIosApp)
146
- npm run single
147
- # Or run parallel
148
- npm run parallel
145
+ bunx wdio-lt --help
146
+ bunx wdio-lt --version
147
+ bunx wdio-lt generate
148
+ bunx wdio-lt gen
149
+ bunx wdio-lt init
150
+ bunx wdio-lt setup
151
+ bunx wdio-lt setup ./android-sample
149
152
  ```
150
153
 
151
- **Note:** Ensure config files in `android-sample` and `ios-sample` point to the correct spec paths (e.g. `../specs/android-test.js`, `../specs/ios-test.js`) and that the WDIO LambdaTest service is registered in `services` in those configs. Test results appear in the terminal and on the [LambdaTest App Automation Dashboard](https://appautomation.lambdatest.com/).
154
+ **Using the installed binary (after `npm i wdio-lambdatest-service-sdk --save-dev`):**
152
155
 
153
- ---
154
-
155
- ## Specs Folder & Code Design
156
+ ```bash
157
+ # From project root (node_modules/.bin in PATH)
158
+ wdio-lt --help
159
+ wdio-lt --version
160
+ wdio-lt generate
161
+ wdio-lt init
162
+ wdio-lt setup
163
+ wdio-lt setup ./android-sample
156
164
 
157
- The sample repo uses a **shared `specs/` folder** at the root so both Android and iOS (and any generated configs) can reuse the same test files.
165
+ # Or via npm run (add to package.json "scripts")
166
+ npm run lt:generate # "lt:generate": "wdio-lt generate"
167
+ npm run lt:setup # "lt:setup": "wdio-lt setup ./android-sample"
168
+ ```
158
169
 
159
- Recommended layout (align with the sample repo):
170
+ **Alternative binary name (same CLI):**
160
171
 
161
- ```
162
- LT-appium-nodejs-webdriverio/
163
- ├── android-sample/
164
- │ ├── conf/ # or *.conf.js in root of android-sample
165
- │ │ └── android.conf.js
166
- │ ├── package.json
167
- │ └── ...
168
- ├── ios-sample/
169
- │ ├── conf/
170
- │ │ └── ios.conf.js
171
- │ ├── package.json
172
- │ └── ...
173
- ├── specs/ # Shared test specs
174
- │ ├── android-test.js
175
- │ ├── ios-test.js
176
- │ └── (your own specs)
177
- ├── wdio-lambdatest-service/ # This SDK (if developed locally)
178
- └── package.json
172
+ ```bash
173
+ npx wdio-lambdatest generate
174
+ npx wdio-lambdatest setup ./android-sample
179
175
  ```
180
176
 
181
- **Design guidelines:**
177
+ **Legacy commands (backward compatible):**
182
178
 
183
- - **One spec file per flow or platform** (e.g. `android-test.js`, `ios-test.js`, `web-test.js`) so configs can reference them clearly.
184
- - **Use `specs: ["../specs/android-test.js"]`** (or similar relative path) in configs under `android-sample` so they point to the shared `specs/` folder.
185
- - **Keep assertions and page interactions in the specs**; keep capabilities and environment in the config files.
186
- - **Reuse the same spec** across different configs (e.g. single device vs parallel) by only changing the config, not the spec.
187
-
188
- Following this structure makes it easy to add new configs (including those generated by `wdio-lt generate`) that point to the same `specs/` folder.
179
+ ```bash
180
+ npx wdio-lambdatest-setup ./android-sample
181
+ npx wdio-lambdatest-generator
182
+ ```
189
183
 
190
184
  ---
191
185
 
192
- ## Generate Config That Connects to LT Automation
193
-
194
- Use the CLI to generate a WDIO config that is **already wired to LambdaTest** (hostname, path, services, and capabilities).
195
-
196
- ### 1. Install the CLI
186
+ ## Try the CLI with the Sample Project
197
187
 
198
- If the SDK is in the repo:
188
+ 1. **Clone the sample repo**
199
189
 
200
190
  ```bash
191
+ git clone https://github.com/LambdaTest/LT-appium-nodejs-webdriverio
201
192
  cd LT-appium-nodejs-webdriverio
202
- npm install ./wdio-lambdatest-service --save-dev
203
193
  ```
204
194
 
205
- Or install from npm (when published):
195
+ 2. **Install the CLI**
206
196
 
207
197
  ```bash
208
- npm install wdio-lambdatest-service --save-dev
198
+ npm i wdio-lambdatest-service-sdk --save-dev
209
199
  ```
210
200
 
211
- ### 2. Run the Config Generator
201
+ 3. **Set credentials**
212
202
 
213
- ```bash
214
- # With Node.js
215
- npx wdio-lt generate
203
+ **Linux / macOS:**
216
204
 
217
- # With Bun (optional)
218
- bunx wdio-lt generate
205
+ ```bash
206
+ export LT_USERNAME="your_username"
207
+ export LT_ACCESS_KEY="your_access_key"
219
208
  ```
220
209
 
221
- ### 3. Follow the Prompts
222
-
223
- - **Test name** – Used for build name and config filename.
224
- - **LambdaTest Username & Access Key** – Stored in the generated config (or use env vars and leave blank if you rely on `LT_USERNAME` / `LT_ACCESS_KEY`).
225
- - **Test type(s)** – App Testing (Mobile) and/or Browser Testing (Desktop). You can select multiple.
226
- - **Device type(s)** – Real Device, Virtual Device (for App Testing). Multi-select.
227
- - **Platform(s)** – Android, iOS. Multi-select.
228
- - **What do you want to test?** – Application (Native App), Website (Mobile Browser). Multi-select.
229
- - **App ID(s)** – If you chose native app, enter the App URL (e.g. `lt://APP123456789`) per platform; you can use sample apps (e.g. `lt://proverbial-android`, `lt://proverbial-ios`).
230
- - **Parallel threads** – 0 for sequential, or a number for parallel.
231
- - **Spec file path** – Path to your test file, e.g. `./specs/test.js` or `../specs/android-test.js` relative to the generated config location.
232
-
233
- ### 4. Generated Output
234
-
235
- The CLI writes:
210
+ **Windows (PowerShell):**
236
211
 
237
- - **Config file:** `LT_Test/<TestName>.conf.js` – Ready to run against LambdaTest (hostname, path, services, and capabilities set).
238
- - **Package script:** In `LT_Test/package.json`, a script like `test:<TestName>` is added.
212
+ ```powershell
213
+ $env:LT_USERNAME = "your_username"
214
+ $env:LT_ACCESS_KEY = "your_access_key"
215
+ ```
239
216
 
240
- ### 5. Run the Generated Config
217
+ 4. **Generate a config and run**
241
218
 
242
219
  ```bash
243
- cd LT_Test
244
- npm install # if needed
245
- npm run test:<TestName>
246
- # or
247
- npx wdio <TestName>.conf.js
220
+ npx wdio-lt generate
221
+ cd LT_Test && npm run test:<TestName>
248
222
  ```
249
223
 
250
- To follow the same code design as the sample repo, set the **spec file path** during `wdio-lt generate` to your existing `specs/` folder, e.g. `../specs/android-test.js`, so the generated config reuses your shared specs.
224
+ Or run the existing samples: see [Steps to Run the Sample Project](#steps-to-run-the-sample-project).
251
225
 
252
226
  ---
253
227
 
254
- ## CLI Commands
255
-
256
- | Command | Description |
257
- |--------|-------------|
258
- | `wdio-lt setup [path]` | Inject LambdaTest service into existing WDIO config files |
259
- | `wdio-lt generate` | Interactively generate a new WDIO config for LambdaTest |
260
- | `wdio-lt init` | Alias for `generate` |
261
- | `wdio-lt --help` | Show help |
262
- | `wdio-lt --version` | Show version |
263
-
264
- ### Examples
265
-
266
- ```bash
267
- # Setup – inject service into all .conf.js files in a directory
268
- wdio-lt setup ./android-sample
269
-
270
- # Setup – interactive mode (prompts for directory)
271
- wdio-lt setup
272
-
273
- # Generate – create a new config interactively
274
- wdio-lt generate
275
- ```
228
+ ## Steps to Run the Sample Project
276
229
 
277
- ### Running the CLI
230
+ After cloning [LT-appium-nodejs-webdriverio](https://github.com/LambdaTest/LT-appium-nodejs-webdriverio) and setting credentials:
278
231
 
279
- **With Node.js** (default; no extra install):
232
+ ### Android
280
233
 
281
234
  ```bash
282
- npx wdio-lt setup ./android-sample
283
- npx wdio-lt generate
235
+ cd android-sample
236
+ npm install
237
+ npm run SingleAndroidApp
238
+ # or: npm run parallel
284
239
  ```
285
240
 
286
- **With Bun** (optional; faster):
241
+ ### iOS
287
242
 
288
243
  ```bash
289
- curl -fsSL https://bun.sh/install | bash # Install Bun
290
- bunx wdio-lt setup ./android-sample
291
- bunx wdio-lt generate
244
+ cd ios-sample
245
+ npm install
246
+ npm run single
247
+ # or: npm run parallel
292
248
  ```
293
249
 
294
- ### Legacy Commands (backward compatible)
295
-
296
- ```bash
297
- wdio-lambdatest-setup ./android-sample
298
- wdio-lambdatest-generator
299
- ```
250
+ Ensure configs point to the correct spec paths (e.g. `../specs/android-test.js`) and include the LambdaTest service. Results appear in the terminal and on the [LambdaTest App Automation Dashboard](https://appautomation.lambdatest.com/).
300
251
 
301
252
  ---
302
253
 
303
- ## Automated Setup
254
+ ## Specs Folder & Code Design
304
255
 
305
- The `setup` command updates existing WebdriverIO config files (`*.conf.js`) to use this SDK:
256
+ The sample repo uses a shared **`specs/`** folder at the root. Use the same layout so generated configs can reuse specs.
306
257
 
307
- ```bash
308
- wdio-lt setup ./path/to/your/project
309
- ```
258
+ Recommended layout:
310
259
 
311
- It will:
260
+ ```
261
+ LT-appium-nodejs-webdriverio/
262
+ ├── android-sample/
263
+ ├── ios-sample/
264
+ ├── specs/ # Shared test specs
265
+ │ ├── android-test.js
266
+ │ ├── ios-test.js
267
+ │ └── ...
268
+ ├── LT_Test/ # Generated configs (from wdio-lt generate)
269
+ └── package.json
270
+ ```
312
271
 
313
- - Scan for `.conf.js` files recursively.
314
- - Inject the service configuration.
315
- - Set `logLevel` to `error` for cleaner output.
316
- - Comment out hardcoded credentials so the SDK can use env vars or service options.
272
+ - Use paths like `../specs/android-test.js` in configs under `LT_Test` or sample dirs.
273
+ - When running `wdio-lt generate`, set the spec path to e.g. `../specs/android-test.js` so the generated config uses the shared specs.
317
274
 
318
275
  ---
319
276
 
320
- ## Config Generator
277
+ ## Setup Command
321
278
 
322
- The `generate` command creates a new WDIO config with interactive prompts:
279
+ Use the CLI to add the LambdaTest service to existing WDIO configs:
323
280
 
324
281
  ```bash
325
- wdio-lt generate
282
+ wdio-lt setup ./path/to/your/project
326
283
  ```
327
284
 
328
- Features:
285
+ This will:
329
286
 
330
- - Test name with validation
331
- - LambdaTest username and access key (secure input)
332
- - **Multi-select:** Test type(s), Device type(s), Platform(s), What to test (App / Website)
333
- - App ID(s) per platform when testing native apps
334
- - Parallel threads and spec file path with smart resolution
335
-
336
- Generated configs are saved to `./LT_Test/<testName>.conf.js`.
287
+ - Find `*.conf.js` files recursively.
288
+ - Add the service configuration.
289
+ - Set `logLevel` to `error`.
290
+ - Comment out hardcoded credentials so env vars or service options are used.
337
291
 
338
292
  ---
339
293
 
340
294
  ## Manual Configuration
341
295
 
342
- Add the service to your `wdio.conf.js`:
296
+ If you prefer not to use the CLI, add the service to your `wdio.conf.js`:
343
297
 
344
298
  ```javascript
345
299
  const path = require('path');
346
300
 
347
301
  exports.config = {
348
- // user / key can be omitted if using service options or env
349
302
  logLevel: 'error',
350
-
351
303
  services: [
352
- [path.join(__dirname, 'node_modules/wdio-lambdatest-service'), {
304
+ [path.join(__dirname, 'node_modules/wdio-lambdatest-service-sdk'), {
353
305
  user: process.env.LT_USERNAME,
354
306
  key: process.env.LT_ACCESS_KEY
355
307
  }]
@@ -358,47 +310,53 @@ exports.config = {
358
310
  };
359
311
  ```
360
312
 
361
- If using the SDK from a local path (e.g. repo root):
313
+ Prefer using **`wdio-lt generate`** or **`wdio-lt setup`** so paths and specs are set correctly.
362
314
 
363
- ```javascript
364
- services: [
365
- [path.join(__dirname, '../wdio-lambdatest-service'), {
366
- user: process.env.LT_USERNAME,
367
- key: process.env.LT_ACCESS_KEY
368
- }]
369
- ],
370
- ```
315
+ ---
316
+
317
+ ## Troubleshooting
318
+
319
+ - **"Cannot read properties of null (reading 'launcher')"** or **"No specs found"**
320
+ Regenerate or fix the config with the CLI so the service path and spec paths are correct:
321
+ - Run `npx wdio-lt generate` and use the new config, or
322
+ - Run `npx wdio-lt setup ./path/to/project` to re-inject the service.
323
+ - Ensure **specs** in the config point to existing files (e.g. `../specs/android-test.js` from `LT_Test`).
324
+
325
+ - **ERESOLVE / peer dependency errors**
326
+ Install with `--legacy-peer-deps` or `--force` (see [Installation](#installation)).
327
+
328
+ - **Wrong or missing spec path**
329
+ When generating, use a path relative to the config file (e.g. `../specs/android-test.js`). Re-run `wdio-lt generate` if needed.
371
330
 
372
331
  ---
373
332
 
374
333
  ## Development
375
334
 
376
- This package provides a **Service** (worker) and a **Launcher** (main process) for WebdriverIO.
335
+ This package ships a **CLI** (`wdio-lt`) and a WebdriverIO service/launcher used by generated and setup configs.
377
336
 
378
- ### Project Structure
337
+ ### Project structure
379
338
 
380
339
  ```
381
340
  wdio-lambdatest-service/
382
341
  ├── bin/
383
- │ ├── cli.js # Main CLI entry (Commander)
384
- │ ├── setup.js # Setup command wrapper
385
- │ └── generate-config.js # Generate command wrapper
386
- ├── lib/
387
- └── cli/
388
- ├── style.js # Chalk style utilities
389
- ├── setup.js # Setup logic
390
- │ └── generate.js # Generate logic (Inquirer prompts)
342
+ │ ├── cli.js
343
+ │ ├── setup.js
344
+ │ └── generate-config.js
345
+ ├── lib/cli/
346
+ ├── setup.js
347
+ ├── generate.js
348
+ └── style.js
391
349
  ├── src/
392
- │ ├── launcher.js # WDIO Launcher
393
- │ └── service.js # WDIO Service
394
- ├── index.js # Main entry point
350
+ │ ├── launcher.js
351
+ │ └── service.js
352
+ ├── index.js
395
353
  └── package.json
396
354
  ```
397
355
 
398
356
  ### Requirements
399
357
 
400
- - **Node.js**: >= 18.0.0 (required for npm install and default CLI run)
401
- - **Bun**: >= 1.0.0 (optional; use `bun add` / `bunx wdio-lt` for faster install and run)
358
+ - **Node.js**: >= 18.0.0
359
+ - **Bun**: >= 1.0.0 (optional)
402
360
 
403
361
  ---
404
362
 
package/bin/cli.js CHANGED
@@ -1,56 +1,42 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * LambdaTest WDIO CLI - Unified command-line interface.
3
+ * TestMU WDIO CLI - Unified command-line interface.
4
4
  * Powered by Commander, Chalk, and Inquirer.
5
5
  * Runs with Node.js or Bun.
6
6
  */
7
7
  const { Command } = require('commander');
8
8
  const chalk = require('chalk');
9
+ const { welcomeBanner, infoBox } = require('../lib/cli/style');
9
10
  const { runSetup } = require('../lib/cli/setup');
10
11
  const { runGenerate } = require('../lib/cli/generate');
11
12
  const pkg = require('../package.json');
12
13
 
13
14
  const program = new Command();
14
15
 
15
- // ASCII Art Logo
16
- const logo = `
17
- ${chalk.cyan('╔═══════════════════════════════════════════════════════════╗')}
18
- ${chalk.cyan('║')} ${chalk.bold.white('🚀 LambdaTest WDIO CLI')} ${chalk.cyan('║')}
19
- ${chalk.cyan('║')} ${chalk.dim('Fast, powerful WebdriverIO configuration tool')} ${chalk.cyan('║')}
20
- ${chalk.cyan('╚═══════════════════════════════════════════════════════════╝')}
21
- `;
22
-
23
16
  program
24
17
  .name('wdio-lt')
25
- .description(chalk.dim('LambdaTest WebdriverIO CLI - Setup and configure WDIO projects'))
18
+ .description(chalk.dim('TestMU WebdriverIO CLI - Setup and configure WDIO projects for LambdaTest'))
26
19
  .version(pkg.version, '-v, --version', 'Display version number')
27
20
  .helpOption('-h, --help', 'Display help for command')
28
- .addHelpText('before', logo)
21
+ .addHelpText('before', welcomeBanner())
29
22
  .addHelpText('after', `
30
- ${chalk.bold('Examples:')}
23
+
24
+ ${chalk.bold('Examples')}
25
+ ${chalk.green('$')} wdio-lt generate ${chalk.dim('# Create new config (recommended)')}
26
+ ${chalk.green('$')} wdio-lt init ${chalk.dim('# Alias for generate')}
31
27
  ${chalk.green('$')} wdio-lt setup ./android-sample ${chalk.dim('# Inject service into configs')}
32
28
  ${chalk.green('$')} wdio-lt setup ${chalk.dim('# Interactive mode')}
33
- ${chalk.green('$')} wdio-lt generate ${chalk.dim('# Create new config')}
34
- ${chalk.green('$')} wdio-lt init ${chalk.dim('# Alias for generate')}
35
29
 
36
- ${chalk.bold('Documentation:')}
37
- ${chalk.cyan('https://github.com/LambdaTest')}
38
- `);
30
+ ${infoBox('CLI preview', [
31
+ 'npx wdio-lt → show this help',
32
+ 'npx wdio-lt generate → interactive config generator',
33
+ 'npx wdio-lt setup [path] → add LambdaTest to existing configs'
34
+ ])}
39
35
 
40
- // Setup command
41
- program
42
- .command('setup [path]')
43
- .description('Inject LambdaTest service into existing WDIO config files')
44
- .action(async (targetPath) => {
45
- try {
46
- await runSetup(targetPath);
47
- } catch (e) {
48
- console.error(chalk.red.bold('\n✖ Error:'), e.message);
49
- process.exit(1);
50
- }
51
- });
36
+ ${chalk.dim('Documentation:')} ${chalk.cyan('https://github.com/LambdaTest')}
37
+ `);
52
38
 
53
- // Generate command
39
+ // Generate command (first / primary)
54
40
  program
55
41
  .command('generate')
56
42
  .alias('gen')
@@ -77,6 +63,19 @@ program
77
63
  }
78
64
  });
79
65
 
66
+ // Setup command
67
+ program
68
+ .command('setup [path]')
69
+ .description('Inject LambdaTest service into existing WDIO config files')
70
+ .action(async (targetPath) => {
71
+ try {
72
+ await runSetup(targetPath);
73
+ } catch (e) {
74
+ console.error(chalk.red.bold('\n✖ Error:'), e.message);
75
+ process.exit(1);
76
+ }
77
+ });
78
+
80
79
  // Parse arguments
81
80
  program.parse();
82
81
 
package/index.js CHANGED
@@ -1,17 +1,17 @@
1
1
  /**
2
2
  * WDIO LambdaTest service entry point.
3
- * Exposes the service class and launcher for WebdriverIO.
4
- * Export shape supports both CommonJS and WDIO plugin resolution (default + launcher).
3
+ * Export shape: object with default (worker service) and launcher (main process)
4
+ * so @wdio/utils initialisePlugin never sees null when reading .launcher or .default.
5
5
  */
6
6
  const LambdaTestService = require('./src/service');
7
7
  const LambdaTestLauncher = require('./src/launcher');
8
8
 
9
- // Primary export: the worker service class (used by WDIO in worker process)
10
9
  const Service = LambdaTestService;
11
-
12
- // Attach launcher so WDIO can read plugin.launcher (main process)
13
10
  Service.launcher = LambdaTestLauncher;
14
- // ESM interop: some loaders expect plugin.default
15
11
  Service.default = Service;
16
12
 
17
- module.exports = Service;
13
+ // Export object so require() never returns null and plugin.launcher / plugin.default always exist
14
+ module.exports = {
15
+ default: Service,
16
+ launcher: LambdaTestLauncher
17
+ };
@@ -6,6 +6,9 @@ const path = require('path');
6
6
  const chalk = require('chalk');
7
7
  const inquirer = require('inquirer');
8
8
 
9
+ // Support both CJS and ESM inquirer (default.prompt vs prompt)
10
+ const prompt = (inquirer.default && inquirer.default.prompt) ? inquirer.default.prompt.bind(inquirer.default) : inquirer.prompt;
11
+
9
12
  /** Safe filename: non-empty, no path separators or reserved chars. */
10
13
  function toSafeFilename(value, fallback) {
11
14
  if (!value || typeof value !== 'string') return fallback;
@@ -14,16 +17,17 @@ function toSafeFilename(value, fallback) {
14
17
  }
15
18
 
16
19
  /**
17
- * Find wdio binary path relative to outputDir. Checks root node_modules then android-sample.
20
+ * Resolve wdio run command for the generated package.json script.
21
+ * Prefer local .bin/wdio so runs work offline; fallback to npx wdio when not found (e.g. app has no @wdio/cli yet).
18
22
  * @param {string} outDir - Absolute path to LT_Test (output dir)
19
- * @returns {string} Relative path to wdio binary
23
+ * @returns {string} Command string for the test script (e.g. "../node_modules/.bin/wdio" or "npx wdio")
20
24
  */
21
- function findWdioBinRelative(outDir) {
25
+ function getWdioRunCommand(outDir) {
22
26
  const rootWdio = path.resolve(outDir, '../node_modules/.bin/wdio');
23
27
  const androidSampleWdio = path.resolve(outDir, '../android-sample/node_modules/.bin/wdio');
24
28
  if (fs.existsSync(rootWdio)) return '../node_modules/.bin/wdio';
25
29
  if (fs.existsSync(androidSampleWdio)) return '../android-sample/node_modules/.bin/wdio';
26
- return '../node_modules/.bin/wdio';
30
+ return 'npx wdio';
27
31
  }
28
32
 
29
33
  /**
@@ -164,11 +168,12 @@ function buildCapabilitiesMulti(config) {
164
168
  }
165
169
 
166
170
  /**
167
- * Resolve LambdaTest service path: try package name first (npm install), then sibling (reference repo).
168
- * Reference repo layout: LT_Test/ (configs) and wdio-lambdatest-service/ as siblings.
171
+ * Resolve LambdaTest service: try wdio-lambdatest-service-sdk then wdio-lambdatest-service (npm), then sibling path.
172
+ * Package can be installed as wdio-lambdatest-service-sdk or wdio-lambdatest-service.
169
173
  */
170
174
  function getServicePathSnippet() {
171
175
  return `(function () {
176
+ try { return require.resolve('wdio-lambdatest-service-sdk'); } catch (e) {}
172
177
  try { return require.resolve('wdio-lambdatest-service'); } catch (e) {}
173
178
  return path.join(__dirname, '../wdio-lambdatest-service');
174
179
  })()`;
@@ -180,7 +185,11 @@ function getServicePathSnippet() {
180
185
  */
181
186
  function buildConfigTemplate(config, commonCaps, capabilities) {
182
187
  const servicePathExpr = getServicePathSnippet();
183
- const safeSpecPath = config.specPath.replace(/\\/g, '/');
188
+ // Normalize: relative path only; no absolute paths or quotes (WDIO resolves from config dir)
189
+ let safeSpecPath = (config.specPath || '../specs/android-test.js').replace(/\\/g, '/').trim();
190
+ if (path.isAbsolute(safeSpecPath) || !safeSpecPath || /['"]/.test(safeSpecPath)) {
191
+ safeSpecPath = '../specs/android-test.js';
192
+ }
184
193
  const mergeSnippet = capabilities.length > 0
185
194
  ? `
186
195
  // Merge commonCapabilities into each capability
@@ -263,7 +272,7 @@ async function runGenerate() {
263
272
  console.log(chalk.dim('─'.repeat(40)));
264
273
  console.log();
265
274
 
266
- const basicAnswers = await inquirer.default.prompt([
275
+ const basicAnswers = await prompt([
267
276
  {
268
277
  type: 'input',
269
278
  name: 'testName',
@@ -295,7 +304,7 @@ async function runGenerate() {
295
304
  console.log(chalk.dim('─'.repeat(40)));
296
305
  console.log();
297
306
 
298
- const credAnswers = await inquirer.default.prompt([
307
+ const credAnswers = await prompt([
299
308
  {
300
309
  type: 'input',
301
310
  name: 'username',
@@ -320,19 +329,19 @@ async function runGenerate() {
320
329
  console.log();
321
330
  console.log(chalk.dim('─'.repeat(40)));
322
331
  console.log(chalk.cyan.bold(' ⚙️ Test Configuration'));
323
- console.log(chalk.dim('─' .repeat(40)));
332
+ console.log(chalk.dim('─'.repeat(40)));
324
333
  console.log(chalk.dim(' (Use space to select, enter to confirm)'));
325
334
  console.log();
326
335
 
327
336
  // Step 1: Test Type (Multi-select)
328
- const testTypeAnswer = await inquirer.default.prompt([
337
+ const testTypeAnswer = await prompt([
329
338
  {
330
339
  type: 'checkbox',
331
340
  name: 'testTypes',
332
341
  message: 'Test type(s):',
333
342
  choices: [
334
- { name: '📱 Mobile Testing ', value: 'app', checked: true },
335
- { name: '🌐 Browser Testing (Desktop)', value: 'browser' }
343
+ { name: ' 📱 Mobile Testing ', value: 'app', checked: true },
344
+ { name: ' 🌐 Browser Testing (Desktop)', value: 'browser' }
336
345
  ],
337
346
  validate: (input) => input.length > 0 || 'Please select at least one test type'
338
347
  }
@@ -348,14 +357,14 @@ async function runGenerate() {
348
357
  console.log();
349
358
 
350
359
  // Step 2: Device Type (Multi-select)
351
- const deviceAnswer = await inquirer.default.prompt([
360
+ const deviceAnswer = await prompt([
352
361
  {
353
362
  type: 'checkbox',
354
363
  name: 'deviceTypes',
355
364
  message: 'Device type(s):',
356
365
  choices: [
357
- { name: '📲 Mobile Device', value: 'real', checked: true },
358
- { name: '💻 Website (Desktop)', value: 'virtual' }
366
+ { name: ' 📲 Mobile Device (Real)', value: 'real', checked: true },
367
+ { name: ' 💻 Mobile Device (Virtual)', value: 'virtual' }
359
368
  ],
360
369
  validate: (input) => input.length > 0 || 'Please select at least one device type'
361
370
  }
@@ -363,14 +372,14 @@ async function runGenerate() {
363
372
  config.deviceTypes = deviceAnswer.deviceTypes;
364
373
 
365
374
  // Step 3: Platform (Multi-select)
366
- const platformAnswer = await inquirer.default.prompt([
375
+ const platformAnswer = await prompt([
367
376
  {
368
377
  type: 'checkbox',
369
378
  name: 'platforms',
370
379
  message: 'Platform(s):',
371
380
  choices: [
372
- { name: '🤖 Android', value: 'android', checked: true },
373
- { name: '🍎 iOS', value: 'ios' }
381
+ { name: ' 🤖 Android', value: 'android', checked: true },
382
+ { name: ' 🍎 iOS', value: 'ios' }
374
383
  ],
375
384
  validate: (input) => input.length > 0 || 'Please select at least one platform'
376
385
  }
@@ -378,14 +387,14 @@ async function runGenerate() {
378
387
  config.platforms = platformAnswer.platforms;
379
388
 
380
389
  // Step 4: What to test (Multi-select)
381
- const testingTypeAnswer = await inquirer.default.prompt([
390
+ const testingTypeAnswer = await prompt([
382
391
  {
383
392
  type: 'checkbox',
384
393
  name: 'testingTypes',
385
394
  message: 'What do you want to test?',
386
395
  choices: [
387
- { name: '📦 Application (Native App)', value: 'app', checked: true },
388
- { name: '🌐 Website (Mobile Browser)', value: 'website' }
396
+ { name: ' 📦 Application (Native App)', value: 'app', checked: true },
397
+ { name: ' 🌐 Website (Mobile Browser)', value: 'website' }
389
398
  ],
390
399
  validate: (input) => input.length > 0 || 'Please select at least one testing type'
391
400
  }
@@ -405,7 +414,7 @@ async function runGenerate() {
405
414
  const platformLabel = platform === 'ios' ? 'iOS' : 'Android';
406
415
  const defaultAppId = getDefaultAppId(platform);
407
416
 
408
- const appIdAnswer = await inquirer.default.prompt([
417
+ const appIdAnswer = await prompt([
409
418
  {
410
419
  type: 'input',
411
420
  name: 'appId',
@@ -426,7 +435,7 @@ async function runGenerate() {
426
435
  console.log(chalk.dim('─'.repeat(40)));
427
436
  console.log();
428
437
 
429
- const parallelAnswer = await inquirer.default.prompt([
438
+ const parallelAnswer = await prompt([
430
439
  {
431
440
  type: 'number',
432
441
  name: 'parallel',
@@ -442,7 +451,7 @@ async function runGenerate() {
442
451
 
443
452
  // Spec file path (reference repo: LT_Test and specs/ are siblings, so ../specs/ from LT_Test)
444
453
  const defaultSpecPath = '../specs/android-test.js';
445
- const specAnswer = await inquirer.default.prompt([
454
+ const specAnswer = await prompt([
446
455
  {
447
456
  type: 'input',
448
457
  name: 'specPath',
@@ -496,8 +505,8 @@ async function runGenerate() {
496
505
  pkg.scripts = {};
497
506
  }
498
507
 
499
- const wdioBin = findWdioBinRelative(outputDir);
500
- pkg.scripts[`test:${config.testName}`] = `${wdioBin} ${config.filename}`;
508
+ const wdioCmd = getWdioRunCommand(outputDir);
509
+ pkg.scripts[`test:${config.testName}`] = `${wdioCmd} ${config.filename}`;
501
510
  fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2));
502
511
 
503
512
  // Success output
package/lib/cli/style.js CHANGED
@@ -4,6 +4,82 @@
4
4
  */
5
5
  const chalk = require('chalk');
6
6
 
7
+ // ASCII art logo (block style) for welcome banner – compact version
8
+ const ASCII_LOGO = [
9
+ '██████████████ ██████████████',
10
+ '██████████████ ██████████████',
11
+ '██████████████ ██████████████',
12
+ '██████████████ ██████████████',
13
+ ' █████████████ ██████████████',
14
+ ' ████████████ ██████████████',
15
+ ' ██████████ ██████████████',
16
+ ' ████████ ██████████████',
17
+ '███████████████████████████████████████████',
18
+ '██████████████ ████████████████ ',
19
+ '██████████████ ███████████████ ',
20
+ '██████████████ '
21
+ ];
22
+
23
+ const BOX_WIDTH = 56;
24
+
25
+ /**
26
+ * Build the welcome banner with box and ASCII art.
27
+ * @returns {string} Styled banner for CLI start/help
28
+ */
29
+ function welcomeBanner() {
30
+ const c = chalk.cyan;
31
+ const bold = chalk.bold;
32
+ const dim = chalk.dim;
33
+ const w = BOX_WIDTH;
34
+ const top = c('╭') + c('─'.repeat(w - 2)) + c('╮');
35
+ const bottom = c('╰') + c('─'.repeat(w - 2)) + c('╯');
36
+ const side = c('│');
37
+ const pad = (s, len) => s + ' '.repeat(Math.max(0, len - s.length));
38
+ const center = (s, totalLen) => {
39
+ const n = Math.max(0, Math.floor((totalLen - s.length) / 2));
40
+ return ' '.repeat(n) + s + ' '.repeat(totalLen - n - s.length);
41
+ };
42
+ const title = 'Welcome to TestMU WDIO CLI';
43
+ const titleLine = side + ' ' + bold.white(center(title, w - 4)) + ' ' + side;
44
+ const tagline = 'WebdriverIO configuration tool for LambdaTest';
45
+ const tagLine = side + ' ' + dim(center(tagline, w - 4)) + ' ' + side;
46
+ const logoLines = ASCII_LOGO.map((line) => side + ' ' + c(pad(line.slice(0, w - 4), w - 4)) + ' ' + side);
47
+ const emptyLine = side + ' '.repeat(w - 2) + side;
48
+ return [
49
+ '',
50
+ top,
51
+ emptyLine,
52
+ titleLine,
53
+ emptyLine,
54
+ ...logoLines,
55
+ emptyLine,
56
+ tagLine,
57
+ emptyLine,
58
+ bottom,
59
+ ''
60
+ ].join('\n');
61
+ }
62
+
63
+ /**
64
+ * Build a compact box for CLI preview / tips (e.g. help footer).
65
+ * @param {string} title - Box title
66
+ * @param {string[]} lines - Content lines (plain text; chalk applied inside)
67
+ * @returns {string}
68
+ */
69
+ function infoBox(title, lines) {
70
+ const cyan = chalk.cyan;
71
+ const dim = chalk.dim;
72
+ const bold = chalk.bold;
73
+ const contentWidth = Math.max(title.length, ...lines.map((l) => l.length), 40);
74
+ const w = contentWidth + 4;
75
+ const top = cyan('╭') + cyan('─'.repeat(w - 2)) + cyan('╮');
76
+ const bottom = cyan('╰') + cyan('─'.repeat(w - 2)) + cyan('╯');
77
+ const side = cyan('│');
78
+ const titleLine = side + ' ' + bold(title) + ' '.repeat(w - 3 - title.length) + side;
79
+ const content = lines.map((l) => side + ' ' + dim(l + ' '.repeat(contentWidth - l.length)) + ' ' + side);
80
+ return [top, titleLine, ...content, bottom].join('\n');
81
+ }
82
+
7
83
  const style = {
8
84
  // Colors
9
85
  reset: chalk.reset,
@@ -51,7 +127,12 @@ const style = {
51
127
  },
52
128
 
53
129
  // Banner
54
- banner: (text) => chalk.cyan.bold(`\n--- ${text} ---\n`)
130
+ banner: (text) => chalk.cyan.bold(`\n--- ${text} ---\n`),
131
+
132
+ // Welcome banner with ASCII art and box
133
+ welcomeBanner,
134
+ // Info box for tips / preview
135
+ infoBox
55
136
  };
56
137
 
57
138
  module.exports = style;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wdio-lambdatest-service-sdk",
3
- "version": "5.1.5",
3
+ "version": "5.1.7",
4
4
  "description": "WebdriverIO service and CLI for LambdaTest Appium & browser automation",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -43,8 +43,8 @@
43
43
  "webdriverio": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
44
44
  },
45
45
  "peerDependenciesMeta": {
46
- "@wdio/cli": { "optional": false },
47
- "webdriverio": { "optional": false }
46
+ "@wdio/cli": { "optional": true },
47
+ "webdriverio": { "optional": true }
48
48
  },
49
49
  "engines": {
50
50
  "node": ">=18.0.0",