feat: add feature plugin tests and validation for feature flags
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { dirname, resolve } from 'node:path'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { mkdtempSync, readFileSync, readdirSync, rmSync } from 'node:fs'
|
||||
import { dirname, join, resolve } from 'node:path'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
||||
import { publicLayersPlugin } from '../src/public'
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url))
|
||||
@@ -8,30 +10,65 @@ const fixture = (p: string) => resolve(here, 'fixtures', p)
|
||||
|
||||
const callConfig = (p: { config?: unknown }) => (p.config as () => unknown)()
|
||||
|
||||
function runGenerateBundle(p: { generateBundle?: unknown }): Record<string, string> {
|
||||
const emitted: Record<string, string> = {}
|
||||
const ctx = {
|
||||
emitFile: ({ fileName, source }: { fileName: string; source: Buffer | string }) => {
|
||||
emitted[fileName] = source.toString()
|
||||
},
|
||||
type ResolvedishConfig = { root: string; build: { outDir: string; copyPublicDir?: boolean } }
|
||||
|
||||
/** List every file written under `dir` as `posixRelativePath → contents`. */
|
||||
function snapshot(dir: string): Record<string, string> {
|
||||
const out: Record<string, string> = {}
|
||||
const walk = (d: string) => {
|
||||
for (const name of readdirSync(d, { withFileTypes: true })) {
|
||||
const abs = join(d, name.name)
|
||||
if (name.isDirectory()) walk(abs)
|
||||
else out[resolve(abs).slice(resolve(dir).length + 1).replace(/\\/g, '/')] = readFileSync(abs, 'utf8')
|
||||
}
|
||||
}
|
||||
;(p.generateBundle as (this: unknown, ...a: unknown[]) => void).call(ctx, {}, {}, false)
|
||||
return emitted
|
||||
walk(dir)
|
||||
return out
|
||||
}
|
||||
|
||||
/** Drive the build-time hooks (configResolved → writeBundle) and return what landed on disk. */
|
||||
function runBuild(
|
||||
p: { configResolved?: unknown; writeBundle?: unknown },
|
||||
outDir: string,
|
||||
{ copyPublicDir, writeDir }: { copyPublicDir?: boolean; writeDir?: string } = {},
|
||||
): Record<string, string> {
|
||||
const cfg: ResolvedishConfig = { root: '/', build: { outDir, copyPublicDir } }
|
||||
;(p.configResolved as (c: ResolvedishConfig) => void)(cfg)
|
||||
;(p.writeBundle as (this: unknown, o: { dir?: string }) => void).call({}, { dir: writeDir ?? outDir })
|
||||
return snapshot(outDir)
|
||||
}
|
||||
|
||||
describe('publicLayersPlugin', () => {
|
||||
const high = fixture('public/high/public')
|
||||
const low = fixture('public/low/public')
|
||||
let outDir: string
|
||||
|
||||
beforeEach(() => {
|
||||
outDir = mkdtempSync(join(tmpdir(), 'vite-layers-public-'))
|
||||
})
|
||||
afterEach(() => {
|
||||
rmSync(outDir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
it('disables Vite publicDir when layers have public/, otherwise no-op', () => {
|
||||
expect(callConfig(publicLayersPlugin([high, low]))).toEqual({ publicDir: false })
|
||||
expect(callConfig(publicLayersPlugin([fixture('public/none/public')]))).toBeUndefined()
|
||||
})
|
||||
|
||||
it('emits assets first-match-wins (higher overrides, lower fills gaps, nested ok)', () => {
|
||||
const emitted = runGenerateBundle(publicLayersPlugin([high, low]))
|
||||
expect(emitted['logo.svg']).toBe('HIGH_LOGO') // overridden by the higher layer
|
||||
expect(emitted['shared.txt']).toBe('LOW_SHARED') // inherited from the lower layer
|
||||
expect(emitted['img/icon.svg']).toBe('LOW_ICON') // nested, from the lower layer
|
||||
it('copies assets first-match-wins (higher overrides, lower fills gaps, nested ok)', () => {
|
||||
const written = runBuild(publicLayersPlugin([high, low]), outDir)
|
||||
expect(written['logo.svg']).toBe('HIGH_LOGO') // overridden by the higher layer
|
||||
expect(written['shared.txt']).toBe('LOW_SHARED') // inherited from the lower layer
|
||||
expect(written['img/icon.svg']).toBe('LOW_ICON') // nested, from the lower layer
|
||||
})
|
||||
|
||||
it('skips the copy when Vite opts out (copyPublicDir: false)', () => {
|
||||
const written = runBuild(publicLayersPlugin([high, low]), outDir, { copyPublicDir: false })
|
||||
expect(written).toEqual({})
|
||||
})
|
||||
|
||||
it('only copies for the output targeting the main outDir', () => {
|
||||
const written = runBuild(publicLayersPlugin([high, low]), outDir, { writeDir: join(outDir, 'server') })
|
||||
expect(written).toEqual({})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user