Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions client-v3/e2e/tests/13-live-show.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ test('leader is NOT in following mode', async () => {
await expect(container).not.toHaveAttribute('data-following', 'true');
});

test('current cue footer is visible by default', async () => {
// toBeVisible() alone would pass even if the footer were pushed below the fold by
// the script pane's computed height — toBeInViewport() catches that layout regression.
await expect(leaderPage.locator('.current-cue-footer')).toBeInViewport();
});

// ── Follower connects ─────────────────────────────────────────────────────

test('follower navigates to /live after leader', async () => {
Expand Down Expand Up @@ -146,6 +152,13 @@ test('can add an individual cue from the live view', async () => {
});
});

test('current cue footer shows the last cue seen for its type', async () => {
await expect(leaderPage.locator('.current-cue-footer .cue-button')).toHaveCount(1, {
timeout: 5_000,
});
await expect(leaderPage.locator('.current-cue-footer .cue-button').first()).toContainText('101');
});

test('can add a cue group from the live view', async () => {
await leaderPage.locator('.add-cue-btn').first().click();
await waitForModal(leaderPage, 'Add Cue');
Expand All @@ -167,6 +180,14 @@ test('can add a cue group from the live view', async () => {
await expect(leaderPage.locator('.cue-group-btn').first()).toContainText('LX 200 - LX 202');
});

test('current cue footer still shows exactly one badge for the cue type after grouped cues are added', async () => {
// Grouped cues are tracked individually — the footer collapses to the single most
// recently passed cue of that type, whichever one that ends up being.
await expect(leaderPage.locator('.current-cue-footer .cue-button')).toHaveCount(1, {
timeout: 5_000,
});
});

test('cue group buttons in live view are non-interactive display-only buttons', async () => {
// Group buttons in live view should NOT open an edit modal — editing is blocked server-side
// during live sessions. Verify clicking doesn't open any modal.
Expand Down
113 changes: 113 additions & 0 deletions client-v3/e2e/tests/14-user-settings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,28 @@ test('changing a toggle enables the Submit button', async () => {
}
});

test('current cue footer setting defaults on and persists after being toggled off', async () => {
const checkbox = page.locator('#show-current-cue-footer-input');
await expect(checkbox).toBeChecked();

await checkbox.click();
await expect(checkbox).not.toBeChecked();
await page.click('button:has-text("Submit")');
await expect(page.locator('button:has-text("Submit")')).toBeDisabled({ timeout: 5_000 });

await page.reload();
await waitForAppReady(page);
await page.click('.nav-link:has-text("Settings"), button[role="tab"]:has-text("Settings")');
await expect(page.locator('#show-current-cue-footer-input')).not.toBeChecked({
timeout: 5_000,
});

// Restore default state so it doesn't affect any later tests
await page.locator('#show-current-cue-footer-input').click();
await page.click('button:has-text("Submit")');
await expect(page.locator('#show-current-cue-footer-input')).toBeChecked({ timeout: 5_000 });
});

// ── Stage Direction Styles ────────────────────────────────────────────────

test('creates a stage direction style for override testing', async () => {
Expand All @@ -87,6 +109,97 @@ test('switches to Stage Direction Styles tab', async () => {
await expect(page.locator('#stage-directions-table')).toBeVisible({ timeout: 5_000 });
});

// ── Default Stage Direction Style ─────────────────────────────────────────

test('"Default Stage Direction Style" section is visible', async () => {
await expect(page.locator('.card:has-text("Default Stage Direction Style")')).toBeVisible();
});

test('default preview uses darkslateblue before any override', async () => {
// The card's example element should reflect the built-in fallback colour
const preview = page
.locator('.card:has-text("Default Stage Direction Style")')
.locator('.example-stage-direction');
await expect(preview).toHaveCSS('background-color', 'rgb(72, 61, 139)'); // darkslateblue
});

test('"Customise" button opens the default style modal', async () => {
await page
.locator('.card:has-text("Default Stage Direction Style") button:has-text("Customise")')
.click();
await waitForModal(page, 'Customise Default Stage Direction Style');
await expect(page.locator('#default-bg-colour-input')).toBeVisible();
});

test('setting a custom background colour saves and updates the card preview', async () => {
await page.locator('#default-bg-colour-input').fill('#FF0000');
await confirmModal(page);
await waitForModalClosed(page);
// Reset button becomes enabled (verifies PATCH /api/v1/user/settings was persisted)
await expect(
page.locator(
'.card:has-text("Default Stage Direction Style") button:has-text("Reset to Default")'
)
).toBeEnabled({ timeout: 5_000 });
// Card preview reflects saved colour (verifies WS GET_USER_SETTINGS sync updated the store)
const preview = page
.locator('.card:has-text("Default Stage Direction Style")')
.locator('.example-stage-direction');
await expect(preview).toHaveCSS('background-color', 'rgb(255, 0, 0)');
});

test('custom colour persists after page reload', async () => {
await page.reload();
await waitForAppReady(page);
await page.click('.nav-link:has-text("Stage Direction")');
await expect(page.locator('#stage-directions-table')).toBeVisible({ timeout: 5_000 });
// Reset button enabled (colour was persisted to DB via GET /api/v1/user/settings)
await expect(
page.locator(
'.card:has-text("Default Stage Direction Style") button:has-text("Reset to Default")'
)
).toBeEnabled({ timeout: 5_000 });
const preview = page
.locator('.card:has-text("Default Stage Direction Style")')
.locator('.example-stage-direction');
await expect(preview).toHaveCSS('background-color', 'rgb(255, 0, 0)');
});

test('text colour override can be enabled and saved', async () => {
await page
.locator('.card:has-text("Default Stage Direction Style") button:has-text("Customise")')
.click();
await waitForModal(page, 'Customise Default Stage Direction Style');
// Enable text colour override
await page.locator('.modal.show').getByText('Override text colour').click();
await expect(page.locator('#default-text-colour-input')).toBeVisible();
await page.locator('#default-text-colour-input').fill('#FFFFFF');
await confirmModal(page);
await waitForModalClosed(page);
// Preview text colour should update (white text on red background)
const preview = page
.locator('.card:has-text("Default Stage Direction Style")')
.locator('.example-stage-direction');
await expect(preview).toHaveCSS('color', 'rgb(255, 255, 255)', { timeout: 5_000 });
});

test('"Reset to Default" disables the Reset button and reverts the preview', async () => {
await page
.locator('.card:has-text("Default Stage Direction Style") button:has-text("Reset to Default")')
.click();
// Reset button becomes disabled once both overrides are cleared
await expect(
page.locator(
'.card:has-text("Default Stage Direction Style") button:has-text("Reset to Default")'
)
).toBeDisabled({ timeout: 5_000 });
// Preview reverts to darkslateblue
const preview = page
.locator('.card:has-text("Default Stage Direction Style")')
.locator('.example-stage-direction');
await expect(preview).toHaveCSS('background-color', 'rgb(72, 61, 139)', { timeout: 5_000 });
});

test('"New Override" button is enabled when stage direction styles exist', async () => {
// Scope to thead to avoid matching the "New Override" button in the Cue Colour Preferences tab
// (BVN BTabs without lazy mounts all tab panels, so inactive tab content stays in the DOM)
Expand Down
Loading
Loading