Includes full bot source (Phases 1–4), plus five new features: - Epic 1: emoji reaction state machine (👀⏳✅🎲) + burst queue cap at 2 with in-world drop notices - Epic 2: per-encounter tone field in YAML injected into LLM system prompt - Epic 3: player pronouns via modal registration + system prompt players block - Epic 4: strengthened skill_check_emit tool contract + missed-skill-check diagnostic Also includes UX design docs, epics, and story files under Docs/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
47 lines
1.8 KiB
TypeScript
47 lines
1.8 KiB
TypeScript
// Integration tests — require live Redis on localhost:6379.
|
|
// Start services before running: docker compose -f docker-compose.dev.yml up -d
|
|
//
|
|
// Run with: npm run test:int
|
|
|
|
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
|
|
// These tests are skipped unless RUN_INTEGRATION=1 is set,
|
|
// so they don't break CI without live services.
|
|
const runInt = process.env.RUN_INTEGRATION === '1';
|
|
|
|
describe.skipIf(!runInt)('Player registry — live Redis', async () => {
|
|
let playerRegistry: typeof import('../../src/session/playerRegistry.js').playerRegistry;
|
|
|
|
beforeAll(async () => {
|
|
const { redis } = await import('../../src/db/redis.js');
|
|
await redis.connect();
|
|
const mod = await import('../../src/session/playerRegistry.js');
|
|
playerRegistry = mod.playerRegistry;
|
|
});
|
|
|
|
afterAll(async () => {
|
|
const { redis } = await import('../../src/db/redis.js');
|
|
await redis.del('players:int-test-guild');
|
|
redis.disconnect();
|
|
});
|
|
|
|
it('round-trips set/get/delete', async () => {
|
|
await playerRegistry.set('int-test-guild', 'user-abc', 'Aelindra');
|
|
const player = await playerRegistry.get('int-test-guild', 'user-abc');
|
|
expect(player).toEqual({ discordId: 'user-abc', dndName: 'Aelindra' });
|
|
|
|
await playerRegistry.delete('int-test-guild', 'user-abc');
|
|
expect(await playerRegistry.get('int-test-guild', 'user-abc')).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe.skipIf(!runInt)('Spec loader — market-thief.yaml', async () => {
|
|
it('loads and validates the market-thief spec', async () => {
|
|
const { loadSpec } = await import('../../src/spec/loader.js');
|
|
const spec = loadSpec('market-thief');
|
|
expect(spec.encounterId).toBe('mardonar-market-thief-001');
|
|
expect(spec.npcs).toHaveLength(2);
|
|
expect(spec.goals.primary.length).toBeGreaterThan(0);
|
|
});
|
|
});
|