test(bgm): cover emitted shape and multi-package collection
Add a SerializedPackage type for the JSON the plugin emits, and tests that assert the maps serialize to plain objects, that the packages module returns every package, and that buildStart watches def files. Add a second fixture package to exercise multi-package collection.
This commit is contained in:
@@ -23,6 +23,12 @@ function load(plugin: ReturnType<typeof bgm>, id: string): unknown {
|
||||
return (plugin.load as Callable<typeof plugin.load>)(id, { ssr: false });
|
||||
}
|
||||
|
||||
/** Parse the JSON payload out of an emitted `export default <json>` module. */
|
||||
function parseModule(code: unknown): unknown {
|
||||
expect(String(code).startsWith('export default ')).toBe(true);
|
||||
return JSON.parse(String(code).slice('export default '.length));
|
||||
}
|
||||
|
||||
describe('bgm vite plugin', () => {
|
||||
it('resolves bgm imports to the virtual module', () => {
|
||||
const plugin = bgm({ root: gamesRoot });
|
||||
@@ -34,10 +40,7 @@ describe('bgm vite plugin', () => {
|
||||
|
||||
it('loads every package as a JSON module', () => {
|
||||
const plugin = bgm({ root: gamesRoot });
|
||||
const code = load(plugin, '\0bgm:virtual:bgm/packages');
|
||||
expect(code).toBeDefined();
|
||||
expect(String(code).startsWith('export default ')).toBe(true);
|
||||
const packages = JSON.parse(String(code).slice('export default '.length));
|
||||
const packages = parseModule(load(plugin, '\0bgm:virtual:bgm/packages')) as Array<Record<string, any>>;
|
||||
expect(packages).toHaveLength(1);
|
||||
expect(packages[0].meta.id).toBe('harbor');
|
||||
expect(packages[0].parts).toHaveProperty('token#wood');
|
||||
@@ -45,17 +48,45 @@ describe('bgm vite plugin', () => {
|
||||
|
||||
it('loads a package as a JSON module', () => {
|
||||
const plugin = bgm({ root: gamesRoot });
|
||||
const code = load(plugin, '\0bgm:virtual:bgm/package/harbor');
|
||||
expect(code).toBeDefined();
|
||||
expect(String(code).startsWith('export default ')).toBe(true);
|
||||
const pkg = JSON.parse(String(code).slice('export default '.length));
|
||||
const pkg = parseModule(load(plugin, '\0bgm:virtual:bgm/package/harbor')) as Record<string, any>;
|
||||
expect(pkg.meta.id).toBe('harbor');
|
||||
expect(pkg.parts).toHaveProperty('token#wood');
|
||||
expect(pkg.surfaces).toHaveProperty('board#harbor');
|
||||
});
|
||||
|
||||
it('serializes maps as plain objects, not Map instances', () => {
|
||||
const plugin = bgm({ root: gamesRoot });
|
||||
const pkg = parseModule(load(plugin, '\0bgm:virtual:bgm/package/harbor')) as Record<string, any>;
|
||||
|
||||
// The emitted shape must be JSON-serializable: plain objects keyed by
|
||||
// `type#id`, not `Map`s (which `JSON.stringify` turns into `{}`).
|
||||
for (const key of ['parts', 'surfaces', 'setups'] as const) {
|
||||
expect(pkg[key]).not.toBeInstanceOf(Map);
|
||||
expect(pkg[key]).toEqual(expect.any(Object));
|
||||
}
|
||||
|
||||
// Consumers read the collections with Object.values / Object.keys.
|
||||
expect(Object.values(pkg.parts).map((p: any) => p.id).sort()).toEqual(['grain', 'wood']);
|
||||
expect(Object.keys(pkg.surfaces)).toEqual(['board#harbor']);
|
||||
expect(Object.keys(pkg.setups)).toEqual(['game#main']);
|
||||
});
|
||||
|
||||
it('errors on an unknown package', () => {
|
||||
const plugin = bgm({ root: gamesRoot });
|
||||
expect(() => load(plugin, '\0bgm:virtual:bgm/package/unknown')).toThrow(/not found/);
|
||||
});
|
||||
|
||||
it('watches every source file for reloads', () => {
|
||||
const plugin = bgm({ root: gamesRoot });
|
||||
const watched: string[] = [];
|
||||
const context = { addWatchFile: (file: string) => watched.push(file) };
|
||||
(plugin.buildStart as Callable<typeof plugin.buildStart>).call(context);
|
||||
|
||||
// Every def file (real + virtual code blocks) is watched so edits
|
||||
// trigger a re-collect.
|
||||
expect(watched.length).toBeGreaterThan(0);
|
||||
expect(watched.some((f) => f.endsWith('.yaml'))).toBe(true);
|
||||
expect(watched.some((f) => f.endsWith('.csv'))).toBe(true);
|
||||
expect(watched.every((f) => path.isAbsolute(f))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user