|
| 1 | +# Testing |
| 2 | + |
| 3 | +Rstack uses [Rstest](https://rstest.rs/) for testing. The value passed to `define.test()` is an Rstest configuration, similar to using Rstest's `defineConfig()` directly. |
| 4 | + |
| 5 | +Test APIs and configuration helpers are available from `rstack/test`: |
| 6 | + |
| 7 | +```ts |
| 8 | +import { defineInlineProject, expect, test } from 'rstack/test'; |
| 9 | +``` |
| 10 | + |
| 11 | +## Single project |
| 12 | + |
| 13 | +For a single test project, pass the Rstest options directly: |
| 14 | + |
| 15 | +```ts title="rstack.config.ts" |
| 16 | +import { define } from 'rstack'; |
| 17 | + |
| 18 | +define.app({ |
| 19 | + // Rsbuild configuration |
| 20 | +}); |
| 21 | + |
| 22 | +define.test({ |
| 23 | + testEnvironment: 'happy-dom', |
| 24 | + setupFiles: ['./tests/rstest.setup.ts'], |
| 25 | +}); |
| 26 | +``` |
| 27 | + |
| 28 | +Unless `extends` is provided explicitly, Rstack automatically extends the test configuration from `define.app()`. If there is no app configuration, it falls back to `define.lib()`. |
| 29 | + |
| 30 | +## Inline projects |
| 31 | + |
| 32 | +Use Rstest inline projects when one app or library needs multiple test configurations, such as separate Node.js and DOM test environments: |
| 33 | + |
| 34 | +```ts title="rstack.config.ts" |
| 35 | +import { define } from 'rstack'; |
| 36 | +import { defineInlineProject } from 'rstack/test'; |
| 37 | + |
| 38 | +define.app({ |
| 39 | + // Shared by both inline projects |
| 40 | +}); |
| 41 | + |
| 42 | +define.test({ |
| 43 | + coverage: { |
| 44 | + enabled: true, |
| 45 | + }, |
| 46 | + projects: [ |
| 47 | + defineInlineProject({ |
| 48 | + name: 'node', |
| 49 | + include: ['./tests/node/**/*.test.ts'], |
| 50 | + testEnvironment: 'node', |
| 51 | + }), |
| 52 | + defineInlineProject({ |
| 53 | + name: 'dom', |
| 54 | + include: ['./tests/dom/**/*.test.tsx'], |
| 55 | + testEnvironment: 'happy-dom', |
| 56 | + setupFiles: ['./tests/rstest.setup.ts'], |
| 57 | + }), |
| 58 | + ], |
| 59 | +}); |
| 60 | +``` |
| 61 | + |
| 62 | +Rstack applies the shared `define.app()` or `define.lib()` adapter to every inline project that does not define its own `extends`. Function-based app or library configuration is resolved once and shared by all inline projects. |
| 63 | + |
| 64 | +Run all projects: |
| 65 | + |
| 66 | +```bash |
| 67 | +rs test |
| 68 | +``` |
| 69 | + |
| 70 | +Run one project by name: |
| 71 | + |
| 72 | +```bash |
| 73 | +rs test --project dom |
| 74 | +``` |
| 75 | + |
| 76 | +See [`examples/rstest-inline-projects`](https://github.com/rstackjs/rstack-cli/tree/main/examples/rstest-inline-projects) for a complete example that tests React server rendering in Node.js and client rendering in happy-dom. |
| 77 | + |
| 78 | +## Custom `extends` |
| 79 | + |
| 80 | +An inline project can opt out of automatic app or library inheritance by providing `extends` explicitly: |
| 81 | + |
| 82 | +```ts |
| 83 | +import { defineInlineProject } from 'rstack/test'; |
| 84 | + |
| 85 | +const customProject = defineInlineProject({ |
| 86 | + name: 'custom', |
| 87 | + extends: customAdapter(), |
| 88 | +}); |
| 89 | +``` |
| 90 | + |
| 91 | +If the root `define.test()` configuration provides `extends`, Rstack leaves the complete test configuration unchanged. |
| 92 | + |
| 93 | +## External projects |
| 94 | + |
| 95 | +String project entries are passed to Rstest unchanged: |
| 96 | + |
| 97 | +```ts |
| 98 | +import { define } from 'rstack'; |
| 99 | + |
| 100 | +define.test({ |
| 101 | + projects: ['./legacy/rstest.config.ts'], |
| 102 | +}); |
| 103 | +``` |
| 104 | + |
| 105 | +External string projects load their own Rstest configuration and do not inherit the current `define.app()` or `define.lib()` configuration. Use inline projects when projects should share the current Rstack build configuration. |
0 commit comments