P14a: global session sidebar + roster + private-channel backend
- Session sidebar (header "☰ Session" toggle, mobile drawer) visible to GM AND players: which session you're in, who's here (GM + players), and the live roll feed. The GM's own public rolls now mirror into the local feed too. - Server roster broadcast to everyone (sendRoster on join/seatGrant/disconnect/ host-resume); includes the GM. Players now see the roster, not just the GM. - Targeted private channel (backend, wired to UI next): privateState (GM→server→ one player only) + privateHandout; image sent INLINE so non-recipients never get it. roster/privateHandout schemas + stores + wsSync handlers + senders. - Adversarial-review fixes: GM included in roster; roster refreshes on GM disconnect; privateState returns a forbidden error on auth failure. +3 server tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,12 @@ test('GM hosts a session; a player on another device sees live combat', async ({
|
||||
await expect(player.getByText('Table rolls')).toBeVisible();
|
||||
await expect(player.getByText('GM').first()).toBeVisible();
|
||||
|
||||
// Session sidebar: both the GM and the player see who's in the session.
|
||||
await gm.getByRole('button', { name: 'Open session panel' }).click();
|
||||
await expect(gm.getByText(/Who's here \(2\)/)).toBeVisible(); // GM + 1 player
|
||||
await player.getByRole('button', { name: 'Open session panel' }).click();
|
||||
await expect(player.getByText(/Who's here \(2\)/)).toBeVisible(); // host + player visible to everyone
|
||||
|
||||
await gmCtx.close();
|
||||
await playerCtx.close();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user