Skip to main content
Glama
creature-presets.test.ts6.61 kB
/** * Tests for creature preset system */ import { describe, it, expect } from 'vitest'; import { getCreaturePreset, expandCreatureTemplate, parseCreatureTemplate, listCreaturePresets, listCreatureVariants, listAllTemplates, CREATURE_PRESETS } from '../../src/data/creature-presets.js'; describe('Creature Presets', () => { describe('getCreaturePreset', () => { it('retrieves goblin preset', () => { const goblin = getCreaturePreset('goblin'); expect(goblin).not.toBeNull(); expect(goblin?.name).toBe('Goblin'); expect(goblin?.hp).toBe(7); expect(goblin?.ac).toBe(15); expect(goblin?.characterType).toBe('enemy'); }); it('handles case insensitivity', () => { expect(getCreaturePreset('GOBLIN')).not.toBeNull(); expect(getCreaturePreset('Goblin')).not.toBeNull(); }); it('handles spaces and dashes', () => { expect(getCreaturePreset('dire wolf')).not.toBeNull(); expect(getCreaturePreset('dire-wolf')).not.toBeNull(); expect(getCreaturePreset('dire_wolf')).not.toBeNull(); }); it('returns null for unknown creatures', () => { expect(getCreaturePreset('beholder')).toBeNull(); }); }); describe('parseCreatureTemplate', () => { it('parses simple template', () => { const { base, variant } = parseCreatureTemplate('goblin'); expect(base).toBe('goblin'); expect(variant).toBeUndefined(); }); it('parses variant template', () => { const { base, variant } = parseCreatureTemplate('goblin:archer'); expect(base).toBe('goblin'); expect(variant).toBe('archer'); }); it('normalizes input', () => { const { base, variant } = parseCreatureTemplate('Dire Wolf:Alpha'); expect(base).toBe('dire_wolf'); expect(variant).toBe('alpha'); }); }); describe('expandCreatureTemplate', () => { it('expands base creature', () => { const goblin = expandCreatureTemplate('goblin'); expect(goblin).not.toBeNull(); expect(goblin?.name).toBe('Goblin'); }); it('expands creature with variant', () => { const archer = expandCreatureTemplate('goblin:archer'); expect(archer).not.toBeNull(); expect(archer?.name).toBe('Goblin Archer'); expect(archer?.defaultAttack?.name).toBe('Shortbow'); }); it('applies HP modifier from variant', () => { const warrior = expandCreatureTemplate('goblin:warrior'); const base = getCreaturePreset('goblin'); expect(warrior).not.toBeNull(); expect(warrior!.hp).toBe(base!.hp + 3); // warrior has +3 HP }); it('applies AC modifier from variant', () => { const archer = expandCreatureTemplate('goblin:archer'); const base = getCreaturePreset('goblin'); expect(archer).not.toBeNull(); expect(archer!.ac).toBe(base!.ac - 2); // archer has -2 AC (no shield) }); it('allows name override', () => { const named = expandCreatureTemplate('goblin:warrior', 'Grak the Bold'); expect(named?.name).toBe('Grak the Bold'); }); it('returns base for unknown variant', () => { const unknown = expandCreatureTemplate('goblin:unknown_variant'); expect(unknown).not.toBeNull(); expect(unknown?.name).toBe('Goblin'); }); it('returns null for unknown creature', () => { expect(expandCreatureTemplate('beholder')).toBeNull(); }); }); describe('listCreaturePresets', () => { it('lists all available creatures', () => { const creatures = listCreaturePresets(); expect(creatures.length).toBeGreaterThan(30); expect(creatures).toContain('goblin'); expect(creatures).toContain('skeleton'); expect(creatures).toContain('wolf'); }); }); describe('listCreatureVariants', () => { it('lists variants for goblin', () => { const variants = listCreatureVariants('goblin'); expect(variants).toContain('warrior'); expect(variants).toContain('archer'); expect(variants).toContain('boss'); expect(variants).toContain('shaman'); }); it('returns empty array for creature without variants', () => { const variants = listCreatureVariants('ogre'); expect(variants).toEqual([]); }); }); describe('listAllTemplates', () => { it('lists all base and variant templates', () => { const templates = listAllTemplates(); expect(templates).toContain('goblin'); expect(templates).toContain('goblin:warrior'); expect(templates).toContain('goblin:archer'); expect(templates.length).toBeGreaterThan(40); }); }); describe('CREATURE_PRESETS structure', () => { it('all creatures have required fields', () => { for (const [key, preset] of Object.entries(CREATURE_PRESETS)) { expect(preset.name, `${key} missing name`).toBeTruthy(); expect(preset.stats, `${key} missing stats`).toBeDefined(); expect(preset.hp, `${key} missing hp`).toBeGreaterThan(0); expect(preset.maxHp, `${key} missing maxHp`).toBeGreaterThan(0); expect(preset.ac, `${key} missing ac`).toBeGreaterThan(0); expect(preset.level, `${key} missing level`).toBeGreaterThan(0); expect(preset.characterType, `${key} missing characterType`).toBe('enemy'); } }); it('all creatures have valid stats', () => { for (const [key, preset] of Object.entries(CREATURE_PRESETS)) { expect(preset.stats.str, `${key} str invalid`).toBeGreaterThanOrEqual(1); expect(preset.stats.dex, `${key} dex invalid`).toBeGreaterThanOrEqual(1); expect(preset.stats.con, `${key} con invalid`).toBeGreaterThanOrEqual(1); expect(preset.stats.int, `${key} int invalid`).toBeGreaterThanOrEqual(1); expect(preset.stats.wis, `${key} wis invalid`).toBeGreaterThanOrEqual(1); expect(preset.stats.cha, `${key} cha invalid`).toBeGreaterThanOrEqual(1); } }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Mnehmos/rpg-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server