mirror of
https://github.com/unjs/unplugin.git
synced 2025-12-08 20:26:33 +00:00
* loose start for bun plugin * implement bun * support emitFile() * fix Bun cases in integration test * add bun to other test files * remove bun-types-no-globals from github * restore bun-types-no-globals from npm @^1.2 * bun does not yet support .onEnd, so for now we shouldn't fake it with brittle workarounds * add Bun in the documentation * some missing bun references in docs * support multiple plugins * use Bun namespace instead of importing module that won't necessarily exist * Bun is a cute pink color! * fix the transform hook * fix for virtual modules * tidy up * setup bun in ci * revert unplugin require path * ignore bun in test-out folders * update tests * support onEnd * remove * implement guessLoader(), bun also now supports onEnd() * don't eat errors/warnings * we dont need to outdir for bun in this test * bun writebundle test * Update to bun@1.2.22 (supports onEnd and onResolve) * use onStart() * define onStart() in mocks * onStart * ci: run vitest in Bun so we can run bun's tests * Bun error message if building outside of Bun * skip bun specific tests when not running in bun * refactor * allow only * ci: fix typecheck --------- Co-authored-by: Kevin Deng <sxzz@sxzz.moe>
156 lines
4.5 KiB
TypeScript
156 lines
4.5 KiB
TypeScript
import type { UnpluginBuildContext, UnpluginContext, UnpluginOptions, VitePlugin } from 'unplugin'
|
|
import type { Mock } from 'vitest'
|
|
import * as path from 'node:path'
|
|
import { createUnplugin } from 'unplugin'
|
|
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
import { onlyBun } from '../../utils'
|
|
import { build, toArray } from '../utils'
|
|
|
|
function createUnpluginWithCallback(resolveIdCallback: UnpluginOptions['resolveId']) {
|
|
return createUnplugin(() => ({
|
|
name: 'test-plugin',
|
|
resolveId: resolveIdCallback,
|
|
}))
|
|
}
|
|
|
|
// We extract this check because all bundlers should behave the same
|
|
const propsToTest: (keyof (UnpluginContext & UnpluginBuildContext))[] = ['addWatchFile', 'emitFile', 'getWatchFiles', 'parse', 'error', 'warn']
|
|
|
|
function createResolveIdHook(): Mock {
|
|
const mockResolveIdHook = vi.fn(function (this: UnpluginContext & UnpluginBuildContext) {
|
|
for (const prop of propsToTest) {
|
|
expect(this).toHaveProperty(prop)
|
|
expect(this[prop]).toBeInstanceOf(Function)
|
|
}
|
|
})
|
|
return mockResolveIdHook
|
|
}
|
|
|
|
function checkResolveIdHook(resolveIdCallback: Mock): void {
|
|
expect.assertions(4 * (1 + propsToTest.length * 2))
|
|
|
|
expect(resolveIdCallback).toHaveBeenCalledWith(
|
|
expect.stringMatching(/(?:\/|\\)entry\.js$/),
|
|
undefined,
|
|
expect.objectContaining({ isEntry: true }),
|
|
)
|
|
|
|
expect(resolveIdCallback).toHaveBeenCalledWith(
|
|
'./proxy-export',
|
|
expect.stringMatching(/(?:\/|\\)entry\.js$/),
|
|
expect.objectContaining({ isEntry: false }),
|
|
)
|
|
|
|
expect(resolveIdCallback).toHaveBeenCalledWith(
|
|
'./default-export',
|
|
expect.stringMatching(/(?:\/|\\)proxy-export\.js$/),
|
|
expect.objectContaining({ isEntry: false }),
|
|
)
|
|
|
|
expect(resolveIdCallback).toHaveBeenCalledWith(
|
|
'./named-export',
|
|
expect.stringMatching(/(?:\/|\\)proxy-export\.js$/),
|
|
expect.objectContaining({ isEntry: false }),
|
|
)
|
|
}
|
|
|
|
describe('resolveId hook', () => {
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('vite', async () => {
|
|
const mockResolveIdHook = createResolveIdHook()
|
|
const plugin = createUnpluginWithCallback(mockResolveIdHook).vite
|
|
// we need to define `enforce` here for the plugin to be run
|
|
const plugins = toArray(plugin()).map((plugin): VitePlugin => ({ ...plugin, enforce: 'pre' }))
|
|
|
|
await build.vite({
|
|
clearScreen: false,
|
|
plugins: [plugins],
|
|
build: {
|
|
lib: {
|
|
entry: path.resolve(__dirname, 'test-src/entry.js'),
|
|
name: 'TestLib',
|
|
},
|
|
write: false, // don't output anything
|
|
},
|
|
})
|
|
|
|
checkResolveIdHook(mockResolveIdHook)
|
|
})
|
|
|
|
it('rollup', async () => {
|
|
const mockResolveIdHook = createResolveIdHook()
|
|
const plugin = createUnpluginWithCallback(mockResolveIdHook).rollup
|
|
|
|
await build.rollup({
|
|
input: path.resolve(__dirname, 'test-src/entry.js'),
|
|
plugins: [plugin()],
|
|
})
|
|
|
|
checkResolveIdHook(mockResolveIdHook)
|
|
})
|
|
|
|
it('webpack', async () => {
|
|
const mockResolveIdHook = createResolveIdHook()
|
|
const plugin = createUnpluginWithCallback(mockResolveIdHook).webpack
|
|
|
|
await new Promise((resolve) => {
|
|
build.webpack(
|
|
{
|
|
entry: path.resolve(__dirname, 'test-src/entry.js'),
|
|
plugins: [plugin()],
|
|
},
|
|
resolve,
|
|
)
|
|
})
|
|
|
|
checkResolveIdHook(mockResolveIdHook)
|
|
})
|
|
|
|
it('rspack', async () => {
|
|
const mockResolveIdHook = createResolveIdHook()
|
|
const plugin = createUnpluginWithCallback(mockResolveIdHook).rspack
|
|
|
|
await new Promise((resolve) => {
|
|
build.rspack(
|
|
{
|
|
entry: path.resolve(__dirname, 'test-src/entry.js'),
|
|
plugins: [plugin()],
|
|
},
|
|
resolve,
|
|
)
|
|
})
|
|
|
|
checkResolveIdHook(mockResolveIdHook)
|
|
})
|
|
|
|
it('esbuild', async () => {
|
|
const mockResolveIdHook = createResolveIdHook()
|
|
const plugin = createUnpluginWithCallback(mockResolveIdHook).esbuild
|
|
|
|
await build.esbuild({
|
|
entryPoints: [path.resolve(__dirname, 'test-src/entry.js')],
|
|
plugins: [plugin()],
|
|
bundle: true, // actually traverse imports
|
|
write: false, // don't pollute console
|
|
})
|
|
|
|
checkResolveIdHook(mockResolveIdHook)
|
|
})
|
|
|
|
onlyBun('bun', async () => {
|
|
const mockResolveIdHook = createResolveIdHook()
|
|
const plugin = createUnpluginWithCallback(mockResolveIdHook).bun
|
|
|
|
await build.bun({
|
|
entrypoints: [path.resolve(__dirname, 'test-src/entry.js')],
|
|
plugins: [plugin()],
|
|
outdir: path.resolve(__dirname, 'test-out/bun'), // Bun requires outdir
|
|
})
|
|
|
|
checkResolveIdHook(mockResolveIdHook)
|
|
})
|
|
})
|