feat(extract): build containment tree and traverse all containers
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.
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { TTSMod, TTSObject } from '@tts/shared';
|
||||
import { filterObjects, findObject, flattenObjects } from './objects.js';
|
||||
import {
|
||||
buildTree,
|
||||
filterObjects,
|
||||
findObject,
|
||||
flattenObjects,
|
||||
} from './objects.js';
|
||||
|
||||
function card(guid: string, name = 'Card'): TTSObject {
|
||||
return { Name: name, GUID: guid, Description: '' };
|
||||
@@ -21,14 +26,15 @@ const mod: TTSMod = {
|
||||
};
|
||||
|
||||
describe('flattenObjects', () => {
|
||||
it('returns every object including those inside bags', () => {
|
||||
it('returns every object including containers and those inside them', () => {
|
||||
const guids = flattenObjects(mod).map((o) => o.GUID);
|
||||
expect(guids).toEqual(['a', 'c', 'd', 'e']);
|
||||
expect(guids).toEqual(['a', 'b', 'c', 'd', 'e']);
|
||||
});
|
||||
|
||||
it('sets Parent links before returning', () => {
|
||||
const [a, c] = flattenObjects(mod);
|
||||
const [a, b, c] = flattenObjects(mod);
|
||||
expect(a!.Parent).toBeUndefined();
|
||||
expect(b!.Parent).toBeUndefined();
|
||||
expect(c!.Parent!.GUID).toBe('b');
|
||||
});
|
||||
});
|
||||
@@ -48,4 +54,26 @@ describe('findObject', () => {
|
||||
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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user