Skip to main content
Glama

Dice Rolling MCP Server

by jimmcq
roller.test.ts5.48 kB
import { DiceRoller } from '../src/roller/dice-roller'; import { DiceExpression } from '../src/types'; import { randomInt } from 'crypto'; import { DiceNotationParser } from '../src/parser/dice-notation-parser'; // Mock the crypto module jest.mock('crypto', () => ({ ...jest.requireActual('crypto'), randomInt: jest.fn(), })); const mockedRandomInt = randomInt as jest.Mock; describe('DiceRoller', () => { const roller = new DiceRoller(); const parser = new DiceNotationParser(); beforeEach(() => { mockedRandomInt.mockClear(); }); test('handles success counting', () => { const expression: DiceExpression = { dice: [{ count: 5, size: 10, success: 8 }], modifier: 0, }; mockedRandomInt .mockReturnValueOnce(8) .mockReturnValueOnce(9) .mockReturnValueOnce(10) .mockReturnValueOnce(1) .mockReturnValueOnce(7); const result = roller.roll('test', expression); expect(result.total).toBe(3); }); test('keep highest works correctly', () => { const expression: DiceExpression = { dice: [{ count: 4, size: 6, keep: { type: 'h', count: 2 } }], modifier: 0, }; // Roll 1, 3, 5, 6 - should keep 5 and 6 mockedRandomInt .mockReturnValueOnce(1) .mockReturnValueOnce(3) .mockReturnValueOnce(5) .mockReturnValueOnce(6); const result = roller.roll('test', expression); expect(result.total).toBe(11); // 5 + 6 // Check that the lowest dice are marked as dropped const droppedCount = result.rolls.filter(roll => roll.dropped).length; expect(droppedCount).toBe(2); const keptCount = result.rolls.filter(roll => !roll.dropped).length; expect(keptCount).toBe(2); }); test('keep lowest works correctly', () => { const expression: DiceExpression = { dice: [{ count: 4, size: 6, keep: { type: 'l', count: 2 } }], modifier: 0, }; // Roll 1, 3, 5, 6 - should keep 1 and 3 mockedRandomInt .mockReturnValueOnce(1) .mockReturnValueOnce(3) .mockReturnValueOnce(5) .mockReturnValueOnce(6); const result = roller.roll('test', expression); expect(result.total).toBe(4); // 1 + 3 // Check that the highest dice are marked as dropped const droppedCount = result.rolls.filter(roll => roll.dropped).length; expect(droppedCount).toBe(2); const keptCount = result.rolls.filter(roll => !roll.dropped).length; expect(keptCount).toBe(2); }); test('drop highest works correctly', () => { const expression: DiceExpression = { dice: [{ count: 4, size: 6, drop: { type: 'h', count: 1 } }], modifier: 0, }; // Roll 1, 3, 5, 6 - should drop 6, keep 1, 3, 5 mockedRandomInt .mockReturnValueOnce(1) .mockReturnValueOnce(3) .mockReturnValueOnce(5) .mockReturnValueOnce(6); const result = roller.roll('test', expression); expect(result.total).toBe(9); // 1 + 3 + 5 // Check that only the highest die is dropped const droppedCount = result.rolls.filter(roll => roll.dropped).length; expect(droppedCount).toBe(1); const keptCount = result.rolls.filter(roll => !roll.dropped).length; expect(keptCount).toBe(3); }); test('drop lowest works correctly', () => { const expression: DiceExpression = { dice: [{ count: 4, size: 6, drop: { type: 'l', count: 1 } }], modifier: 0, }; // Roll 1, 3, 5, 6 - should drop 1, keep 3, 5, 6 mockedRandomInt .mockReturnValueOnce(1) .mockReturnValueOnce(3) .mockReturnValueOnce(5) .mockReturnValueOnce(6); const result = roller.roll('test', expression); expect(result.total).toBe(14); // 3 + 5 + 6 // Check that only the lowest die is dropped const droppedCount = result.rolls.filter(roll => roll.dropped).length; expect(droppedCount).toBe(1); const keptCount = result.rolls.filter(roll => !roll.dropped).length; expect(keptCount).toBe(3); }); test('basic rolling without modifiers', () => { const expression: DiceExpression = { dice: [{ count: 2, size: 6 }], modifier: 0, }; mockedRandomInt.mockReturnValueOnce(3).mockReturnValueOnce(5); const result = roller.roll('test', expression); expect(result.total).toBe(8); expect(result.rolls).toHaveLength(2); expect(result.rolls[0].result).toBe(3); expect(result.rolls[1].result).toBe(5); }); test('should handle reroll mechanic', () => { const expression = { dice: [{ count: 2, size: 6, reroll: [1] }], modifier: 0, }; // First die: rolls 1 (reroll), then rolls 4 // Second die: rolls 3 (no reroll) mockedRandomInt .mockReturnValueOnce(1) // Initial roll that triggers reroll .mockReturnValueOnce(4) // Reroll result .mockReturnValueOnce(3); // Second die const result = roller.roll('test', expression); expect(result.total).toBe(7); // 4 + 3 expect(result.rolls).toHaveLength(2); expect(result.rolls[0].rerolled).toBe(true); expect(result.rolls[0].modified).toBe(4); expect(result.rolls[1].rerolled).toBeUndefined(); }); test('rolls fudge dice correctly', () => { const expression = parser.parse('3dF'); mockedRandomInt .mockReturnValueOnce(0) .mockReturnValueOnce(1) .mockReturnValueOnce(2); const result = roller.roll('test', expression); expect(result.rolls.map(r => r.result)).toEqual([-1, 0, 1]); expect(result.total).toBe(0); }); });

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/jimmcq/dice-rolling-mcp'

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