// RED test: FEAT-3 initiative field on add participant. // If initiative field set, use it (no roll). Empty = roll d20+mod (current). import React from 'react'; import { screen, waitFor, within } from '@testing-library/react'; import '@testing-library/jest-dom'; import { renderApp, createCampaignViaUI, selectCampaignByName, createEncounterViaUI, selectEncounterByName, getParticipantForm } from './testHelpers'; import { fireEvent } from '@testing-library/react'; import { getCalls } from '../__mocks__/firebase/_mock-db'; function lastParticipantUpdate(name) { const calls = getCalls().filter(c => c.fn === 'updateDoc' && c.path.includes('/encounters/')); const last = calls[calls.length - 1]; return last && last.data.participants && last.data.participants.find(p => p.name === name); } describe('FEAT-3: initiative field on add (optional, empty=roll)', () => { test('initiative field set → uses value, no roll', async () => { await renderApp(); await createCampaignViaUI('Camp'); await selectCampaignByName('Camp'); await createEncounterViaUI('Enc'); await selectEncounterByName('Enc'); const form = within(getParticipantForm()); fireEvent.change(form.getByPlaceholderText('e.g., Dire Wolf'), { target: { value: 'Goblin' } }); fireEvent.change(form.getByLabelText(/Init Mod/i), { target: { value: '2' } }); fireEvent.change(form.getByLabelText(/Max HP/i), { target: { value: '7' } }); // set explicit initiative fireEvent.change(form.getByPlaceholderText('auto'), { target: { value: '15' } }); fireEvent.click(form.getByRole('button', { name: /Add to Encounter/i })); await waitFor(() => lastParticipantUpdate('Goblin')); const p = lastParticipantUpdate('Goblin'); expect(p.initiative).toBe(15); }); test('initiative field empty → rolls d20+mod', async () => { await renderApp(); await createCampaignViaUI('Camp2'); await selectCampaignByName('Camp2'); await createEncounterViaUI('Enc2'); await selectEncounterByName('Enc2'); const form = within(getParticipantForm()); fireEvent.change(form.getByPlaceholderText('e.g., Dire Wolf'), { target: { value: 'Wolf' } }); fireEvent.change(form.getByLabelText(/Init Mod/i), { target: { value: '3' } }); fireEvent.change(form.getByLabelText(/Max HP/i), { target: { value: '11' } }); // leave initiative empty fireEvent.click(form.getByRole('button', { name: /Add to Encounter/i })); await waitFor(() => lastParticipantUpdate('Wolf')); const p = lastParticipantUpdate('Wolf'); // rolled d20 (1-20) + mod 3 = range 4-23 expect(p.initiative).toBeGreaterThanOrEqual(4); expect(p.initiative).toBeLessThanOrEqual(23); }); });