Skip to main content
Glama
rest.test.ts5.81 kB
import { describe, it, expect, beforeEach } from 'vitest'; import { handleCreateCharacter, handleGetCharacter } from '../../src/server/crud-tools.js'; import { handleTakeLongRest, handleTakeShortRest } from '../../src/server/rest-tools.js'; import { closeDb, getDb } from '../../src/storage/index.js'; const mockCtx = { sessionId: 'test-session' }; /** * CRIT-002: Spell Slots Never Recover * * Foundation: Rest mechanics for HP restoration. * Spell slot restoration will be added when spellcasting system exists. * * Long Rest: Restores HP to max * Short Rest: Restores some HP (simulates spending hit dice) */ describe('CRIT-002: Rest Mechanics', () => { beforeEach(() => { closeDb(); getDb(':memory:'); }); describe('Long Rest', () => { it('should restore HP to max after long rest', async () => { // Create character with damaged HP const createResult = await handleCreateCharacter({ name: 'Wounded Warrior', stats: { str: 14, dex: 12, con: 14, int: 10, wis: 10, cha: 10 }, hp: 20, maxHp: 50, ac: 15, level: 5 }, mockCtx); const character = JSON.parse(createResult.content[0].text); expect(character.hp).toBe(20); expect(character.maxHp).toBe(50); // Take long rest const restResult = await handleTakeLongRest({ characterId: character.id }, mockCtx); const restData = JSON.parse(restResult.content[0].text); // Verify HP restored expect(restData.hpRestored).toBe(30); expect(restData.newHp).toBe(50); // Verify character record updated const reloadedResult = await handleGetCharacter({ id: character.id }, mockCtx); const reloaded = JSON.parse(reloadedResult.content[0].text); expect(reloaded.hp).toBe(50); }); it('should not overheal past maxHp', async () => { // Create character already at full HP const createResult = await handleCreateCharacter({ name: 'Healthy Hero', stats: { str: 14, dex: 12, con: 14, int: 10, wis: 10, cha: 10 }, hp: 50, maxHp: 50, ac: 15, level: 5 }, mockCtx); const character = JSON.parse(createResult.content[0].text); // Take long rest const restResult = await handleTakeLongRest({ characterId: character.id }, mockCtx); const restData = JSON.parse(restResult.content[0].text); expect(restData.hpRestored).toBe(0); expect(restData.newHp).toBe(50); }); it('should throw error for non-existent character', async () => { await expect(handleTakeLongRest({ characterId: 'non-existent-id' }, mockCtx)).rejects.toThrow(); }); }); describe('Short Rest', () => { it('should restore some HP after short rest', async () => { // Create character with damaged HP const createResult = await handleCreateCharacter({ name: 'Wounded Warrior', stats: { str: 14, dex: 12, con: 16, int: 10, wis: 10, cha: 10 }, // CON 16 = +3 modifier hp: 20, maxHp: 50, ac: 15, level: 5 }, mockCtx); const character = JSON.parse(createResult.content[0].text); // Take short rest spending 2 hit dice const restResult = await handleTakeShortRest({ characterId: character.id, hitDiceToSpend: 2 }, mockCtx); const restData = JSON.parse(restResult.content[0].text); // Should heal some HP (hit dice roll + CON modifier per die) expect(restData.hpRestored).toBeGreaterThan(0); expect(restData.newHp).toBeGreaterThan(20); expect(restData.newHp).toBeLessThanOrEqual(50); }); it('should not heal past maxHp on short rest', async () => { // Create character almost at full HP const createResult = await handleCreateCharacter({ name: 'Slightly Wounded', stats: { str: 14, dex: 12, con: 14, int: 10, wis: 10, cha: 10 }, hp: 48, maxHp: 50, ac: 15, level: 5 }, mockCtx); const character = JSON.parse(createResult.content[0].text); // Take short rest const restResult = await handleTakeShortRest({ characterId: character.id, hitDiceToSpend: 5 // Try to spend many dice }, mockCtx); const restData = JSON.parse(restResult.content[0].text); // Should cap at maxHp expect(restData.newHp).toBe(50); }); it('should default to 1 hit die if not specified', async () => { const createResult = await handleCreateCharacter({ name: 'Test Character', stats: { str: 14, dex: 12, con: 14, int: 10, wis: 10, cha: 10 }, hp: 20, maxHp: 50, ac: 15, level: 5 }, mockCtx); const character = JSON.parse(createResult.content[0].text); // Take short rest without specifying dice const restResult = await handleTakeShortRest({ characterId: character.id }, mockCtx); const restData = JSON.parse(restResult.content[0].text); expect(restData.hitDiceSpent).toBe(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