import { describe, expect, it } from 'vitest'; import type { Asset } from '../../src/core/model/Asset'; import { ASSET_TYPES, type AssetType } from '../../src/core/model/AssetTypes'; import { ASSET_CATEGORIES, ASSET_GROUPS, groupAssets } from '../../src/editor/panels/assetGroups'; let serial = 0; const asset = (type: AssetType, name: string): Asset => ({ id: `a${++serial}`, type, name, props: {} }) as unknown as Asset; const groupsOf = (assets: readonly Asset[]) => groupAssets(assets).flatMap((c) => c.groups); const shape = (assets: Asset[]) => groupsOf(assets).map((g) => [g.type, g.assets.map((a) => a.name)]); describe('groupAssets (#176)', () => { it('puts every asset into the group of its type, and no empty group', () => { const assets = [asset('texture', 'Sheet'), asset('sprite', 'Hero'), asset('texture', 'Tiles')]; expect(shape(assets)).toEqual([ ['sprite', ['Hero']], ['texture', ['Sheet', 'Tiles']], ]); }); it('puts the groups under their category, categories in their fixed order and none empty', () => { const assets = [ asset('song', 'Tune'), asset('behavior', 'Mover'), asset('scene', 'Level'), asset('sprite', 'Hero'), ]; expect(groupAssets(assets).map((c) => [c.category, c.groups.map((g) => g.type)])).toEqual([ ['Basics', ['scene']], ['Visuals', ['sprite']], ['Logics', ['behavior']], ['Audio', ['song']], ]); }); it('sorts the groups in a category by their heading, not by type or declaration order', () => { const types = [...ASSET_TYPES].reverse(); const categories = groupAssets(types.map((t) => asset(t, 'x'))); expect(categories.map((c) => c.category)).toEqual([...ASSET_CATEGORIES]); for (const { groups } of categories) { const headings = groups.map((g) => ASSET_GROUPS[g.type].name); expect(headings).toEqual([...headings].sort((a, b) => a.localeCompare(b))); } expect(categories.flatMap((c) => c.groups)).toHaveLength(ASSET_TYPES.length); // By heading: "State machine" sorts under S, the type key `statemachine` would not tell. const logic = categories .find((c) => c.category === 'Logics')! .groups.map((g) => ASSET_GROUPS[g.type].name); expect(logic.indexOf('Behavior')).toBeLessThan(logic.indexOf('State machine')); expect(logic.indexOf('State machine')).toBeLessThan(logic.indexOf('Struct')); }); it('sorts the assets in a group by name, ignoring case and reading numbers as numbers', () => { const assets = ['Level 10', 'level 2', 'Boss', 'Level 1', 'arena'].map((n) => asset('scene', n)); expect(shape(assets)).toEqual([['scene', ['arena', 'Boss', 'Level 1', 'level 2', 'Level 10']]]); }); it('keeps the project order among equal names', () => { const first = asset('sprite', 'Coin'); const second = asset('sprite', 'coin'); expect(groupsOf([first, second])[0]!.assets).toEqual([first, second]); expect(groupsOf([second, first])[0]!.assets).toEqual([second, first]); }); it('leaves the project list alone', () => { const assets = [asset('sprite', 'B'), asset('sprite', 'A')]; groupAssets(assets); expect(assets.map((a) => a.name)).toEqual(['B', 'A']); }); });