7f1ab8f094
- GM "📣 Handout" composer in the header (title + body + optional image) sets uiStore.activeHandout; a clear button hides it. - snapshot gains an optional handout {title, body, imageId}; buildSnapshot streams the handout image over the existing image channel (id "handout"). - Player view (local + networked) shows the handout as a prominent card above the boards. resizeToMax() keeps handout images compact. - (Live scene/map switching already works via "Show to players".) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
58 lines
2.6 KiB
TypeScript
58 lines
2.6 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import { createCharacter } from './helpers';
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('/');
|
|
await page.evaluate(async () => {
|
|
indexedDB.deleteDatabase('ttrpg-manager');
|
|
localStorage.clear();
|
|
});
|
|
await page.reload();
|
|
});
|
|
|
|
test('player view shows the party and hides enemy HP numbers', async ({ page }) => {
|
|
await page.getByRole('button', { name: '+ New campaign' }).first().click();
|
|
await page.locator('input[data-autofocus]').fill('Show');
|
|
await page.getByRole('button', { name: 'Create' }).click();
|
|
|
|
// A player character
|
|
await page.getByRole('link', { name: 'Characters' }).click();
|
|
await createCharacter(page, 'Hero');
|
|
|
|
// An active encounter with the hero + a monster
|
|
await page.getByRole('link', { name: 'Combat' }).click();
|
|
await page.getByRole('button', { name: '+ New encounter' }).first().click();
|
|
await page.locator('input[data-autofocus]').fill('Skirmish');
|
|
await page.getByRole('button', { name: 'Create' }).click();
|
|
await page.getByLabel('Name').fill('Bandit');
|
|
await page.getByRole('button', { name: 'Add', exact: true }).click();
|
|
const addChar = page.locator('select').filter({ has: page.locator('option', { hasText: 'Choose…' }) });
|
|
await addChar.selectOption({ label: 'Hero (Lv 1)' });
|
|
await page.getByRole('button', { name: 'Start combat' }).click();
|
|
|
|
// Player view
|
|
await page.getByRole('link', { name: 'Dashboard' }).click();
|
|
await page.getByRole('link', { name: 'Player View' }).click();
|
|
await expect(page.getByRole('heading', { name: 'Show' })).toBeVisible();
|
|
await expect(page.getByText('Hero').first()).toBeVisible();
|
|
// Enemy shows a status word, not exact HP
|
|
await expect(page.getByText('Bandit')).toBeVisible();
|
|
await expect(page.getByText(/Healthy|Bloodied|Down/)).toBeVisible();
|
|
});
|
|
|
|
test('handout: GM pushes a handout to the player view', async ({ page }) => {
|
|
await page.getByRole('button', { name: '+ New campaign' }).first().click();
|
|
await page.locator('input[data-autofocus]').fill('Handout Camp');
|
|
await page.getByRole('button', { name: 'Create' }).click();
|
|
|
|
await page.getByRole('button', { name: /Handout/ }).click();
|
|
await page.getByLabel('Handout title').fill('A Mysterious Letter');
|
|
await page.getByLabel('Handout text').fill('Meet me at midnight.');
|
|
await page.getByRole('button', { name: 'Show to players' }).click();
|
|
|
|
await page.getByRole('link', { name: 'Dashboard' }).click();
|
|
await page.getByRole('link', { name: 'Player View' }).click();
|
|
await expect(page.getByRole('heading', { name: 'A Mysterious Letter' })).toBeVisible();
|
|
await expect(page.getByText('Meet me at midnight.')).toBeVisible();
|
|
});
|