-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrstest.rslib.ts
More file actions
159 lines (151 loc) · 8.4 KB
/
Copy pathrstest.rslib.ts
File metadata and controls
159 lines (151 loc) · 8.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import { resolve } from 'node:path';
import { withRslibConfig, type WithRslibConfigOptions } from '@rstest/adapter-rslib';
import type { ExtendConfig, ExtendConfigFn } from '@rstest/core';
import { agentBundleLibId } from './packages/agent-bundle/rslib.config.ts';
const workspaceRoot = import.meta.dirname;
const packageRoot = resolve(workspaceRoot, 'packages/agent-bundle');
/**
* Plugins `packages/agent-bundle/rslib.config.ts` registers for publishing
* the package, not for compiling its modules. The adapter copies the lib
* config's `plugins` into every pool verbatim, so without this filter they
* would run inside each test bundle:
*
* - `plugin-publint` (rsbuild-plugin-publint, `throwOn: 'warning'`) audits
* the manifest at `api.context.rootPath` in `onAfterBuild` — under the
* pools that would be the workspace root's private `package.json`, and a
* test build has no manifest to gate. Rstest 0.11 never drives
* `onAfterBuild` (DEBUG=rstest shows no publint output), so today the
* registration is inert; it stays out so a runner change cannot arm it.
*
* The `__filename`/`__dirname` shim for the inlined TypeScript 5 parser is
* the lib entries' `shims.esm`, a field the adapter never reads (below), so
* nothing filters it: pools leave dependencies external, and Rstest supplies
* the real `__dirname` and `__filename` of each test module itself.
*
* Verify the names against the plugin objects, not the package names:
* `pluginPublint().name` is `plugin-publint`.
*/
const publishOnlyPlugins: ReadonlySet<string> = new Set(['plugin-publint']);
/** The `name` of an Rsbuild plugin entry; nested arrays, promises, and falsy entries have none. */
const pluginName = (plugin: unknown): string | undefined => (
typeof plugin === 'object' && plugin !== null && 'name' in plugin && typeof plugin.name === 'string'
? plugin.name
: undefined
);
/**
* Per-test restoration shared by every pool. The unit pool runs with
* `isolate: false`, so a mock, `rs.stubEnv`, or `rs.stubGlobal` a test leaves
* behind is the next file's problem; restoring before each test makes file
* order irrelevant. Rstest dispatches `restoreMocks` ahead of `clearMocks`
* (its `mockRestore` is `mockReset` plus the original implementation, so
* calls are cleared too); `clearMocks` stays listed as the floor should
* `restoreMocks` ever be relaxed.
*/
export const rstestHygiene = {
clearMocks: true,
restoreMocks: true,
unstubEnvs: true,
unstubGlobals: true,
} as const satisfies ExtendConfig;
/**
* What `packages/agent-bundle/rslib.config.ts` becomes under the adapter —
* `withRslibConfig` in @rstest/adapter-rslib 0.11.12 (dist/index.js),
* verified against its source, since the adapter documents none of it.
*
* The lib entry is found by `libId` (line 53: `lib.find((l) => l.id ===
* libId) || {}`); without a `libId`, or with one no entry carries, the entry
* is silently `{}` and only the top-level fields count. That is why the entry
* has an `id` and these options pass it: a field moved into the selected
* public entry — `output.target`, `source.define` — would otherwise vanish
* from every pool without a diagnostic. Of the entry, only `source`,
* `output`, `tools`, `plugins`, and `resolve` are merged over the top-level
* config (lines 54-61); `format` is read once more, directly, as the fallback
* for `output.module` (line 105).
*
* Mapped into the pool config (lines 69-120), after `modifyLibConfig`:
*
* | Rslib config | Rstest config |
* | -------------------------------------------- | -------------------------------------- |
* | `root` | `root` |
* | `plugins` | `plugins`, verbatim, plus the |
* | | adapter's own entry that removes |
* | | `rsbuild:dts` and `rsbuild:type-check` |
* | `source.define`, `source.tsconfigPath` | the same keys (also `assetsInclude`, |
* | | `decorators`, `include`, `exclude`, |
* | | `transformImport`) |
* | `resolve` | `resolve`, verbatim |
* | `output.module`, else lib `format !== 'cjs'` | `output.module` (`true` is ESM) |
* | `output.target` | `testEnvironment`: `web` becomes |
* | | `happy-dom`, anything else `node` |
* | | (line 119) |
* | `output.cssModules` | `output.cssModules` |
* | `performance.buildCache` | `performance.buildCache`, its |
* | | `buildDependencies` resolved against |
* | | the config file, which is appended |
* | `tools.rspack`, `tools.swc`, | the same keys |
* | `tools.bundlerChain` | |
* | the config file's path | `forceRerunTriggers` |
* | the `libId` option | `name` (line 75; dropped below) |
*
* Never read: every other lib-entry field — `bundle`, `dts`, `syntax`, and
* would-be `autoExternal`, `autoExtension`, `redirect`, `shims`, `banner`,
* `footer`, `umdName`, `outBase`, `experiments` — and, top-level,
* `source.entry`, `output.{cleanDistPath,copy,filenameHash,legalComments}`
* (likewise `output.externals`, `distPath`, `minify`, `sourceMap`), any
* `tools.*` beyond the three above, any `performance.*` beyond `buildCache`,
* `mode`, `logLevel`, `dev`, `server`. Pools therefore leave every dependency
* external — Rstest's default for `testEnvironment: 'node'` — where the
* package build's `autoExternal` bundles devDependencies (the TypeScript
* parser, #381). One probe escapes `modifyLibConfig`: when the pool sets
* neither `source.tsconfigPath` nor `source.decorators.version` and the lib
* sets no `source.decorators.version`, the adapter reads the tsconfig the lib
* names (`tsconfig.build.json`, before the repointing below) for
* `experimentalDecorators` (lines 62-67); it feeds nothing else.
*
* `modifyLibConfig` keeps `source.define` — `__AGENT_BUNDLE_VERSION__` in
* src/cli.ts is a compile-time identifier and resolves here exactly as in the
* published build — and `source.tsconfigPath`, repointed at the workspace
* tsconfig so test files resolve beside the sources. It drops the
* publish-only plugins above and `tools.rspack`, whose `ignoreWarnings` entry
* exists for the inlined TypeScript parser (external in pools).
*
* Exported so rstest-rslib-adapter.test.ts can hold `libId` against the
* config's lib entries: the resolved config cannot show whether the lookup
* matched, because a miss yields `{}` and this config's entry adds nothing
* the top level lacks.
*/
export const agentBundleRslibAdapterOptions = {
cwd: packageRoot,
libId: agentBundleLibId,
modifyLibConfig: ({ plugins, tools, ...config }) => {
const { rspack: _publishOnlyRspack, ...testTools } = tools ?? {};
return {
...config,
root: workspaceRoot,
plugins: plugins?.filter((plugin) => {
const name = pluginName(plugin);
return name === undefined || !publishOnlyPlugins.has(name);
}),
source: {
...config.source,
tsconfigPath: resolve(workspaceRoot, 'tsconfig.json'),
},
tools: testTools,
};
},
} satisfies WithRslibConfigOptions;
/**
* The shared pool configuration: the package's Rslib build config, reduced to
* what compiling tests needs (`agentBundleRslibAdapterOptions`), plus
* `rstestHygiene`, minus the `name` the adapter derives from `libId` — a
* project name labels GitHub step summaries and answers `--project`, and
* `esm-node` describes the build, not a pool, so the pools keep Rstest's
* default (`rstest`).
*/
export const withAgentBundleRslibConfig = (): ExtendConfigFn => {
const rslib = withRslibConfig(agentBundleRslibAdapterOptions);
return async (userConfig) => {
const { name: _libId, ...config } = await rslib(userConfig);
return { ...config, ...rstestHygiene };
};
};