@isentinel/jest-roblox 0.3.1 → 0.3.4
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 +160 -155
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +6 -25
- package/dist/index.d.mts +293 -6
- package/dist/index.mjs +84 -2
- package/dist/{run-Cl5gYSQr.mjs → run-D20euZYa.mjs} +4072 -2878
- package/dist/{schema-BpjBo-Aw.d.mts → schema-BCTnsaiC.d.mts} +68 -21
- package/package.json +25 -17
- package/plugin/JestRobloxRunner.rbxm +0 -0
- package/dist/sea-entry.cjs +0 -42878
package/README.md
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
<a href="https://github.com/christopher-buss/jest-roblox-cli/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
Run your roblox-ts and Luau tests inside Roblox, get results in your terminal.
|
|
11
10
|
|
|
12
11
|
<p align="center">
|
|
@@ -19,8 +18,7 @@ Run your roblox-ts and Luau tests inside Roblox, get results in your terminal.
|
|
|
19
18
|
- Two backends: Open Cloud (remote) and Studio (local)
|
|
20
19
|
- Multiple output formatters (human, agent, JSON, GitHub Actions)
|
|
21
20
|
|
|
22
|
-
> [!NOTE]
|
|
23
|
-
> roblox-ts projects currently require
|
|
21
|
+
> [!NOTE] roblox-ts projects currently require
|
|
24
22
|
> [@isentinel/roblox-ts](https://npmx.dev/package/@isentinel/roblox-ts) for
|
|
25
23
|
> source maps and coverage support.
|
|
26
24
|
|
|
@@ -123,79 +121,86 @@ Precedence: CLI flags > config file > extended config > defaults.
|
|
|
123
121
|
|
|
124
122
|
### Root config fields
|
|
125
123
|
|
|
126
|
-
Two distinct buckets live at the root level. Jest passthrough fields live
|
|
127
|
-
|
|
124
|
+
Two distinct buckets live at the root level. Jest passthrough fields live under
|
|
125
|
+
`test:` (see "Test fields" below).
|
|
128
126
|
|
|
129
127
|
#### Workspace Run Options
|
|
130
128
|
|
|
131
|
-
Atomic to one invocation — these describe what the run targets and how the
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
| Field
|
|
137
|
-
|
|
138
|
-
| `backend`
|
|
139
|
-
| `color`
|
|
140
|
-
| `formatters`
|
|
141
|
-
| `gameOutput`
|
|
142
|
-
| `outputFile`
|
|
143
|
-
| `workspace.gameOutput` | `true` to also emit per-package Game Output files under `.jest-roblox/output/` (`--workspace` only)
|
|
144
|
-
| `workspace.outputFile` | `true` to also emit per-package result files under `.jest-roblox/output/` (`--workspace` only)
|
|
145
|
-
| `parallel`
|
|
146
|
-
| `placeId`
|
|
147
|
-
| `port`
|
|
148
|
-
| `silent`
|
|
149
|
-
| `universeId`
|
|
129
|
+
Atomic to one invocation — these describe what the run targets and how the CLI
|
|
130
|
+
presents output, not how any individual package runs. In `--workspace` mode they
|
|
131
|
+
resolve as: CLI flag > unanimous per-package declaration > default. Mixed
|
|
132
|
+
per-package declarations error loudly.
|
|
133
|
+
|
|
134
|
+
| Field | What it does | Default |
|
|
135
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
|
|
136
|
+
| `backend` | `"auto"`, `"open-cloud"`, or `"studio"` | `"auto"` |
|
|
137
|
+
| `color` | Use ANSI colors in console output | `true` |
|
|
138
|
+
| `formatters` | Output formatters (`"default"`, `"agent"`, `"json"`, `"github-actions"`) | `["default"]` |
|
|
139
|
+
| `gameOutput` | Write Game Output to a file — a path, or `true` for `game-output.log` under the root. In `--workspace` mode this is one grouped aggregate file across every package | — |
|
|
140
|
+
| `outputFile` | Write the Jest result JSON — a path, or `true` for `jest-output.log` under the root. In `--workspace` mode this is the single merged result across every package | — |
|
|
141
|
+
| `workspace.gameOutput` | `true` to also emit per-package Game Output files under `.jest-roblox/output/` (`--workspace` only) | — |
|
|
142
|
+
| `workspace.outputFile` | `true` to also emit per-package result files under `.jest-roblox/output/` (`--workspace` only) | — |
|
|
143
|
+
| `parallel` | Number of concurrent Open Cloud sessions, or `"auto"` (= `min(jobs, 3)`) | — |
|
|
144
|
+
| `placeId` | Open Cloud place ID | — |
|
|
145
|
+
| `port` | WebSocket port for Studio backend | `3001` |
|
|
146
|
+
| `silent` | Suppress console output | `false` |
|
|
147
|
+
| `universeId` | Open Cloud universe ID | — |
|
|
150
148
|
|
|
151
149
|
#### Per-package fields
|
|
152
150
|
|
|
153
151
|
Loaded per package (directly or via `extends: "../jest.shared.ts"`). The
|
|
154
|
-
workspace-root config is NOT a source of truth for these — declare them in
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
|
159
|
-
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
166
|
-
| `
|
|
167
|
-
| `luauRoots` | Where Luau files live for coverage instrumentation | auto from tsconfig `outDir` |
|
|
152
|
+
workspace-root config is NOT a source of truth for these — declare them in each
|
|
153
|
+
package's own jest.config or in a shared config that every package extends.
|
|
154
|
+
|
|
155
|
+
| Field | What it does | Default |
|
|
156
|
+
| --------------- | ----------------------------------------------------------------- | --------------------------- |
|
|
157
|
+
| `placeFile` | Path to your `.rbxl` file | `"./game.rbxl"` |
|
|
158
|
+
| `timeout` | Max time for tests to run (ms) | `300000` (5 min) |
|
|
159
|
+
| `sourceMap` | Map Luau errors back to TypeScript (roblox-ts only) | `true` |
|
|
160
|
+
| `rojoProject` | Path to your Rojo project file | auto |
|
|
161
|
+
| `jestPath` | Where Jest lives in the DataModel | auto |
|
|
162
|
+
| `showLuau` | Show Luau code snippets in failure output | `true` |
|
|
163
|
+
| `coverageCache` | Reuse incrementally-instrumented coverage shadow dir between runs | `true` |
|
|
164
|
+
| `luauRoots` | Where Luau files live for coverage instrumentation | auto from tsconfig `outDir` |
|
|
168
165
|
|
|
169
166
|
### Test fields
|
|
170
167
|
|
|
171
168
|
Put these under `test: { ... }`.
|
|
172
169
|
|
|
173
|
-
| Field
|
|
174
|
-
|
|
175
|
-
| `projects`
|
|
176
|
-
| `testMatch`
|
|
177
|
-
| `testPathIgnorePatterns` | Patterns to skip
|
|
178
|
-
| `setupFiles`
|
|
179
|
-
| `setupFilesAfterEnv`
|
|
180
|
-
| `verbose`
|
|
181
|
-
| `silent`
|
|
170
|
+
| Field | What it does | Default |
|
|
171
|
+
| ------------------------ | ------------------------------------------------ | ------------------------------------ |
|
|
172
|
+
| `projects` | Where to look for tests in the DataModel | **required** |
|
|
173
|
+
| `testMatch` | Glob patterns that find test files | `**/*.spec.ts`, `**/*.test.ts`, etc. |
|
|
174
|
+
| `testPathIgnorePatterns` | Patterns to skip | `/node_modules/`, `/dist/`, `/out/` |
|
|
175
|
+
| `setupFiles` | Scripts to run before the test environment loads | — |
|
|
176
|
+
| `setupFilesAfterEnv` | Scripts to run after the test environment loads | — |
|
|
177
|
+
| `verbose` | Show individual test results | `false` |
|
|
178
|
+
| `silent` | Suppress console output | `false` |
|
|
182
179
|
|
|
183
180
|
### Coverage fields
|
|
184
181
|
|
|
185
182
|
Put these under `test: { ... }`.
|
|
186
183
|
|
|
187
|
-
> [!IMPORTANT]
|
|
188
|
-
>
|
|
189
|
-
>
|
|
190
|
-
|
|
191
|
-
| Field
|
|
192
|
-
|
|
193
|
-
| `collectCoverage`
|
|
194
|
-
| `coverageDirectory`
|
|
195
|
-
| `coverageReporters`
|
|
196
|
-
| `coverageThreshold`
|
|
197
|
-
| `coveragePathIgnorePatterns` | Files to leave out of coverage
|
|
198
|
-
| `collectCoverageFrom`
|
|
184
|
+
> [!IMPORTANT] Coverage requires [Lute](https://github.com/luau-lang/lute) to be
|
|
185
|
+
> installed and on your `PATH`. Lute parses Luau ASTs so the CLI can insert
|
|
186
|
+
> coverage probes.
|
|
187
|
+
|
|
188
|
+
| Field | What it does | Default |
|
|
189
|
+
| ---------------------------- | -------------------------------------- | ------------------------------------------- |
|
|
190
|
+
| `collectCoverage` | Turn on coverage | `false` |
|
|
191
|
+
| `coverageDirectory` | Where to write coverage reports | `"coverage"` |
|
|
192
|
+
| `coverageReporters` | Which report formats to use | `["text", "lcov"]` |
|
|
193
|
+
| `coverageThreshold` | Minimum coverage to pass | — |
|
|
194
|
+
| `coveragePathIgnorePatterns` | Files to leave out of coverage | test files, `node_modules`, `rbxts_include` |
|
|
195
|
+
| `collectCoverageFrom` | Globs for files to include in coverage | — |
|
|
196
|
+
|
|
197
|
+
> [!NOTE] Coverage uses vitest `all` / Istanbul semantics: every instrumented
|
|
198
|
+
> file matching the include globs is reported, so a source file with no test
|
|
199
|
+
> shows **0%** (and fails `coverageThreshold`) instead of being silently
|
|
200
|
+
> omitted. When `collectCoverageFrom` is unset for a multi-project run, the
|
|
201
|
+
> include universe is derived from each project's `include` globs, excluding
|
|
202
|
+
> `*.spec`/`*.test` and `*.client`/`*.server` entry-point scripts (which compile
|
|
203
|
+
> to LocalScript/Script and can't be `require`d, so no test can cover them).
|
|
199
204
|
|
|
200
205
|
### Project-level config
|
|
201
206
|
|
|
@@ -257,9 +262,9 @@ Two ways to run tests, plus an auto-pick:
|
|
|
257
262
|
|
|
258
263
|
### Auto (default)
|
|
259
264
|
|
|
260
|
-
`--backend auto` (the default) probes for a connected Studio plugin first.
|
|
261
|
-
|
|
262
|
-
|
|
265
|
+
`--backend auto` (the default) probes for a connected Studio plugin first. If
|
|
266
|
+
detected, runs via Studio; otherwise falls back to Open Cloud — but only if
|
|
267
|
+
credentials are available (see Open Cloud below). With no plugin and no
|
|
263
268
|
credentials, the run errors instead of silently falling back.
|
|
264
269
|
|
|
265
270
|
### Open Cloud (remote)
|
|
@@ -268,13 +273,15 @@ Uploads your place file to Roblox and polls for results.
|
|
|
268
273
|
|
|
269
274
|
You need these environment variables:
|
|
270
275
|
|
|
271
|
-
| Variable
|
|
272
|
-
|
|
273
|
-
| `ROBLOX_OPEN_CLOUD_API_KEY` | Your Open Cloud API key
|
|
274
|
-
| `ROBLOX_UNIVERSE_ID`
|
|
275
|
-
| `ROBLOX_PLACE_ID`
|
|
276
|
+
| Variable | What it is |
|
|
277
|
+
| --------------------------- | ---------------------------- |
|
|
278
|
+
| `ROBLOX_OPEN_CLOUD_API_KEY` | Your Open Cloud API key |
|
|
279
|
+
| `ROBLOX_UNIVERSE_ID` | The universe to run tests in |
|
|
280
|
+
| `ROBLOX_PLACE_ID` | The place to run tests in |
|
|
276
281
|
|
|
277
|
-
> Prefix any of the above with `JEST_` (e.g. `JEST_ROBLOX_PLACE_ID`) to override
|
|
282
|
+
> Prefix any of the above with `JEST_` (e.g. `JEST_ROBLOX_PLACE_ID`) to override
|
|
283
|
+
> the unprefixed value. Use the `JEST_`-prefixed form when the generic names
|
|
284
|
+
> collide with other tooling.
|
|
278
285
|
|
|
279
286
|
#### Required scopes
|
|
280
287
|
|
|
@@ -284,39 +291,38 @@ with the missing scope name.
|
|
|
284
291
|
|
|
285
292
|
Always required:
|
|
286
293
|
|
|
287
|
-
| Scope
|
|
288
|
-
|
|
289
|
-
| `universe-places:write`
|
|
290
|
-
| `universe.place.luau-execution-session:write` | Start the Luau session that runs the tests
|
|
294
|
+
| Scope | What it's for |
|
|
295
|
+
| --------------------------------------------- | ------------------------------------------------ |
|
|
296
|
+
| `universe-places:write` | Publish the built `.rbxl` as a new place version |
|
|
297
|
+
| `universe.place.luau-execution-session:write` | Start the Luau session that runs the tests |
|
|
291
298
|
|
|
292
299
|
`--workspace --parallel >1` additionally requires the queue scopes for
|
|
293
300
|
work-stealing across concurrent sessions:
|
|
294
301
|
|
|
295
|
-
| Scope
|
|
296
|
-
|
|
302
|
+
| Scope | What it's for |
|
|
303
|
+
| -------------------------------------------------- | ---------------------------------------------- |
|
|
297
304
|
| `memory-store.queue:add` / `:dequeue` / `:discard` | Work-stealing queue across concurrent sessions |
|
|
298
305
|
|
|
299
306
|
`--workspace --parallel >1` with a streaming formatter additionally requires:
|
|
300
307
|
|
|
301
|
-
| Scope
|
|
302
|
-
|
|
308
|
+
| Scope | What it's for |
|
|
309
|
+
| ----------------------------------------- | ------------------------------------------------------- |
|
|
303
310
|
| `memory-store.sorted-map:read` / `:write` | Stream live per-package results back as packages finish |
|
|
304
311
|
|
|
305
312
|
Streaming is enabled by default and disabled only for `--silent`,
|
|
306
313
|
`--formatters json`, and `--formatters agent` (without `--verbose`).
|
|
307
|
-
`--formatters agent --verbose` re-enables streaming and therefore still
|
|
308
|
-
|
|
314
|
+
`--formatters agent --verbose` re-enables streaming and therefore still needs
|
|
315
|
+
the sorted-map scopes; `--formatters github-actions` also streams.
|
|
309
316
|
|
|
310
317
|
### Studio (local)
|
|
311
318
|
|
|
312
319
|
Connects to Roblox Studio over WebSocket. Faster than Open Cloud (no upload
|
|
313
|
-
step), but Studio must be open with the plugin running. Studio doesn't expose
|
|
314
|
-
multiple concurrent projects aren't supported yet.
|
|
320
|
+
step), but Studio must be open with the plugin running. Studio doesn't expose
|
|
321
|
+
which place is open, so multiple concurrent projects aren't supported yet.
|
|
315
322
|
|
|
316
|
-
> [!NOTE]
|
|
317
|
-
>
|
|
318
|
-
>
|
|
319
|
-
> the studio place being served.
|
|
323
|
+
> [!NOTE] For `--coverage`, prefer `--backend open-cloud` since the coverage
|
|
324
|
+
> output is built to a separate output under `.jest-roblox/coverage/` that is
|
|
325
|
+
> likely not the studio place being served.
|
|
320
326
|
|
|
321
327
|
Install the plugin with [Drillbit](https://github.com/jacktabscode/drillbit):
|
|
322
328
|
|
|
@@ -329,7 +335,8 @@ Create a file named drillbit.toml in your project's directory.
|
|
|
329
335
|
github = "https://github.com/christopher-buss/jest-roblox-cli/releases/download/v0.2.7/JestRobloxRunner.rbxm"
|
|
330
336
|
```
|
|
331
337
|
|
|
332
|
-
Then run `drillbit` and it will download the plugin and install it in Studio for
|
|
338
|
+
Then run `drillbit` and it will download the plugin and install it in Studio for
|
|
339
|
+
you.
|
|
333
340
|
|
|
334
341
|
Or download `JestRobloxRunner.rbxm` from the
|
|
335
342
|
[latest release](https://github.com/christopher-buss/jest-roblox-cli/releases)
|
|
@@ -337,20 +344,19 @@ and drop it into your Studio plugins folder.
|
|
|
337
344
|
|
|
338
345
|
## Workspace mode
|
|
339
346
|
|
|
340
|
-
Run tests across multiple packages in a pnpm workspace in a single
|
|
341
|
-
|
|
347
|
+
Run tests across multiple packages in a pnpm workspace in a single invocation.
|
|
348
|
+
Open Cloud only — Studio backend is not supported.
|
|
342
349
|
|
|
343
|
-
> [!NOTE]
|
|
344
|
-
> Package discovery uses one of two sources. By default it reads
|
|
350
|
+
> [!NOTE] Package discovery uses one of two sources. By default it reads
|
|
345
351
|
> `pnpm-workspace.yaml` at the workspace root. Alternatively, declare a
|
|
346
352
|
> `workspace` block in your jest config (see
|
|
347
|
-
> [Workspaces without pnpm](#workspaces-without-pnpm)) to enumerate packages
|
|
348
|
-
>
|
|
349
|
-
>
|
|
350
|
-
>
|
|
351
|
-
>
|
|
352
|
-
>
|
|
353
|
-
>
|
|
353
|
+
> [Workspaces without pnpm](#workspaces-without-pnpm)) to enumerate packages by
|
|
354
|
+
> glob — this works in Luau-only, npm, and yarn repos. `--affected-since` always
|
|
355
|
+
> delegates change detection to `turbo` or `nx` and is not yet wired for the
|
|
356
|
+
> `workspace.packages` source. When using Nx, each project's Nx name must match
|
|
357
|
+
> the `package.json` `name` field — `--affected-since` returns Nx project names
|
|
358
|
+
> and looks them up against the package list, so a mismatch surfaces as
|
|
359
|
+
> `Package "<name>" not found in workspace`.
|
|
354
360
|
|
|
355
361
|
Pick packages explicitly or by what changed:
|
|
356
362
|
|
|
@@ -362,8 +368,8 @@ jest-roblox --workspace --packages @scope/pkg-a,@scope/pkg-b
|
|
|
362
368
|
jest-roblox --workspace --affected-since main
|
|
363
369
|
```
|
|
364
370
|
|
|
365
|
-
`--workspace` must be combined with `--packages` or `--affected-since` —
|
|
366
|
-
|
|
371
|
+
`--workspace` must be combined with `--packages` or `--affected-since` — the two
|
|
372
|
+
are mutually exclusive, and either flag requires `--workspace`.
|
|
367
373
|
|
|
368
374
|
### Workspaces without pnpm
|
|
369
375
|
|
|
@@ -395,12 +401,12 @@ from. Each glob in `packages` selects directories that contain a
|
|
|
395
401
|
`jest.config.*`; the package name comes from `package.json#name`, falling back
|
|
396
402
|
to the directory name (so Luau-only packages need no `package.json`). Every
|
|
397
403
|
selected package must resolve the same `workspace.packages`/`root` — inheriting
|
|
398
|
-
from one shared config guarantees this, and a package that overrides or omits
|
|
399
|
-
|
|
404
|
+
from one shared config guarantees this, and a package that overrides or omits it
|
|
405
|
+
fails the run.
|
|
400
406
|
|
|
401
|
-
Run from inside any package as usual. To run from a directory with no
|
|
402
|
-
|
|
403
|
-
|
|
407
|
+
Run from inside any package as usual. To run from a directory with no resolvable
|
|
408
|
+
jest config (e.g. the repo root), either point at the shared config with
|
|
409
|
+
`--workspace-root`:
|
|
404
410
|
|
|
405
411
|
```bash
|
|
406
412
|
jest-roblox --workspace --packages foo --workspace-root packages/testing
|
|
@@ -415,61 +421,61 @@ export { default } from "./packages/testing/jest.shared.ts";
|
|
|
415
421
|
|
|
416
422
|
Per-package coverage is aggregated into a single report under
|
|
417
423
|
`<rootDir>/<coverageDirectory>`. `rootDir` defaults to the current working
|
|
418
|
-
directory, so run from the workspace root (or set `rootDir`) if you want
|
|
419
|
-
|
|
424
|
+
directory, so run from the workspace root (or set `rootDir`) if you want the
|
|
425
|
+
report to land there.
|
|
420
426
|
|
|
421
|
-
Game Output has two independent sinks. Setting `gameOutput` (a path, or
|
|
422
|
-
|
|
427
|
+
Game Output has two independent sinks. Setting `gameOutput` (a path, or `true`)
|
|
428
|
+
writes one **grouped** aggregate file at the workspace root —
|
|
423
429
|
`[{ package, project, entries }]`, one group per (package, project) that ran.
|
|
424
|
-
Setting `workspace.gameOutput: true` writes a **per-package** file per
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
per-package paths.
|
|
430
|
+
Setting `workspace.gameOutput: true` writes a **per-package** file per (package,
|
|
431
|
+
project) under `.jest-roblox/output/`. Either, both, or neither may be set; with
|
|
432
|
+
both, humans see the aggregate announced and agents see the per-package paths.
|
|
428
433
|
|
|
429
434
|
`outputFile` (the Jest result JSON) follows the same two-sink model:
|
|
430
|
-
`outputFile` (a path, or `true`) writes one merged result at the workspace
|
|
431
|
-
|
|
432
|
-
|
|
435
|
+
`outputFile` (a path, or `true`) writes one merged result at the workspace root,
|
|
436
|
+
and `workspace.outputFile: true` writes a per-package result file per (package,
|
|
437
|
+
project) under `.jest-roblox/output/`.
|
|
433
438
|
|
|
434
439
|
## CLI flags
|
|
435
440
|
|
|
436
|
-
| Flag
|
|
437
|
-
|
|
438
|
-
| `--backend <type>`
|
|
439
|
-
| `--port <n>`
|
|
440
|
-
| `--config <path>`
|
|
441
|
-
| `--testPathPattern <regex>`
|
|
442
|
-
| `-t, --testNamePattern <regex>`
|
|
443
|
-
| `--formatters <name...>`
|
|
444
|
-
| `--outputFile <path>`
|
|
445
|
-
| `--gameOutput <path>`
|
|
446
|
-
| `--coverage`
|
|
447
|
-
| `--
|
|
448
|
-
| `--
|
|
449
|
-
| `--
|
|
450
|
-
| `--
|
|
451
|
-
|
|
|
452
|
-
|
|
|
453
|
-
| `--
|
|
454
|
-
| `--
|
|
455
|
-
| `--
|
|
456
|
-
| `--
|
|
457
|
-
| `--
|
|
458
|
-
| `--
|
|
459
|
-
| `--no-
|
|
460
|
-
| `--
|
|
461
|
-
| `--
|
|
462
|
-
| `--
|
|
463
|
-
| `--
|
|
464
|
-
| `--
|
|
465
|
-
| `--
|
|
466
|
-
| `--
|
|
467
|
-
| `--
|
|
468
|
-
| `--packages
|
|
469
|
-
| `--
|
|
470
|
-
| `--
|
|
471
|
-
| `--
|
|
472
|
-
| `--
|
|
441
|
+
| Flag | What it does |
|
|
442
|
+
| -------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
443
|
+
| `--backend <type>` | Choose `auto`, `open-cloud`, or `studio` |
|
|
444
|
+
| `--port <n>` | WebSocket port for Studio |
|
|
445
|
+
| `--config <path>` | Path to config file |
|
|
446
|
+
| `--testPathPattern <regex>` | Filter test files by path |
|
|
447
|
+
| `-t, --testNamePattern <regex>` | Filter tests by name |
|
|
448
|
+
| `--formatters <name...>` | Output formatters (`default`, `agent`, `json`, `github-actions`) |
|
|
449
|
+
| `--outputFile <path>` | Write results to a file |
|
|
450
|
+
| `--gameOutput <path>` | Write game print/warn/error to a file |
|
|
451
|
+
| `--coverage` | Collect coverage |
|
|
452
|
+
| `--no-coverage` | Disable coverage for this run, even when enabled in config |
|
|
453
|
+
| `--coverageDirectory <path>` | Where to put coverage reports |
|
|
454
|
+
| `--coverageReporters <r...>` | Which report formats to use |
|
|
455
|
+
| `--collectCoverageFrom <glob>` | Globs for files to include in coverage (repeatable) |
|
|
456
|
+
| `--no-show-luau` | Hide Luau code in failure output |
|
|
457
|
+
| `-u, --updateSnapshot` | Update snapshot files |
|
|
458
|
+
| `--sourceMap` | Map Luau errors to TypeScript (roblox-ts only) |
|
|
459
|
+
| `--rojoProject <path>` | Path to Rojo project file |
|
|
460
|
+
| `--timeout <ms>` | Max time for tests to run |
|
|
461
|
+
| `--passWithNoTests` | Exit `0` when no test files are found |
|
|
462
|
+
| `--verbose` | Show each test result |
|
|
463
|
+
| `--silent` | Hide all output |
|
|
464
|
+
| `--no-color` | Turn off colors |
|
|
465
|
+
| `--no-coverage-cache` | Force a clean coverage re-instrumentation |
|
|
466
|
+
| `--parallel [n]` | Open Cloud concurrent sessions, or `auto` (= `min(jobs, 3)`) |
|
|
467
|
+
| `--project <name...>` | Filter which named projects to run |
|
|
468
|
+
| `--setupFiles <path...>` | Scripts to run before env |
|
|
469
|
+
| `--setupFilesAfterEnv <path...>` | Scripts to run after env |
|
|
470
|
+
| `--typecheck` | Run type tests too |
|
|
471
|
+
| `--typecheckOnly` | Run only type tests |
|
|
472
|
+
| `--typecheckTsconfig <path>` | tsconfig for type tests |
|
|
473
|
+
| `--workspace` | Enable workspace mode (pair with `--packages` or `--affected-since`; see [Workspace mode](#workspace-mode)) |
|
|
474
|
+
| `--packages <names>` | Comma-separated package names (workspace mode) |
|
|
475
|
+
| `--affected-since <ref>` | Run only packages affected since a git ref (workspace mode) |
|
|
476
|
+
| `--apiKey <key>` | Open Cloud API key (prefer env vars in CI — visible in process listings) |
|
|
477
|
+
| `--universeId <id>` | Target universe ID (Open Cloud) |
|
|
478
|
+
| `--placeId <id>` | Target place ID (Open Cloud) |
|
|
473
479
|
|
|
474
480
|
## How it works
|
|
475
481
|
|
|
@@ -480,10 +486,9 @@ root, and `workspace.outputFile: true` writes a per-package result file per
|
|
|
480
486
|
5. Maps Luau line numbers to TypeScript via source maps (roblox-ts only)
|
|
481
487
|
6. Prints results
|
|
482
488
|
|
|
483
|
-
> [!NOTE]
|
|
484
|
-
>
|
|
485
|
-
>
|
|
486
|
-
> goes through source maps to report TypeScript lines.
|
|
489
|
+
> [!NOTE] Coverage adds extra steps: copy Luau files, insert tracking probes,
|
|
490
|
+
> build a separate place file, then map hit counts back to source. For
|
|
491
|
+
> roblox-ts, this goes through source maps to report TypeScript lines.
|
|
487
492
|
|
|
488
493
|
## Test file patterns
|
|
489
494
|
|
package/dist/cli.d.mts
CHANGED
package/dist/cli.mjs
CHANGED
|
@@ -1,31 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $ as loadConfig, D as outputMultiResult, H as formatBanner, O as outputSingleResult, P as parseGameOutput, Q as mergeCliWithConfig, Y as LuauScriptError, dt as version, f as formatMissingScopes, lt as isValidBackend, n as runJestRoblox, ot as VALID_BACKENDS, p as walkErrorChain, ut as ConfigError } from "./run-D20euZYa.mjs";
|
|
2
2
|
import { OpenCloudError } from "@bedrock-rbx/ocale";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { parseArgs as parseArgs$1 } from "node:util";
|
|
5
5
|
import color from "tinyrainbow";
|
|
6
|
-
//#region src/utils/error-chain.ts
|
|
7
|
-
const MAX_DEPTH = 5;
|
|
8
|
-
function walkErrorChain(err) {
|
|
9
|
-
const entries = [];
|
|
10
|
-
let current = err;
|
|
11
|
-
while (current instanceof Error && entries.length < MAX_DEPTH) {
|
|
12
|
-
entries.push({
|
|
13
|
-
name: current.constructor.name,
|
|
14
|
-
code: readStringProperty(current, "code"),
|
|
15
|
-
errno: readStringProperty(current, "errno"),
|
|
16
|
-
message: current.message,
|
|
17
|
-
syscall: readStringProperty(current, "syscall")
|
|
18
|
-
});
|
|
19
|
-
current = current.cause;
|
|
20
|
-
}
|
|
21
|
-
return entries;
|
|
22
|
-
}
|
|
23
|
-
function readStringProperty(err, key) {
|
|
24
|
-
const value = Reflect.get(err, key);
|
|
25
|
-
if (value === void 0 || value === null) return;
|
|
26
|
-
return String(value);
|
|
27
|
-
}
|
|
28
|
-
//#endregion
|
|
29
6
|
//#region src/cli.ts
|
|
30
7
|
const VERSION = version;
|
|
31
8
|
const HELP_TEXT = `
|
|
@@ -47,6 +24,7 @@ Options:
|
|
|
47
24
|
--no-color Disable colored output
|
|
48
25
|
-u, --updateSnapshot Update snapshot files
|
|
49
26
|
--coverage Enable coverage collection
|
|
27
|
+
--no-coverage Disable coverage for this run (overrides config)
|
|
50
28
|
--collectCoverageFrom <glob> Globs for files to include in coverage (repeatable)
|
|
51
29
|
--coverageDirectory <path> Directory for coverage output (default: coverage)
|
|
52
30
|
--coverageReporters <r...> Coverage reporters (default: text, lcov)
|
|
@@ -90,6 +68,7 @@ Examples:
|
|
|
90
68
|
jest-roblox -t "should spawn" Run tests matching pattern
|
|
91
69
|
jest-roblox --formatters json Output JSON to file
|
|
92
70
|
jest-roblox --coverage Run tests with coverage instrumentation
|
|
71
|
+
jest-roblox --no-coverage Skip coverage instrumentation for this run
|
|
93
72
|
`;
|
|
94
73
|
function parseArgs(args) {
|
|
95
74
|
const { positionals, values } = parseArgs$1({
|
|
@@ -122,6 +101,7 @@ function parseArgs(args) {
|
|
|
122
101
|
type: "boolean"
|
|
123
102
|
},
|
|
124
103
|
"no-color": { type: "boolean" },
|
|
104
|
+
"no-coverage": { type: "boolean" },
|
|
125
105
|
"no-coverage-cache": { type: "boolean" },
|
|
126
106
|
"no-show-luau": { type: "boolean" },
|
|
127
107
|
"outputFile": { type: "string" },
|
|
@@ -176,7 +156,7 @@ function parseArgs(args) {
|
|
|
176
156
|
affectedSince: values["affected-since"],
|
|
177
157
|
apiKey: values.apiKey,
|
|
178
158
|
backend: validateBackend(values.backend),
|
|
179
|
-
collectCoverage: values.coverage,
|
|
159
|
+
collectCoverage: values["no-coverage"] === true ? false : values.coverage,
|
|
180
160
|
collectCoverageFrom: values.collectCoverageFrom,
|
|
181
161
|
color: values["no-color"] === true ? false : values.color,
|
|
182
162
|
config: values.config,
|
|
@@ -288,6 +268,7 @@ function formatBackendErrorBanner(err) {
|
|
|
288
268
|
const extras = formatChainExtras(entry);
|
|
289
269
|
const label = color.dim(`[${index.toString()}]`);
|
|
290
270
|
body.push(` ${label} ${entry.name}: ${entry.message}${extras}`);
|
|
271
|
+
if (entry.requiredScopes !== void 0) body.push(` ${color.yellow(formatMissingScopes(entry.requiredScopes))}`);
|
|
291
272
|
}
|
|
292
273
|
return formatBanner({
|
|
293
274
|
body,
|