Rework backend #1
@@ -182,6 +182,7 @@ REWORK_PLAN.md.
|
||||
- [x] BUG-5: fixed (1-list model, 500 rounds clean)
|
||||
- [x] BUG-6: fixed structurally (1-list model)
|
||||
- [x] BUG-12: fixed — campaign selection follows activeDisplay
|
||||
- [x] BUG-15: fixed — DisplayView no longer re-sorts (drag order preserved)
|
||||
- [ ] BUG-8: ws adapter reconnect
|
||||
- [ ] BUG-10: deact+reactivate double-act
|
||||
- [ ] BUG-11: FE Combat.scenario crash
|
||||
|
||||
+4
-3
@@ -2500,9 +2500,10 @@ function DisplayView() {
|
||||
|
||||
let participantsToRender = [];
|
||||
if (participants) {
|
||||
// Hide inactive monsters (pre-staged/summoned reserves) from the player view
|
||||
const visibleParticipants = participants.filter(p => p.isActive || p.type !== 'monster');
|
||||
participantsToRender = sortParticipantsByInitiative(visibleParticipants, visibleParticipants);
|
||||
// 1-list model: participants[] IS the display order (DM drag = source of
|
||||
// truth). Do NOT re-sort by initiative — that diverges from AdminView /
|
||||
// turnOrderIds after any cross-init drag (BUG-15).
|
||||
participantsToRender = participants.filter(p => p.isActive || p.type !== 'monster');
|
||||
}
|
||||
|
||||
const displayStyles = campaignBackgroundUrl
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// RED test: DisplayView must render participants in turnOrderIds (drag) order,
|
||||
// NOT re-sort by initiative. 1-list model: participants[] = display source.
|
||||
// Bug: DisplayView line ~2505 calls sortParticipantsByInitiative(), ignoring
|
||||
// DM drag order. After cross-init drag, display diverges from AdminView/turnOrderIds.
|
||||
import React from 'react';
|
||||
import { render, waitFor, screen } from '@testing-library/react';
|
||||
import '@testing-library/jest-dom';
|
||||
import App from '../App';
|
||||
import { MOCK_DB } from '../__mocks__/firebase/_mock-db';
|
||||
import { resetAdapterCalls } from '../storage/firebase';
|
||||
|
||||
function seedDragOrder() {
|
||||
const campaignPath = 'artifacts/ttrpg-initiative-tracker-default/public/data/campaigns/c1';
|
||||
const encounterPath = 'artifacts/ttrpg-initiative-tracker-default/public/data/campaigns/c1/encounters/e1';
|
||||
const activeDisplayPath = 'artifacts/ttrpg-initiative-tracker-default/public/data/activeDisplay/status';
|
||||
// Three monsters, init-sorted would be: high(20), mid(11), low(10).
|
||||
// But participants[] = DRAG order: low BEFORE mid (DM dragged across init).
|
||||
const participants = [
|
||||
{ id: 'high', name: 'High', type: 'monster', initiative: 20, currentHp: 10, maxHp: 10, isActive: true },
|
||||
{ id: 'low', name: 'Low', type: 'monster', initiative: 10, currentHp: 10, maxHp: 10, isActive: true },
|
||||
{ id: 'mid', name: 'Mid', type: 'monster', initiative: 11, currentHp: 10, maxHp: 10, isActive: true },
|
||||
];
|
||||
MOCK_DB.set(campaignPath, { name: 'Camp', playerDisplayBackgroundUrl: '' });
|
||||
MOCK_DB.set(encounterPath, {
|
||||
name: 'Enc',
|
||||
participants,
|
||||
turnOrderIds: participants.map(p => p.id),
|
||||
round: 1,
|
||||
currentTurnParticipantId: 'high',
|
||||
isStarted: true,
|
||||
});
|
||||
MOCK_DB.set(activeDisplayPath, { activeCampaignId: 'c1', activeEncounterId: 'e1', hidePlayerHp: false });
|
||||
}
|
||||
|
||||
describe('DisplayView drag order (BUG-15)', () => {
|
||||
beforeEach(() => {
|
||||
window.history.replaceState({}, '', '/display');
|
||||
global.alert = jest.fn();
|
||||
window.open = jest.fn();
|
||||
// jsdom lacks scrollIntoView (DisplayView auto-scrolls current actor)
|
||||
Element.prototype.scrollIntoView = jest.fn();
|
||||
resetAdapterCalls();
|
||||
});
|
||||
afterEach(() => {
|
||||
window.history.replaceState({}, '', '/');
|
||||
});
|
||||
|
||||
test('renders participants in participants[] order, not init-sorted', async () => {
|
||||
seedDragOrder();
|
||||
render(<App />);
|
||||
|
||||
// wait for participant names to render
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByText(/High|Mid|Low/i).length).toBeGreaterThanOrEqual(3);
|
||||
}, { timeout: 3000 });
|
||||
|
||||
// collect name elements in DOM order (strip Current marker)
|
||||
const names = screen.getAllByText(/High|Mid|Low/i).map(el => el.textContent.replace(/\(Current\)/i, '').trim());
|
||||
// participants[] order = High, Low, Mid (drag moved Low before Mid).
|
||||
// Display must mirror this. Init-sorted would be High, Mid, Low.
|
||||
expect(names).toEqual(['High', 'Low', 'Mid']);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user