Files
ttrpg_manager/e2e/interactive-dice.spec.ts
T
NilsBriggen 9647e6b3d6 Phase 4: interactive dice & sheet rolling
- Dice notation: exploding (Nd6!) and reroll-below (Nd6r2), capped + tested
- Degrees of success / roll-vs-DC (PF2e ±10 + nat 20/1 steps; 5e crit on nat 20/1)
- Global roll tray (shared store + RollTray in layout) with animated result + degree
- Roll from the character sheet: skills, saves, and attack to-hit/damage are
  clickable and post to the tray + history (rollAndShow/rollCheck helpers)
- Saved roll macros per campaign (persisted) on the Dice page

10 new unit tests (notation explode/reroll, degrees), interactive-dice e2e.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 01:32:15 +02:00

39 lines
1.7 KiB
TypeScript

import { test, expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
await page.goto('/');
await page.evaluate(async () => {
indexedDB.deleteDatabase('ttrpg-manager');
localStorage.clear();
});
await page.reload();
});
test('rolling a skill from the sheet shows the roll tray', async ({ page }) => {
await page.getByRole('button', { name: '+ New campaign' }).first().click();
await page.locator('input[data-autofocus]').fill('Dice Camp');
await page.getByRole('button', { name: 'Create' }).click();
await page.getByRole('link', { name: 'Characters' }).click();
await page.getByRole('button', { name: '+ New character' }).first().click();
await page.locator('input[data-autofocus]').fill('Roller');
await page.getByRole('button', { name: 'Create' }).click();
await page.getByRole('link', { name: /Roller/ }).click();
// Click the Acrobatics modifier to roll it
await page.getByTitle('Roll Acrobatics (DEX)').click();
// The shared roll tray appears (unique dismiss control) showing the roll
await expect(page.getByRole('button', { name: 'Dismiss roll' })).toBeVisible();
await expect(page.locator('text=/= \\d+/').first()).toBeVisible();
});
test('dice page: save and use a macro', async ({ page }) => {
await page.getByRole('link', { name: 'Dice' }).click();
await page.getByLabel('Dice expression').fill('2d6+3');
await page.getByRole('button', { name: /Save/ }).click();
// Macro chip appears and rolls when clicked
const chip = page.getByRole('button', { name: '2d6+3', exact: true });
await expect(chip).toBeVisible();
await chip.click();
await expect(page.locator('text=/= \\d+/').first()).toBeVisible();
});