@vitus-labs/tools-rollup 1.5.2-alpha.4 → 1.6.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitus-labs/tools-rollup",
3
- "version": "1.5.2-alpha.4+45b8634",
3
+ "version": "1.6.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -30,38 +30,39 @@
30
30
  },
31
31
  "scripts": {
32
32
  "prepublish": "bun run build",
33
- "build": "tsc"
33
+ "build": "tsc",
34
+ "typecheck": "tsc --noEmit"
34
35
  },
35
36
  "publishConfig": {
36
37
  "access": "public"
37
38
  },
38
39
  "dependencies": {
39
- "@microsoft/api-extractor": "^7.55.2",
40
+ "@microsoft/api-extractor": "^7.56.3",
40
41
  "@rollup/plugin-node-resolve": "^16.0.3",
41
42
  "@rollup/plugin-replace": "^6.0.3",
42
43
  "@rollup/plugin-terser": "^0.4.4",
43
44
  "@rollup/plugin-typescript": "^12.3.0",
44
- "@types/node": "^25.0.3",
45
- "@vitus-labs/tools-core": "1.5.2-alpha.4+45b8634",
45
+ "@types/node": "^25.2.1",
46
+ "@vitus-labs/tools-core": "1.6.0",
46
47
  "chalk": "^5.6.2",
47
- "find-up": "^7.0.0",
48
- "lodash-es": "^4.17.22",
48
+ "find-up": "^8.0.0",
49
+ "lodash-es": "^4.17.23",
49
50
  "rimraf": "^6.1.2",
50
- "rollup": "^4.55.1",
51
+ "rollup": "^4.57.1",
51
52
  "rollup-plugin-api-extractor": "^0.2.5",
52
53
  "rollup-plugin-filesize": "^10.0.0",
53
54
  "rollup-plugin-tsconfig-paths": "^1.5.2",
54
55
  "rollup-plugin-typescript-paths": "^1.5.0",
55
56
  "rollup-plugin-typescript2": "^0.36.0",
56
- "rollup-plugin-visualizer": "^5.14.0",
57
+ "rollup-plugin-visualizer": "^6.0.5",
57
58
  "ts-patch": "^3.3.0",
58
59
  "tslib": "^2.8.1",
59
60
  "typescript-transform-paths": "^3.5.6"
60
61
  },
61
62
  "devDependencies": {
62
63
  "@types/lodash-es": "^4.17.12",
63
- "@vitus-labs/tools-typescript": "1.5.2-alpha.4+45b8634",
64
+ "@vitus-labs/tools-typescript": "1.6.0",
64
65
  "typescript": "^5.9.3"
65
66
  },
66
- "gitHead": "45b863472eafa888f12f8f56d347dd20b72cd4f9"
67
+ "gitHead": "cb7b3bfa4e5730ecb95b3c886d23074a3ce9e85f"
67
68
  }
@@ -0,0 +1,50 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import config from './baseConfig.js'
3
+
4
+ describe('baseConfig', () => {
5
+ it('should have correct source and output directories', () => {
6
+ expect(config.sourceDir).toBe('src')
7
+ expect(config.outputDir).toBe('lib')
8
+ expect(config.typesDir).toBe('lib/types')
9
+ })
10
+
11
+ it('should have typescript enabled by default', () => {
12
+ expect(config.typescript).toBe(true)
13
+ })
14
+
15
+ it('should have replaceGlobals enabled', () => {
16
+ expect(config.replaceGlobals).toBe(true)
17
+ })
18
+
19
+ it('should define file extensions', () => {
20
+ expect(config.extensions).toContain('.ts')
21
+ expect(config.extensions).toContain('.tsx')
22
+ expect(config.extensions).toContain('.js')
23
+ expect(config.extensions).toContain('.json')
24
+ })
25
+
26
+ it('should have visualise config', () => {
27
+ expect(config.visualise).toEqual({
28
+ template: 'network',
29
+ gzipSize: true,
30
+ outputDir: 'analysis',
31
+ })
32
+ })
33
+
34
+ it('should have filesize enabled', () => {
35
+ expect(config.filesize).toBe(true)
36
+ })
37
+
38
+ it('should have default globals', () => {
39
+ expect(config.globals).toHaveProperty('react', 'React')
40
+ })
41
+
42
+ it('should have external dependencies', () => {
43
+ expect(config.external).toContain('react/jsx-runtime')
44
+ })
45
+
46
+ it('should have exclude patterns', () => {
47
+ expect(config.exclude).toContain('node_modules/**')
48
+ expect(config.exclude).toContain('**/__tests__/**')
49
+ })
50
+ })
@@ -0,0 +1,308 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
2
+
3
+ const {
4
+ mockNodeResolve,
5
+ mockReplace,
6
+ mockTerser,
7
+ mockTypescript,
8
+ mockApiExtractor,
9
+ mockFilesize,
10
+ mockVisualizer,
11
+ mockConfig,
12
+ mockPKG,
13
+ } = vi.hoisted(() => ({
14
+ mockNodeResolve: vi.fn(() => ({ name: 'mock-resolve' })),
15
+ mockReplace: vi.fn(() => ({ name: 'mock-replace' })),
16
+ mockTerser: vi.fn(() => ({ name: 'mock-terser' })),
17
+ mockTypescript: vi.fn(() => ({ name: 'mock-typescript' })),
18
+ mockApiExtractor: vi.fn(() => ({ name: 'mock-api-extractor' })),
19
+ mockFilesize: vi.fn(() => ({ name: 'mock-filesize' })),
20
+ mockVisualizer: vi.fn(() => ({ name: 'mock-visualizer' })),
21
+ mockConfig: {
22
+ sourceDir: 'src',
23
+ outputDir: 'lib',
24
+ typesDir: 'lib/types',
25
+ extensions: ['.ts', '.tsx', '.js'],
26
+ typescript: true,
27
+ replaceGlobals: true,
28
+ visualise: { template: 'network', gzipSize: true, outputDir: 'analysis' },
29
+ filesize: true,
30
+ include: ['src'],
31
+ exclude: ['node_modules/**'],
32
+ external: ['react/jsx-runtime'],
33
+ globals: { react: 'React' },
34
+ } as Record<string, any>,
35
+ mockPKG: {
36
+ name: '@test/pkg',
37
+ version: '1.0.0',
38
+ bundleName: 'testPkg',
39
+ externalDependencies: ['react'],
40
+ } as Record<string, any>,
41
+ }))
42
+
43
+ vi.mock('@rollup/plugin-node-resolve', () => ({
44
+ nodeResolve: mockNodeResolve,
45
+ }))
46
+ vi.mock('@rollup/plugin-replace', () => ({ default: mockReplace }))
47
+ vi.mock('@rollup/plugin-terser', () => ({ default: mockTerser }))
48
+ vi.mock('rollup-plugin-typescript2', () => ({ default: mockTypescript }))
49
+ vi.mock('rollup-plugin-api-extractor', () => ({
50
+ apiExtractor: mockApiExtractor,
51
+ }))
52
+ vi.mock('rollup-plugin-filesize', () => ({ default: mockFilesize }))
53
+ vi.mock('rollup-plugin-visualizer', () => ({ visualizer: mockVisualizer }))
54
+
55
+ vi.mock('node:module', () => ({
56
+ createRequire: vi.fn(() => vi.fn(() => ({}))),
57
+ }))
58
+
59
+ vi.mock('@vitus-labs/tools-core', () => ({
60
+ swapGlobals: (globals: Record<string, string>) =>
61
+ Object.fromEntries(Object.entries(globals).map(([k, v]) => [v, k])),
62
+ }))
63
+
64
+ vi.mock('../config/index.js', () => ({
65
+ CONFIG: mockConfig,
66
+ PKG: mockPKG,
67
+ PLATFORMS: ['browser', 'node', 'web', 'native'],
68
+ }))
69
+
70
+ import rollupConfig from './config.js'
71
+
72
+ const defaultConfig = { ...mockConfig }
73
+ const defaultPKG = { ...mockPKG }
74
+
75
+ describe('rollupConfig', () => {
76
+ beforeEach(() => {
77
+ vi.clearAllMocks()
78
+ Object.assign(mockConfig, defaultConfig)
79
+ Object.assign(mockPKG, defaultPKG)
80
+ })
81
+
82
+ it('should create a valid ES module build config', () => {
83
+ const config = rollupConfig({
84
+ file: 'lib/index.js',
85
+ format: 'es',
86
+ env: 'development',
87
+ platform: 'universal',
88
+ })
89
+
90
+ expect(config.input).toBe('src')
91
+ expect(config.output.file).toBe('lib/index.js')
92
+ expect(config.output.format).toBe('es')
93
+ expect(config.output.sourcemap).toBe(true)
94
+ expect(config.external).toContain('react')
95
+ expect(config.external).toContain('react/jsx-runtime')
96
+ })
97
+
98
+ it('should set named exports for CJS format', () => {
99
+ const config = rollupConfig({
100
+ file: 'lib/index.cjs',
101
+ format: 'cjs',
102
+ env: 'development',
103
+ platform: 'universal',
104
+ })
105
+
106
+ expect(config.output.exports).toBe('named')
107
+ })
108
+
109
+ it('should set name for UMD format', () => {
110
+ const config = rollupConfig({
111
+ file: 'lib/index.umd.js',
112
+ format: 'umd',
113
+ env: 'development',
114
+ platform: 'universal',
115
+ })
116
+
117
+ expect(config.output.name).toBe('testPkg')
118
+ expect(config.output.exports).toBe('named')
119
+ })
120
+
121
+ it('should not set name for ES format', () => {
122
+ const config = rollupConfig({
123
+ file: 'lib/index.js',
124
+ format: 'es',
125
+ env: 'development',
126
+ platform: 'universal',
127
+ })
128
+
129
+ expect(config.output.name).toBeUndefined()
130
+ expect(config.output.exports).toBeUndefined()
131
+ })
132
+
133
+ it('should add platform-specific extensions for known platforms', () => {
134
+ rollupConfig({
135
+ file: 'lib/index.js',
136
+ format: 'es',
137
+ env: 'development',
138
+ platform: 'browser',
139
+ })
140
+
141
+ expect(mockNodeResolve).toHaveBeenCalledWith(
142
+ expect.objectContaining({
143
+ browser: true,
144
+ extensions: expect.arrayContaining(['.browser.ts']),
145
+ }),
146
+ )
147
+ })
148
+
149
+ it('should not add platform extensions for unknown platforms', () => {
150
+ rollupConfig({
151
+ file: 'lib/index.js',
152
+ format: 'es',
153
+ env: 'development',
154
+ platform: 'universal',
155
+ })
156
+
157
+ expect(mockNodeResolve).toHaveBeenCalledWith(
158
+ expect.objectContaining({
159
+ browser: false,
160
+ extensions: expect.not.arrayContaining(['.universal.ts']),
161
+ }),
162
+ )
163
+ })
164
+
165
+ it('should add typescript plugin when enabled', () => {
166
+ rollupConfig({
167
+ file: 'lib/index.js',
168
+ format: 'es',
169
+ env: 'development',
170
+ platform: 'universal',
171
+ })
172
+
173
+ expect(mockTypescript).toHaveBeenCalled()
174
+ })
175
+
176
+ it('should add apiExtractor when typesFilePath is provided', () => {
177
+ rollupConfig({
178
+ file: 'lib/index.js',
179
+ format: 'es',
180
+ env: 'development',
181
+ platform: 'universal',
182
+ typesFilePath: './lib/index.d.ts',
183
+ })
184
+
185
+ expect(mockApiExtractor).toHaveBeenCalled()
186
+ })
187
+
188
+ it('should add replace plugin when replaceGlobals is true', () => {
189
+ rollupConfig({
190
+ file: 'lib/index.js',
191
+ format: 'es',
192
+ env: 'development',
193
+ platform: 'node',
194
+ })
195
+
196
+ expect(mockReplace).toHaveBeenCalledWith(
197
+ expect.objectContaining({
198
+ preventAssignment: true,
199
+ values: expect.objectContaining({
200
+ __VERSION__: '"1.0.0"',
201
+ __NODE__: 'true',
202
+ }),
203
+ }),
204
+ )
205
+ })
206
+
207
+ it('should add process.env.NODE_ENV for production', () => {
208
+ rollupConfig({
209
+ file: 'lib/index.js',
210
+ format: 'es',
211
+ env: 'production',
212
+ platform: 'universal',
213
+ })
214
+
215
+ expect(mockReplace).toHaveBeenCalledWith(
216
+ expect.objectContaining({
217
+ values: expect.objectContaining({
218
+ 'process.env.NODE_ENV': '"production"',
219
+ }),
220
+ }),
221
+ )
222
+ })
223
+
224
+ it('should add terser for production builds', () => {
225
+ rollupConfig({
226
+ file: 'lib/index.js',
227
+ format: 'es',
228
+ env: 'production',
229
+ platform: 'universal',
230
+ })
231
+
232
+ expect(mockTerser).toHaveBeenCalled()
233
+ })
234
+
235
+ it('should not add terser for development builds', () => {
236
+ rollupConfig({
237
+ file: 'lib/index.js',
238
+ format: 'es',
239
+ env: 'development',
240
+ platform: 'universal',
241
+ })
242
+
243
+ expect(mockTerser).not.toHaveBeenCalled()
244
+ })
245
+
246
+ it('should skip replace plugin when replaceGlobals is false', () => {
247
+ mockConfig.replaceGlobals = false
248
+
249
+ rollupConfig({
250
+ file: 'lib/index.js',
251
+ format: 'es',
252
+ env: 'development',
253
+ platform: 'universal',
254
+ })
255
+
256
+ expect(mockReplace).not.toHaveBeenCalled()
257
+ })
258
+
259
+ it('should skip typescript plugin when disabled', () => {
260
+ mockConfig.typescript = false
261
+
262
+ rollupConfig({
263
+ file: 'lib/index.js',
264
+ format: 'es',
265
+ env: 'development',
266
+ platform: 'universal',
267
+ })
268
+
269
+ expect(mockTypescript).not.toHaveBeenCalled()
270
+ })
271
+
272
+ it('should skip visualizer when visualise is false', () => {
273
+ mockConfig.visualise = false
274
+
275
+ rollupConfig({
276
+ file: 'lib/index.js',
277
+ format: 'es',
278
+ env: 'development',
279
+ platform: 'universal',
280
+ })
281
+
282
+ expect(mockVisualizer).not.toHaveBeenCalled()
283
+ })
284
+
285
+ it('should skip filesize when disabled', () => {
286
+ mockConfig.filesize = false
287
+
288
+ rollupConfig({
289
+ file: 'lib/index.js',
290
+ format: 'es',
291
+ env: 'development',
292
+ platform: 'universal',
293
+ })
294
+
295
+ expect(mockFilesize).not.toHaveBeenCalled()
296
+ })
297
+
298
+ it('should swap globals in output', () => {
299
+ const config = rollupConfig({
300
+ file: 'lib/index.js',
301
+ format: 'es',
302
+ env: 'development',
303
+ platform: 'universal',
304
+ })
305
+
306
+ expect(config.output.globals).toEqual({ React: 'react' })
307
+ })
308
+ })
@@ -0,0 +1,214 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
2
+
3
+ const { mockPKG } = vi.hoisted(() => ({
4
+ mockPKG: {
5
+ type: 'commonjs',
6
+ name: '@test/pkg',
7
+ main: 'lib/index.cjs',
8
+ module: 'lib/index.js',
9
+ exports: {
10
+ import: './lib/index.js',
11
+ require: './lib/index.cjs',
12
+ types: './lib/index.d.ts',
13
+ },
14
+ } as Record<string, any>,
15
+ }))
16
+
17
+ vi.mock('../config/index.js', () => ({
18
+ PKG: mockPKG,
19
+ CONFIG: {},
20
+ PLATFORMS: ['browser', 'node', 'web', 'native'],
21
+ }))
22
+
23
+ describe('createBuildPipeline', () => {
24
+ const defaultPKG = { ...mockPKG, exports: { ...mockPKG.exports } }
25
+
26
+ beforeEach(() => {
27
+ Object.assign(mockPKG, defaultPKG)
28
+ mockPKG.exports = { ...defaultPKG.exports }
29
+ for (const key of Object.keys(mockPKG)) {
30
+ if (!(key in defaultPKG)) delete mockPKG[key]
31
+ }
32
+ })
33
+
34
+ describe('with CJS package', () => {
35
+ let createBuildPipeline: () => any[]
36
+
37
+ beforeEach(async () => {
38
+ vi.resetModules()
39
+ mockPKG.type = 'commonjs'
40
+ const mod = await import('./createBuildPipeline.js')
41
+ createBuildPipeline = mod.default
42
+ })
43
+
44
+ it('should create builds from package.json fields', () => {
45
+ const builds = createBuildPipeline()
46
+
47
+ expect(builds.length).toBeGreaterThan(0)
48
+ const mainBuild = builds.find((b) => b.file === 'lib/index.cjs')
49
+ expect(mainBuild).toBeDefined()
50
+ expect(mainBuild.format).toBe('cjs')
51
+ })
52
+
53
+ it('should include module build as ES format', () => {
54
+ const builds = createBuildPipeline()
55
+
56
+ const moduleBuild = builds.find((b) => b.file === 'lib/index.js')
57
+ expect(moduleBuild).toBeDefined()
58
+ expect(moduleBuild.format).toBe('es')
59
+ })
60
+
61
+ it('should add typesFilePath to the first build', () => {
62
+ const builds = createBuildPipeline()
63
+
64
+ expect(builds[0].typesFilePath).toBe('./lib/index.d.ts')
65
+ })
66
+ })
67
+
68
+ describe('with ES module package', () => {
69
+ let createBuildPipeline: () => any[]
70
+
71
+ beforeEach(async () => {
72
+ vi.resetModules()
73
+ mockPKG.type = 'module'
74
+ const mod = await import('./createBuildPipeline.js')
75
+ createBuildPipeline = mod.default
76
+ })
77
+
78
+ it('should use ES format for main build', () => {
79
+ const builds = createBuildPipeline()
80
+
81
+ const mainBuild = builds.find((b) => b.file === 'lib/index.cjs')
82
+ if (mainBuild) {
83
+ expect(mainBuild.format).toBe('es')
84
+ }
85
+ })
86
+
87
+ it('should include exports options for ES module packages', () => {
88
+ const builds = createBuildPipeline()
89
+
90
+ expect(builds.length).toBeGreaterThan(0)
91
+ })
92
+ })
93
+
94
+ describe('with string exports', () => {
95
+ let createBuildPipeline: () => any[]
96
+
97
+ beforeEach(async () => {
98
+ vi.resetModules()
99
+ mockPKG.type = 'module'
100
+ mockPKG.exports = './lib/index.js'
101
+ const mod = await import('./createBuildPipeline.js')
102
+ createBuildPipeline = mod.default
103
+ })
104
+
105
+ it('should handle string exports', () => {
106
+ const builds = createBuildPipeline()
107
+
108
+ const exportBuild = builds.find((b) => b.file === './lib/index.js')
109
+ expect(exportBuild).toBeDefined()
110
+ expect(exportBuild.format).toBe('es')
111
+ })
112
+ })
113
+
114
+ describe('with object exports having node and default fields', () => {
115
+ let createBuildPipeline: () => any[]
116
+
117
+ beforeEach(async () => {
118
+ vi.resetModules()
119
+ mockPKG.type = 'module'
120
+ mockPKG.exports = {
121
+ import: './lib/index.js',
122
+ require: './lib/index.cjs',
123
+ node: './lib/node.js',
124
+ default: './lib/default.js',
125
+ types: './lib/index.d.ts',
126
+ }
127
+ const mod = await import('./createBuildPipeline.js')
128
+ createBuildPipeline = mod.default
129
+ })
130
+
131
+ it('should include node and default exports', () => {
132
+ const builds = createBuildPipeline()
133
+
134
+ const nodeBuild = builds.find((b) => b.file === './lib/node.js')
135
+ expect(nodeBuild).toBeDefined()
136
+ expect(nodeBuild.platform).toBe('node')
137
+
138
+ const defaultBuild = builds.find((b) => b.file === './lib/default.js')
139
+ expect(defaultBuild).toBeDefined()
140
+ })
141
+ })
142
+
143
+ describe('with no exports', () => {
144
+ let createBuildPipeline: () => any[]
145
+
146
+ beforeEach(async () => {
147
+ vi.resetModules()
148
+ mockPKG.type = 'module'
149
+ delete mockPKG.exports
150
+ const mod = await import('./createBuildPipeline.js')
151
+ createBuildPipeline = mod.default
152
+ })
153
+
154
+ it('should return builds based on main/module fields only', () => {
155
+ const builds = createBuildPipeline()
156
+
157
+ expect(builds.length).toBeGreaterThan(0)
158
+ })
159
+ })
160
+
161
+ describe('with react-native build', () => {
162
+ let createBuildPipeline: () => any[]
163
+
164
+ beforeEach(async () => {
165
+ vi.resetModules()
166
+ mockPKG.type = 'commonjs'
167
+ mockPKG['react-native'] = 'lib/native.js'
168
+ mockPKG.module = 'lib/index.js'
169
+ const mod = await import('./createBuildPipeline.js')
170
+ createBuildPipeline = mod.default
171
+ })
172
+
173
+ it('should add native build when path differs from module', () => {
174
+ const builds = createBuildPipeline()
175
+
176
+ const nativeBuild = builds.find((b) => b.platform === 'native')
177
+ expect(nativeBuild).toBeDefined()
178
+ expect(nativeBuild.file).toBe('lib/native.js')
179
+ })
180
+ })
181
+
182
+ describe('with browser-specific builds', () => {
183
+ let createBuildPipeline: () => any[]
184
+
185
+ beforeEach(async () => {
186
+ vi.resetModules()
187
+ mockPKG.type = 'commonjs'
188
+ mockPKG.main = 'lib/index.cjs'
189
+ mockPKG.module = 'lib/index.js'
190
+ mockPKG.browser = {
191
+ './lib/index.js': './lib/browser.js',
192
+ }
193
+ const mod = await import('./createBuildPipeline.js')
194
+ createBuildPipeline = mod.default
195
+ })
196
+
197
+ it('should create browser-specific build variants', () => {
198
+ const builds = createBuildPipeline()
199
+
200
+ const browserBuild = builds.find((b) => b.platform === 'browser')
201
+ expect(browserBuild).toBeDefined()
202
+ expect(browserBuild.file).toBe('lib/browser.js')
203
+ })
204
+
205
+ it('should set node platform for main build when browser variant exists', () => {
206
+ const builds = createBuildPipeline()
207
+
208
+ const nodeBuild = builds.find(
209
+ (b) => b.file === 'lib/index.cjs' && b.platform === 'node',
210
+ )
211
+ expect(nodeBuild).toBeDefined()
212
+ })
213
+ })
214
+ })
@@ -0,0 +1,107 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
2
+
3
+ const {
4
+ mockRollup,
5
+ mockBundleWrite,
6
+ mockCreateBuildPipeline,
7
+ mockRollupConfig,
8
+ } = vi.hoisted(() => ({
9
+ mockRollup: vi.fn(),
10
+ mockBundleWrite: vi.fn(),
11
+ mockCreateBuildPipeline: vi.fn(),
12
+ mockRollupConfig: vi.fn(),
13
+ }))
14
+
15
+ vi.mock('rollup', () => ({ rollup: mockRollup }))
16
+ vi.mock('rimraf', () => ({ rimraf: { sync: vi.fn() } }))
17
+
18
+ vi.mock('../config/index.js', () => ({
19
+ CONFIG: { outputDir: 'lib' },
20
+ }))
21
+
22
+ vi.mock('../rollup/index.js', () => ({
23
+ createBuildPipeline: mockCreateBuildPipeline,
24
+ config: mockRollupConfig,
25
+ }))
26
+
27
+ describe('build', () => {
28
+ beforeEach(() => {
29
+ vi.clearAllMocks()
30
+
31
+ mockBundleWrite.mockResolvedValue(undefined)
32
+ mockRollup.mockResolvedValue({ write: mockBundleWrite })
33
+
34
+ mockCreateBuildPipeline.mockReturnValue([
35
+ {
36
+ file: 'lib/index.js',
37
+ format: 'es',
38
+ env: 'development',
39
+ platform: 'universal',
40
+ },
41
+ ])
42
+ mockRollupConfig.mockImplementation((item: any) => ({
43
+ input: 'src',
44
+ output: { file: item.file, format: item.format },
45
+ }))
46
+ })
47
+
48
+ it('should execute build pipeline successfully', async () => {
49
+ vi.resetModules()
50
+ const { runBuild } = await import('./build.js')
51
+
52
+ await runBuild()
53
+
54
+ expect(mockRollup).toHaveBeenCalled()
55
+ expect(mockBundleWrite).toHaveBeenCalled()
56
+ })
57
+
58
+ it('should handle build failure gracefully', async () => {
59
+ const buildError = new Error('rollup failed')
60
+ mockRollup.mockRejectedValue(buildError)
61
+
62
+ vi.resetModules()
63
+ const { runBuild } = await import('./build.js')
64
+ vi.clearAllMocks()
65
+
66
+ mockRollup.mockRejectedValue(buildError)
67
+ mockRollupConfig.mockImplementation((item: any) => ({
68
+ input: 'src',
69
+ output: { file: item.file, format: item.format },
70
+ }))
71
+
72
+ await expect(runBuild()).rejects.toThrow('rollup failed')
73
+ })
74
+
75
+ it('should handle multiple builds in sequence', async () => {
76
+ mockCreateBuildPipeline.mockReturnValue([
77
+ {
78
+ file: 'lib/index.js',
79
+ format: 'es',
80
+ env: 'development',
81
+ platform: 'universal',
82
+ },
83
+ {
84
+ file: 'lib/index.cjs',
85
+ format: 'cjs',
86
+ env: 'development',
87
+ platform: 'universal',
88
+ },
89
+ ])
90
+
91
+ vi.resetModules()
92
+ const { runBuild } = await import('./build.js')
93
+ vi.clearAllMocks()
94
+
95
+ // Re-setup after clear
96
+ mockRollup.mockResolvedValue({ write: mockBundleWrite })
97
+ mockBundleWrite.mockResolvedValue(undefined)
98
+ mockRollupConfig.mockImplementation((item: any) => ({
99
+ input: 'src',
100
+ output: { file: item.file, format: item.format },
101
+ }))
102
+
103
+ await runBuild()
104
+
105
+ expect(mockRollupConfig).toHaveBeenCalledTimes(2)
106
+ })
107
+ })
package/tsconfig.json CHANGED
@@ -11,5 +11,5 @@
11
11
  }
12
12
  },
13
13
  "include": ["typings", "src"],
14
- "exclude": ["node_modules", "__stories__", "lib"]
14
+ "exclude": ["node_modules", "__stories__", "lib", "**/*.test.ts"]
15
15
  }
@@ -0,0 +1,3 @@
1
+ import { createVitestConfig } from '../../vitest.shared.js'
2
+
3
+ export default createVitestConfig(['src/config/baseConfig.ts'])