diff --git a/e2e/director.spec.ts b/e2e/director.spec.ts new file mode 100644 index 0000000..3227fde --- /dev/null +++ b/e2e/director.spec.ts @@ -0,0 +1,44 @@ +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(); + // Load the sample campaign (gives us a party + an active encounter). + await page.getByLabel('Settings').click(); + await page.getByRole('button', { name: 'Load sample campaign' }).click(); + await expect(page.getByRole('heading', { name: 'Sample: Lost Mine' })).toBeVisible(); +}); + +test('AI Director narrates a grounded scene with no API key (deterministic)', async ({ page }) => { + await page.getByLabel('Primary').getByRole('link', { name: 'AI Director' }).click(); + await expect(page.getByRole('heading', { name: 'AI Director' })).toBeVisible(); + await expect(page.getByText(/deterministic mode/)).toBeVisible(); + + // Empty until we start. + await expect(page.getByText('The story begins when you start the scene.')).toBeVisible(); + + await page.getByRole('button', { name: 'Begin the scene' }).click(); + + // A narration entry appears; the empty-state is gone; source badge shows deterministic. + await expect(page.getByText('The story begins when you start the scene.')).toBeHidden(); + await expect(page.getByText('deterministic', { exact: true })).toBeVisible(); + await expect(page.getByRole('button', { name: 'Continue' })).toBeVisible(); +}); + +test('the director can play a chosen party character (player persona)', async ({ page }) => { + await page.getByLabel('Primary').getByRole('link', { name: 'AI Director' }).click(); + + await page.getByRole('button', { name: 'Player', exact: true }).click(); + // Subtitle reflects the mode. + await expect(page.getByText(/ยท Player/)).toBeVisible(); + + // Seat the AI on the first party character. + await page.getByLabel('Character the AI plays').selectOption({ index: 1 }); + + await page.getByRole('button', { name: /Take the first action|Take turn/ }).click(); + await expect(page.getByText('deterministic', { exact: true })).toBeVisible(); +}); diff --git a/src/features/assistant/director/TranscriptPane.tsx b/src/features/assistant/director/TranscriptPane.tsx index 5467c1b..221cd92 100644 --- a/src/features/assistant/director/TranscriptPane.tsx +++ b/src/features/assistant/director/TranscriptPane.tsx @@ -18,7 +18,7 @@ export function TranscriptPane({ entries }: { entries: DirectorTranscriptEntry[] } return ( -