codeceptjs 4.0.0-rc.20 → 4.0.0-rc.22

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/docs/parallel.md CHANGED
@@ -5,581 +5,183 @@ title: Parallel Execution
5
5
 
6
6
  # Parallel Execution
7
7
 
8
- CodeceptJS has multiple approaches for running tests in parallel:
8
+ Two built-in ways to run tests in parallel:
9
9
 
10
- - **Test Sharding** - distributes tests across multiple machines for CI matrix execution
11
- - `run-workers` - which spawns [NodeJS Worker](https://nodejs.org/api/worker_threads.html) in a thread. Tests are split by scenarios, scenarios are mixed between groups, each worker runs tests from its own group.
12
- - `run-multiple` - which spawns a subprocess with CodeceptJS. Tests are split by files and configured in `codecept.conf.js`.
10
+ - **`run-workers`** split tests across worker threads on one runner.
11
+ - **`--shard`** split test files across CI machines in a matrix build.
13
12
 
14
- Workers are faster and simpler to start, while `run-multiple` requires additional configuration and can be used to run tests in different browsers at once.
13
+ For anything more specific your own grouping, a config per group, several browsers at once drive the `Workers` API from a script (see [Custom parallelization](#custom-parallelization)).
15
14
 
16
- ## Test Sharding for CI Matrix
15
+ ## Workers
17
16
 
18
- Test sharding allows you to split your test suite across multiple machines or CI workers without manual configuration. This is particularly useful for CI/CD pipelines where you want to run tests in parallel across different machines.
19
-
20
- Use the `--shard` option with the `run` command to execute only a portion of your tests:
21
-
22
- ```bash
23
- # Run the first quarter of tests
24
- npx codeceptjs run --shard 1/4
25
-
26
- # Run the second quarter of tests
27
- npx codeceptjs run --shard 2/4
28
-
29
- # Run the third quarter of tests
30
- npx codeceptjs run --shard 3/4
31
-
32
- # Run the fourth quarter of tests
33
- npx codeceptjs run --shard 4/4
34
- ```
35
-
36
- ### CI Matrix Example
37
-
38
- Here's how you can use test sharding with GitHub Actions matrix strategy:
39
-
40
- ```yaml
41
- name: Tests
42
- on: [push, pull_request]
43
-
44
- jobs:
45
- test:
46
- runs-on: ubuntu-latest
47
- strategy:
48
- matrix:
49
- shard: [1/4, 2/4, 3/4, 4/4]
50
-
51
- steps:
52
- - uses: actions/checkout@v2
53
- - uses: actions/setup-node@v2
54
- - run: npm install
55
- - run: npx codeceptjs run --shard ${{ matrix.shard }}
56
- ```
57
-
58
- This approach ensures:
59
-
60
- - Each CI job runs only its assigned portion of tests
61
- - Tests are distributed evenly across shards
62
- - No manual configuration or maintenance of test lists
63
- - Automatic load balancing as you add or remove tests
64
-
65
- ### Shard Distribution
66
-
67
- Tests are distributed evenly across shards using a round-robin approach:
68
-
69
- - If you have 100 tests and 4 shards, each shard runs approximately 25 tests
70
- - The first shard gets tests 1-25, second gets 26-50, third gets 51-75, fourth gets 76-100
71
- - If tests don't divide evenly, earlier shards may get one extra test
72
-
73
- ## Parallel Execution by Workers
74
-
75
- It is easy to run tests in parallel if you have a lots of tests and free CPU cores. Just execute your tests using `run-workers` command specifying the number of workers to spawn:
76
-
77
- ```
78
- npx codeceptjs run-workers 2
79
- ```
80
-
81
- > ℹ Workers require NodeJS >= 11.7
82
-
83
- This command is similar to `run`, however, steps output can't be shown in workers mode, as it is impossible to synchronize steps output from different processes.
84
-
85
- Each worker spins an instance of CodeceptJS, executes a group of tests, and sends back report to the main process.
86
-
87
- By default, the tests are assigned one by one to the available workers this may lead to multiple execution of `BeforeSuite()`. Use the option `--suites` to assign the suites one by one to the workers.
17
+ `run-workers <N>` spawns `N` [worker threads](https://nodejs.org/api/worker_threads.html), each an independent CodeceptJS instance running a slice of the suite, and merges the results:
88
18
 
89
19
  ```sh
90
- npx codeceptjs run-workers --suites 2
20
+ npx codeceptjs run-workers 4
91
21
  ```
92
22
 
93
- ### Test Distribution Strategies
23
+ Steps are not streamed to the console in this mode — output from separate threads can't be interleaved cleanly. While workers run, CodeceptJS sets `process.env.RUNS_WITH_WORKERS=true`, so plugins and helpers can branch on it. All `run` options work here too: `--grep "@smoke"`, `-c codecept.conf.js`, `--debug`, and the rest.
94
24
 
95
- CodeceptJS supports three different strategies for distributing tests across workers:
25
+ ### Distribution strategies
96
26
 
97
- #### Default Strategy (`--by test`)
27
+ `--by` controls how tests spread across workers:
98
28
 
99
- Tests are pre-assigned to workers at startup, distributing them evenly across all workers. Each worker gets a predetermined set of tests to run.
29
+ | `--by` | How tests are assigned | Use when |
30
+ | --- | --- | --- |
31
+ | `test` (default) | each test pinned to a worker up front | tests take roughly equal time |
32
+ | `suite` | each suite pinned to a worker; its tests stay together | suites share a `BeforeSuite` you don't want repeated |
33
+ | `pool` | workers pull the next test from a shared queue as they free up | test durations vary — best load balancing |
100
34
 
101
35
  ```sh
102
- npx codeceptjs run-workers 3 --by test
103
- ```
104
-
105
- #### Suite Strategy (`--by suite`)
106
-
107
- Test suites are pre-assigned to workers, with all tests in a suite running on the same worker. This ensures better test isolation but may lead to uneven load distribution.
108
-
109
- ```sh
110
- npx codeceptjs run-workers 3 --by suite
111
- ```
112
-
113
- #### Pool Strategy (`--by pool`) - **Recommended for optimal performance**
114
-
115
- Tests are maintained in a shared pool and distributed dynamically to workers as they become available. This provides the best load balancing and resource utilization.
116
-
117
- ```sh
118
- npx codeceptjs run-workers 3 --by pool
119
- ```
120
-
121
- ## Dynamic Test Pooling Mode
122
-
123
- The pool mode enables dynamic test distribution for improved worker load balancing. Instead of pre-assigning tests to workers at startup, tests are stored in a shared pool and distributed on-demand as workers become available.
124
-
125
- ### Benefits of Pool Mode
126
-
127
- - **Better load balancing**: Workers never sit idle while others are still running long tests
128
- - **Improved performance**: Especially beneficial when tests have varying execution times
129
- - **Optimal resource utilization**: All CPU cores stay busy until the entire test suite is complete
130
- - **Automatic scaling**: Workers continuously process tests until the pool is empty
131
-
132
- ### When to Use Pool Mode
133
-
134
- Pool mode is particularly effective in these scenarios:
135
-
136
- - **Uneven test execution times**: When some tests take significantly longer than others
137
- - **Large test suites**: With hundreds or thousands of tests where load balancing matters
138
- - **Mixed test types**: When combining unit tests, integration tests, and end-to-end tests
139
- - **CI/CD pipelines**: For consistent and predictable test execution times
140
-
141
- ### Usage Examples
142
-
143
- ```bash
144
- # Basic pool mode with 4 workers
145
36
  npx codeceptjs run-workers 4 --by pool
146
-
147
- # Pool mode with grep filtering
148
- npx codeceptjs run-workers 3 --by pool --grep "@smoke"
149
-
150
- # Pool mode in debug mode
151
- npx codeceptjs run-workers 2 --by pool --debug
152
-
153
- # Pool mode with specific configuration
154
- npx codeceptjs run-workers 3 --by pool -c codecept.conf.js
155
37
  ```
156
38
 
157
- ### How Pool Mode Works
158
-
159
- 1. **Pool Creation**: All tests are collected into a shared pool of test identifiers
160
- 2. **Worker Initialization**: The specified number of workers are spawned
161
- 3. **Dynamic Assignment**: Workers request tests from the pool when they're ready
162
- 4. **Continuous Processing**: Each worker runs one test, then immediately requests the next
163
- 5. **Automatic Completion**: Workers exit when the pool is empty and no more tests remain
164
-
165
- ### Performance Comparison
166
-
167
- ```bash
168
- # Traditional mode - tests pre-assigned, some workers may finish early
169
- npx codeceptjs run-workers 3 --by test # ✓ Good for uniform test times
170
-
171
- # Suite mode - entire suites assigned to workers
172
- npx codeceptjs run-workers 3 --by suite # ✓ Good for test isolation
39
+ `--suites` is shorthand for `--by suite`.
173
40
 
174
- # Pool mode - tests distributed dynamically
175
- npx codeceptjs run-workers 3 --by pool # ✓ Best for mixed test execution times
176
- ```
41
+ ### Multiple browsers
177
42
 
178
- ## Test stats with Parallel Execution by Workers
43
+ Define browser profiles under `multiple` in `codecept.conf.js`:
179
44
 
180
45
  ```js
181
- import { event } from 'codeceptjs';
182
-
183
- export default function() {
46
+ multiple: {
47
+ default: { browsers: ['chrome', 'firefox'] },
48
+ }
49
+ ```
184
50
 
185
- event.dispatcher.on(event.workers.result, function (result) {
51
+ Then run a profile across workers — by name, or `all` for every profile:
186
52
 
187
- console.log(result);
53
+ ```sh
54
+ npx codeceptjs run-workers 3 default
55
+ npx codeceptjs run-workers 3 all
56
+ ```
188
57
 
189
- });
190
- }
58
+ (`run-multiple` runs the same profiles in separate subprocesses instead of threads — see `npx codeceptjs run-multiple --help`.)
191
59
 
192
- // in console log
193
- FAIL | 7 passed, 1 failed, 1 skipped // 2s
194
- {
195
- "tests": {
196
- "passed": [
197
- {
198
- "type": "test",
199
- "title": "Assert @C3",
200
- "body": "() => { }",
201
- "async": 0,
202
- "sync": true,
203
- "_timeout": 2000,
204
- "_slow": 75,
205
- "_retries": -1,
206
- "timedOut": false,
207
- "_currentRetry": 0,
208
- "pending": false,
209
- "opts": {},
210
- "tags": [
211
- "@C3"
212
- ],
213
- "uid": "xe4q1HdqpRrZG5dPe0JG+A",
214
- "workerIndex": 3,
215
- "retries": -1,
216
- "duration": 493,
217
- "err": null,
218
- "parent": {
219
- "title": "My",
220
- "ctx": {},
221
- "suites": [],
222
- "tests": [],
223
- "root": false,
224
- "pending": false,
225
- "_retries": -1,
226
- "_beforeEach": [],
227
- "_beforeAll": [],
228
- "_afterEach": [],
229
- "_afterAll": [],
230
- "_timeout": 2000,
231
- "_slow": 75,
232
- "_bail": false,
233
- "_onlyTests": [],
234
- "_onlySuites": [],
235
- "delayed": false
236
- },
237
- "steps": [
238
- {
239
- "actor": "I",
240
- "name": "amOnPage",
241
- "status": "success",
242
- "args": [
243
- "https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST"
244
- ],
245
- "startedAt": 1698760652610,
246
- "startTime": 1698760652611,
247
- "endTime": 1698760653098,
248
- "finishedAt": 1698760653098,
249
- "duration": 488
250
- },
251
- {
252
- "actor": "I",
253
- "name": "grabCurrentUrl",
254
- "status": "success",
255
- "args": [],
256
- "startedAt": 1698760653098,
257
- "startTime": 1698760653098,
258
- "endTime": 1698760653099,
259
- "finishedAt": 1698760653099,
260
- "duration": 1
261
- }
262
- ]
263
- }
264
- ],
265
- "failed": [],
266
- "skipped": []
267
- }
268
- }
269
- ```
60
+ ### Reading worker results
270
61
 
271
- CodeceptJS also exposes the env var `process.env.RUNS_WITH_WORKERS` when running tests with `run-workers` command so that you could handle the events better in your plugins/helpers
62
+ When all workers finish, the run fires `event.workers.result` with the merged result:
272
63
 
273
64
  ```js
274
65
  import { event } from 'codeceptjs'
275
66
 
276
67
  export default function () {
277
- // this event would trigger the `_publishResultsToTestrail` when running `run-workers` command
278
- event.dispatcher.on(event.workers.result, async () => {
279
- await _publishResultsToTestrail()
280
- })
281
-
282
- // this event would not trigger the `_publishResultsToTestrail` multiple times when running `run-workers` command
283
- event.dispatcher.on(event.all.result, async () => {
284
- // when running `run` command, this env var is undefined
285
- if (!process.env.RUNS_WITH_WORKERS) await _publishResultsToTestrail()
68
+ event.dispatcher.on(event.workers.result, result => {
69
+ console.log(result.hasFailed() ? 'FAILED' : 'PASSED', result.stats)
70
+ for (const test of result.tests) {
71
+ console.log(test.title, test.duration, 'ms', `worker ${test.workerIndex}`)
72
+ }
286
73
  })
287
74
  }
288
75
  ```
289
76
 
290
- ## Parallel Execution by Workers on Multiple Browsers
77
+ For end-of-run work like publishing to a test-management tool, listen on `event.workers.result` (fires once) rather than `event.all.result` (fires in every worker).
291
78
 
292
- To run tests in parallel across multiple browsers, modify your `codecept.conf.js` file to configure multiple browsers on which you want to run your tests and your tests will run across multiple browsers.
79
+ ## Sharding
293
80
 
294
- Start with modifying the `codecept.conf.js` file. Add multiple key inside the config which will be used to configure multiple profiles.
81
+ `--shard <index>/<total>` runs only a slice of your **test files**: the file list is cut into `total` even chunks and this run executes chunk `index`. It is built for CI matrices — one machine per shard, each running `run`:
295
82
 
296
- ```
297
- export const config = {
298
- helpers: {
299
- WebDriver: {
300
- url: 'http://localhost:3000',
301
- desiredCapabilties: {}
302
- }
303
- },
304
- multiple: {
305
- profile1: {
306
- browsers: [
307
- {
308
- browser: "firefox",
309
- desiredCapabilties: {
310
- // override capabilties related to firefox
311
- }
312
- },
313
- {
314
- browser: "chrome",
315
- desiredCapabilties: {
316
- // override capabilties related to chrome
317
- }
318
- }
319
- ]
320
- },
321
- profile2: {
322
- browsers: [
323
- {
324
- browser: "safari",
325
- desiredCapabilties: {
326
- // override capabilties related to safari
327
- }
328
- }
329
- ]
330
- }
331
- }
332
- };
333
- ```
334
-
335
- To trigger tests on all the profiles configured, you can use the following command:
336
-
337
- ```
338
- npx codeceptjs run-workers 3 all -c codecept.conf.js
83
+ ```sh
84
+ npx codeceptjs run --shard 1/4
85
+ npx codeceptjs run --shard 2/4
339
86
  ```
340
87
 
341
- This will run your tests across all browsers configured from profile1 & profile2 on 3 workers.
88
+ GitHub Actions:
342
89
 
343
- To trigger tests on specific profile, you can use the following command:
344
-
345
- ```
346
- npx codeceptjs run-workers 2 profile1 -c codecept.conf.js
90
+ ```yaml
91
+ jobs:
92
+ test:
93
+ runs-on: ubuntu-latest
94
+ strategy:
95
+ matrix:
96
+ shard: ['1/4', '2/4', '3/4', '4/4']
97
+ steps:
98
+ - uses: actions/checkout@v4
99
+ - uses: actions/setup-node@v4
100
+ with:
101
+ node-version: 20
102
+ - run: npm ci
103
+ - run: npx codeceptjs run --shard ${{ matrix.shard }}
347
104
  ```
348
105
 
349
- This will run your tests across 2 browsers from profile1 on 2 workers.
350
-
351
- ## Custom Parallel Execution
352
-
353
- To get a full control of parallelization create a custom execution script to match your needs.
354
- This way you can configure which tests are matched, how the groups are formed, and with which configuration each worker is executed.
355
-
356
- Start with creating file `bin/parallel.js`.
357
-
358
- On MacOS/Linux run following commands:
359
-
360
- ```
361
- mkdir bin
362
- touch bin/parallel.js
363
- chmod +x bin/parallel.js
364
- ```
106
+ Add or remove tests freely shards rebalance automatically.
365
107
 
366
- > Filename or directory can be customized. You are creating your own custom runner so take this paragraph as an example.
108
+ ## Custom parallelization
367
109
 
368
- Create a placeholder in file:
110
+ When the built-in commands aren't enough, build a runner with the `Workers` API: decide which tests go to which group, give each group its own config, and listen for results.
369
111
 
370
112
  ```js
371
113
  #!/usr/bin/env node
372
114
  import { Workers, event } from 'codeceptjs'
373
- // here will go magic
374
- ```
375
-
376
- Now let's see how to update this file for different parallelization modes:
377
-
378
- ### Example: Running tests in 2 browsers in 4 threads
379
115
 
380
- ```js
381
- const workerConfig = {
382
- testConfig: './test/data/sandbox/codecept.customworker.js',
383
- }
384
-
385
- // don't initialize workers in constructor
386
- const workers = new Workers(null, workerConfig)
387
- // split tests by suites in 2 groups
388
- const testGroups = workers.createGroupsOfSuites(2)
389
-
390
- const browsers = ['firefox', 'chrome']
391
-
392
- const configs = browsers.map(browser => {
393
- return {
394
- helpers: {
395
- WebDriver: { browser },
396
- },
397
- }
398
- })
116
+ const workers = new Workers(null, { testConfig: './codecept.conf.js' })
399
117
 
400
- for (const config of configs) {
401
- for (group of testGroups) {
118
+ // split the suite into 2 groups, run each group on two browsers
119
+ const groups = workers.createGroupsOfSuites(2)
120
+ for (const browser of ['chromium', 'firefox']) {
121
+ for (const group of groups) {
402
122
  const worker = workers.spawn()
403
123
  worker.addTests(group)
404
- worker.addConfig(config)
124
+ worker.addConfig({ helpers: { Playwright: { browser } } })
405
125
  }
406
126
  }
407
127
 
408
- // Listen events for failed test
409
- workers.on(event.test.failed, failedTest => {
410
- console.log('Failed : ', failedTest.title)
411
- })
412
-
413
- // Listen events for passed test
414
- workers.on(event.test.passed, successTest => {
415
- console.log('Passed : ', successTest.title)
416
- })
417
-
418
- // test run status will also be available in event
419
- workers.on(event.all.result, () => {
420
- // Use printResults() to display result with standard style
421
- workers.printResults()
422
- })
423
-
424
- // run workers as async function
425
- runWorkers()
426
-
427
- async function runWorkers() {
428
- try {
429
- // run bootstrapAll
430
- await workers.bootstrapAll()
431
- // run tests
432
- await workers.run()
433
- } finally {
434
- // run teardown All
435
- await workers.teardownAll()
436
- }
437
- }
438
- ```
128
+ workers.on(event.test.failed, t => console.log('FAIL', t.title))
129
+ workers.on(event.all.result, () => workers.printResults())
439
130
 
440
- Inside `event.all.result` you can obtain test results from all workers, so you can customize the report:
441
-
442
- ```js
443
- workers.on(event.all.result, result => {
444
- // print output
445
- console.log('Test status : ', result.hasFailed() ? 'Failed' : 'Passed');
446
-
447
- // print stats
448
- console.log(`Total tests : ${result.stats.tests}`);
449
- console.log(`Passed tests : ${result.stats.passes}`);
450
- console.log(`Failed test tests : ${result.stats.failures}`);
451
-
452
- // If you don't want to listen for failed and passed test separately, use `tests` array
453
- for (const test of result.tests) {
454
- console.log(`Test status: ${test.err===null}, `, `Test : ${test.title}`);
455
- }
131
+ await workers.bootstrapAll()
132
+ try {
133
+ await workers.run()
134
+ } finally {
135
+ await workers.teardownAll()
456
136
  }
457
137
  ```
458
138
 
459
- ### Example: Running Tests Split By A Custom Function
460
-
461
- If you want your tests to split according to your need this method is suited for you. For example: If you have 4 long running test files and 4 normal test files there chance all 4 tests end up in same worker thread. For these cases custom function will be helpful.
462
-
463
- ```js
464
- /*
465
- Define a function to split your tests.
466
-
467
- function should return an array with this format [[file1, file2], [file3], ...]
468
-
469
- where file1 and file2 will run in a worker thread and file3 will run in a worker thread
470
- */
471
- const splitTests = () => {
472
- const files = [['./test/data/sandbox/guthub_test.js', './test/data/sandbox/devto_test.js'], ['./test/data/sandbox/longrunnig_test.js']]
473
-
474
- return files
475
- }
476
-
477
- const workerConfig = {
478
- testConfig: './test/data/sandbox/codecept.customworker.js',
479
- by: splitTests,
480
- }
481
-
482
- // don't initialize workers in constructor
483
- const customWorkers = new Workers(null, workerConfig)
484
-
485
- customWorkers.run()
486
-
487
- // You can use event listeners similar to above example.
488
- customWorkers.on(event.all.result, () => {
489
- workers.printResults()
490
- })
491
- ```
139
+ Building blocks:
492
140
 
493
- ### Emitting messages to the parent worker
141
+ - `new Workers(N, { testConfig, options })` — `N` workers; pass `null` to spawn them yourself with `spawn()`.
142
+ - `createGroupsOfTests(n)` / `createGroupsOfSuites(n)` — split the suite into `n` groups.
143
+ - `worker.addTests(group)` / `worker.addConfig(partialConfig)` — assign tests and config overrides to a spawned worker.
144
+ - `bootstrapAll()` → `run()` → `teardownAll()` — lifecycle (wrap `run()` in `try/finally` so teardown always runs).
145
+ - Events on the `workers` object: `event.test.passed`, `event.test.failed`, `event.all.result`, plus `'message'` for anything a child worker sends. `printResults()` prints the standard summary; `result.hasFailed()` and `result.stats` give the totals.
494
146
 
495
- Child workers can send non-test events to the main process. This is useful if you want to pass along information not related to the tests event cycles itself such as `event.test.success`.
147
+ To split by your own rule, pass a function as `by` it receives the worker count and returns an array of file groups:
496
148
 
497
149
  ```js
498
- // inside main process
499
- // listen for any non test related events
500
- workers.on('message', data => {
501
- console.log(data)
502
- })
503
-
504
- workers.on(event.all.result, result => {
505
- // logic
506
- })
507
- ```
508
-
509
- ## Sharing Data Between Workers
150
+ const splitTests = () => [
151
+ ['./test/login_test.js', './test/signup_test.js'], // group 1
152
+ ['./test/slow_checkout_test.js'], // group 2
153
+ ]
510
154
 
511
- NodeJS Workers can communicate between each other via messaging system. CodeceptJS allows you to share data between different worker processes using the `share()` and `inject()` functions.
155
+ const workers = new Workers(2, { testConfig: './codecept.conf.js', by: splitTests })
156
+ workers.on(event.all.result, () => workers.printResults())
157
+ await workers.run()
158
+ ```
512
159
 
513
- ### Basic Usage
160
+ ## Sharing data between workers
514
161
 
515
- You can share data directly using the `share()` function and access it using `inject()`:
162
+ Worker threads don't share memory. `share()` publishes a value that any worker reads with `inject()`:
516
163
 
517
164
  ```js
518
- // In one test or worker
519
- share({ userData: { name: 'user', password: '123456' } })
165
+ // in any test or hook
166
+ share({ user: { name: 'jane', password: 's3cret' } })
520
167
 
521
- // In another test or worker
522
- const testData = inject()
523
- console.log(testData.userData.name) // 'user'
524
- console.log(testData.userData.password) // '123456'
168
+ // anywhere else, even in another worker
169
+ const { user } = inject()
525
170
  ```
526
171
 
527
- ### Initializing Data in Bootstrap
528
-
529
- For complex scenarios where you need to initialize shared data before tests run, you can use the bootstrap function:
172
+ Seed shared state before tests run from `bootstrap()`:
530
173
 
531
174
  ```js
532
- // inside codecept.conf.js
175
+ // codecept.conf.js
533
176
  export const config = {
534
177
  bootstrap() {
535
- // Initialize shared data container
536
- share({ userData: null, config: { retries: 3 } })
178
+ share({ user: null })
537
179
  },
538
180
  }
539
181
  ```
540
182
 
541
- Then in your tests, you can check and update the shared data:
542
-
543
- ```js
544
- const testData = inject()
545
- if (!testData.userData) {
546
- // Update shared data - both approaches work:
547
- share({ userData: { name: 'user', password: '123456' } })
548
- // or mutate the injected object:
549
- testData.userData = { name: 'user', password: '123456' }
550
- }
551
- ```
552
-
553
- ### Working with Proxy Objects
554
-
555
- Since CodeceptJS 3.7.0+, shared data uses Proxy objects for synchronization between workers. The proxy system works seamlessly for most use cases:
556
-
557
- ```js
558
- // ✅ All of these work correctly:
559
- const data = inject()
560
- console.log(data.userData.name) // Access nested properties
561
- console.log(Object.keys(data)) // Enumerate shared keys
562
- data.newProperty = 'value' // Add new properties
563
- Object.assign(data, { more: 'data' }) // Merge objects
564
- ```
565
-
566
- **Important Note:** Avoid reassigning the entire injected object:
567
-
568
- ```js
569
- // ❌ AVOID: This breaks the proxy reference
570
- let testData = inject()
571
- testData = someOtherObject // This will NOT work as expected!
572
-
573
- // ✅ PREFERRED: Use share() to replace data or mutate properties
574
- share({ userData: someOtherObject }) // This works!
575
- // or
576
- Object.assign(inject(), someOtherObject) // This works!
577
- ```
578
-
579
- ### Local Data (Worker-Specific)
580
-
581
- If you want to share data only within the same worker (not across all workers), use the `local` option:
183
+ Shared data is a Proxy. Don't reassign the injected object itself (`let d = inject(); d = {…}` breaks the link); mutate it or call `share()` again. Pass `{ local: true }` to keep a value inside one worker:
582
184
 
583
185
  ```js
584
- share({ localData: 'worker-specific' }, { local: true })
186
+ share({ tmpFile: '/tmp/run-1' }, { local: true })
585
187
  ```