feat(content): add action kind and group schema

This commit is contained in:
ginnoir
2026-06-11 20:12:21 -05:00
parent c76b2d1231
commit c48e53cc7b
3 changed files with 113 additions and 9 deletions
+61
View File
@@ -6,6 +6,7 @@ const validActions = [
{
id: 'forage',
name: 'Forage',
group: { id: 'camp', label: 'Camp' },
durationMs: 3000,
yields: [{ resourceId: 'gold', amount: 1 }],
},
@@ -28,6 +29,7 @@ describe('buildContent()', () => {
{
id: 'forage',
name: 'Forage',
group: { id: 'camp', label: 'Camp' },
durationMs: 3000,
yields: [{ resourceId: 'ghost', amount: 1 }],
},
@@ -48,6 +50,7 @@ describe('buildContent()', () => {
{
id: 'forage',
name: 'Forage',
group: { id: 'camp', label: 'Camp' },
durationMs: -1,
yields: [{ resourceId: 'gold', amount: 1 }],
},
@@ -66,6 +69,7 @@ describe('costs and multi-yield', () => {
{
id: 'craft',
name: 'Craft',
group: { id: 'camp', label: 'Camp' },
durationMs: 1000,
costs: [{ resourceId: 'wood', amount: 2 }],
yields: [
@@ -84,6 +88,7 @@ describe('costs and multi-yield', () => {
{
id: 'craft',
name: 'Craft',
group: { id: 'camp', label: 'Camp' },
durationMs: 1000,
costs: [{ resourceId: 'ghost', amount: 1 }],
yields: [{ resourceId: 'gold', amount: 1 }],
@@ -104,6 +109,7 @@ describe('unlock conditions', () => {
{
id: 'forage',
name: 'Forage',
group: { id: 'camp', label: 'Camp' },
durationMs: 3000,
yields: [{ resourceId: 'gold', amount: 1 }],
unlock: {
@@ -131,6 +137,7 @@ describe('action narrative fields', () => {
{
id: 'forage',
name: 'Forage',
group: { id: 'camp', label: 'Camp' },
durationMs: 3000,
yields: [{ resourceId: 'gold', amount: 1 }],
storyHint: 'Gather what the forest offers.',
@@ -148,3 +155,57 @@ describe('action narrative fields', () => {
expect(content.actionsById.forage.storyTooltip).toBeUndefined();
});
});
describe('action kind schema', () => {
it('accepts kind, group, and storyChoiceId', () => {
const content = buildContent({
resources: [{ id: 'supplies', name: 'Supplies' }],
actions: [
{
id: 'pick_high_road',
name: 'Take the high road',
kind: 'story',
group: { id: 'fork', label: 'Crossroads' },
storyChoiceId: 'pick_a',
yields: [],
},
],
});
expect(content.actionsById.pick_high_road.kind).toBe('story');
expect(content.actionsById.pick_high_road.group.label).toBe('Crossroads');
});
it('defaults kind to timed and requires durationMs for timed actions', () => {
expect(() =>
buildContent({
resources: [{ id: 'supplies', name: 'Supplies' }],
actions: [
{
id: 'broken',
name: 'Broken',
kind: 'timed',
group: { id: 'camp', label: 'Camp' },
yields: [{ resourceId: 'supplies', amount: 1 }],
},
],
}),
).toThrow();
});
it('requires durationMs for loop actions', () => {
const content = buildContent({
resources: [{ id: 'supplies', name: 'Supplies' }],
actions: [
{
id: 'rest',
name: 'Rest',
kind: 'loop',
group: { id: 'camp_loop', label: 'Camp activities' },
durationMs: 2000,
yields: [{ resourceId: 'supplies', amount: 1 }],
},
],
});
expect(content.actionsById.rest.kind).toBe('loop');
});
});