Add buildTree to mirror how TTS nests objects, with a display label (Nickname or class Name). Generalize traverseMod to descend into any object with ContainedObjects, not just bags, and add Nickname to TTSObject.
79 lines
2.2 KiB
TypeScript
79 lines
2.2 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import type { TTSMod, TTSObject } from '@tts/shared';
|
|
import {
|
|
buildTree,
|
|
filterObjects,
|
|
findObject,
|
|
flattenObjects,
|
|
} from './objects.js';
|
|
|
|
function card(guid: string, name = 'Card'): TTSObject {
|
|
return { Name: name, GUID: guid, Description: '' };
|
|
}
|
|
|
|
function bag(guid: string, contained: TTSObject[]): TTSObject {
|
|
return { Name: 'Bag', GUID: guid, Description: '', ContainedObjects: contained };
|
|
}
|
|
|
|
const mod: TTSMod = {
|
|
GameMode: 'Tabletop',
|
|
Date: '2024-01-01',
|
|
ObjectStates: [
|
|
card('a', 'Deck'),
|
|
bag('b', [card('c', 'Card'), card('d', 'Token')]),
|
|
card('e', 'Deck'),
|
|
],
|
|
};
|
|
|
|
describe('flattenObjects', () => {
|
|
it('returns every object including containers and those inside them', () => {
|
|
const guids = flattenObjects(mod).map((o) => o.GUID);
|
|
expect(guids).toEqual(['a', 'b', 'c', 'd', 'e']);
|
|
});
|
|
|
|
it('sets Parent links before returning', () => {
|
|
const [a, b, c] = flattenObjects(mod);
|
|
expect(a!.Parent).toBeUndefined();
|
|
expect(b!.Parent).toBeUndefined();
|
|
expect(c!.Parent!.GUID).toBe('b');
|
|
});
|
|
});
|
|
|
|
describe('filterObjects', () => {
|
|
it('filters by predicate', () => {
|
|
const decks = filterObjects(mod, (o) => o.Name === 'Deck');
|
|
expect(decks.map((o) => o.GUID)).toEqual(['a', 'e']);
|
|
});
|
|
});
|
|
|
|
describe('findObject', () => {
|
|
it('finds an object by GUID', () => {
|
|
expect(findObject(mod, 'd')?.Name).toBe('Token');
|
|
});
|
|
|
|
it('returns undefined for a missing GUID', () => {
|
|
expect(findObject(mod, 'zzz')).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('buildTree', () => {
|
|
it('mirrors the containment hierarchy', () => {
|
|
const tree = buildTree(mod);
|
|
expect(tree.map((n) => n.object.GUID)).toEqual(['a', 'b', 'e']);
|
|
expect(tree[1]!.children.map((n) => n.object.GUID)).toEqual(['c', 'd']);
|
|
});
|
|
|
|
it('uses Nickname as the label when present', () => {
|
|
const named = {
|
|
...card('n', 'Card'),
|
|
Nickname: 'Ace of Spades',
|
|
};
|
|
const tree = buildTree({ ...mod, ObjectStates: [named] });
|
|
expect(tree[0]!.label).toBe('Ace of Spades');
|
|
});
|
|
|
|
it('falls back to the class Name as the label', () => {
|
|
const tree = buildTree(mod);
|
|
expect(tree[0]!.label).toBe('Deck');
|
|
});
|
|
}); |