import { describe, expect, it } from 'vitest'; import * as fs from 'node:fs'; import * as os from 'node:os'; import * as path from 'node:path'; import { fileURLToPath } from 'node:url'; import { build } from 'vite'; import { bgm } from '@tts/bgm'; const fixtureRoot = path.resolve( path.dirname(fileURLToPath(import.meta.url)), '__fixtures__', 'vite-build', ); const gamesRoot = path.join(fixtureRoot, 'games'); describe('tabletop vite build (integration)', () => { it('bundles the library logic against a fixture package', async () => { const outDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'tabletop-build-')); try { await build({ root: fixtureRoot, logLevel: 'silent', build: { outDir, write: true, emptyOutDir: true, // Keep identifiers readable so the test can assert on them. minify: false, }, plugins: [bgm({ root: gamesRoot })], }); const chunk = walk(outDir).find((f) => f.endsWith('.js'))!; const code = fs.readFileSync(path.join(outDir, chunk), 'utf8'); // The bgm plugin serialized the package's parts and setup into the // emitted module, and the library's logic is bundled alongside. expect(code).toContain('token#wood'); expect(code).toContain('game#main'); // The library's pure logic (setup seeding, render state, stacking, // mount resolution) is reachable from the fixture entry. expect(code).toContain('placementCount'); expect(code).toContain('offsetX'); expect(code).toContain('worldCount'); } finally { await fs.promises.rm(outDir, { recursive: true, force: true }); } }); }); /** Recursively list files under a directory, as paths relative to it. */ function walk(dir: string): string[] { const out: string[] = []; const visit = (current: string) => { for (const entry of fs.readdirSync(current, { withFileTypes: true })) { const full = path.join(current, entry.name); if (entry.isDirectory()) visit(full); else out.push(path.relative(dir, full)); } }; visit(dir); return out; }