import { useState, type ReactNode } from 'react';
import { act, render, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { App } from '../app';
import { ServerProvider } from '../context/server-context';
import { ApiClient } from '../lib/api';
import { I18nProvider } from '../lib/i18n';
import type { SessionActor, TriggerCatalog, TriggerDefinition } from '../types';
import { AppShell, type RouteId } from './app-shell';
import { MinecraftIcon } from './minecraft-icon';
const timestamp = '2026-01-01T00:00:00Z';
function themeClient(roles: SessionActor['roles'] = ['owner'], permissions: string[] = []): ApiClient {
const client = new ApiClient();
vi.spyOn(client, 'session').mockResolvedValue({ authenticated: true, csrfToken: 'csrf', actor: {
id: 'theme-observer', displayName: 'Theme account', roles, permissions, totpVerified: true,
} });
vi.spyOn(client, 'status').mockResolvedValue({ sampledAt: timestamp, uptimeSeconds: 1, playersOnline: 2 });
vi.spyOn(client, 'features').mockResolvedValue({ consoleEnabled: true, moderationEnabled: false,
claimsEnabled: false, worldTrackingEnabled: false, rollbackEnabled: false });
vi.spyOn(client, 'subscribe').mockReturnValue(() => undefined);
return client;
}
function ShellHarness({ initialRoute, navigate, children }: {
initialRoute: RouteId; navigate: (route: RouteId) => void; children?: ReactNode;
}) {
const [route, setRoute] = useState(initialRoute);
return <AppShell route={route} navigate={(next) => { navigate(next); setRoute(next); }}>
{children ?? <h1>Workspace fixture</h1>}
</AppShell>;
}
function renderShell({ client = themeClient(), route = 'overview', locale = 'en-US' }: {
client?: ApiClient; route?: RouteId; locale?: 'en-US' | 'zh-CN';
} = {}) {
localStorage.setItem('xfesm.locale', locale);
const navigate = vi.fn();
const view = render(<I18nProvider><ServerProvider client={client}>
<ShellHarness initialRoute={route} navigate={navigate} />
</ServerProvider></I18nProvider>);
return { ...view, navigate };
}
describe('Minecraft-themed application chrome', () => {
afterEach(() => {
location.hash = '';
localStorage.removeItem('xfesm.locale');
sessionStorage.removeItem('xfesm.csrf');
vi.restoreAllMocks();
});
it('keeps permission filtering intact instead of exposing every themed navigation slot', async () => {
renderShell({ client: themeClient(['observer'], ['status_read', 'player_read', 'trigger_read']) });
const navigation = within(await screen.findByRole('navigation', { name: 'Core management' }));
for (const label of ['Overview', 'Online players', 'Triggers', 'Content studio', 'Settings']) {
expect(navigation.getByRole('button', { name: label })).toBeInTheDocument();
}
for (const label of ['Economy', 'UI menus', 'Command policies', 'Audit log', 'Secure console']) {
expect(navigation.queryByRole('button', { name: label })).not.toBeInTheDocument();
}
expect(screen.queryByRole('navigation', { name: 'Governance & recovery' })).not.toBeInTheDocument();
});
it('preserves a single active route and its accessible name when navigating themed buttons', async () => {
const user = userEvent.setup();
const { navigate } = renderShell({ route: 'triggers' });
const navigation = within(await screen.findByRole('navigation', { name: 'Core management' }));
const triggers = navigation.getByRole('button', { name: 'Triggers' });
expect(triggers).toHaveAttribute('aria-current', 'page');
expect(triggers).toHaveClass('nav-link--active');
await user.click(navigation.getByRole('button', { name: 'UI menus' }));
expect(navigate).toHaveBeenLastCalledWith('menus');
expect(navigation.getByRole('button', { name: 'UI menus' })).toHaveAttribute('aria-current', 'page');
expect(triggers).not.toHaveAttribute('aria-current');
expect(screen.getAllByRole('button', { current: 'page' })).toHaveLength(1);
});
it('keeps pixel navigation and brand icons decorative without duplicating accessible button names', async () => {
const { container } = renderShell({ route: 'triggers' });
const navigation = within(await screen.findByRole('navigation', { name: 'Core management' }));
const triggers = navigation.getByRole('button', { name: 'Triggers' });
const icon = triggers.querySelector('[data-minecraft-icon="redstone"]');
expect(icon).toBeInTheDocument();
expect(icon).toHaveAttribute('aria-hidden', 'true');
expect(triggers).toHaveAccessibleName('Triggers');
const pixels = container.querySelectorAll('.minecraft-icon');
expect(pixels.length).toBeGreaterThan(10);
for (const pixel of pixels) {
expect(pixel).toHaveAttribute('aria-hidden', 'true');
expect(pixel).toHaveAttribute('focusable', 'false');
expect(pixel).toHaveAttribute('viewBox', '0 0 16 16');
}
expect(screen.queryByRole('img')).not.toBeInTheDocument();
});
it('provides alternative text only when an individual pixel icon is intentionally labelled', () => {
const { container } = render(<><MinecraftIcon name="grass" /><MinecraftIcon name="emerald" label="Emerald status" /></>);
expect(container.querySelector('[data-minecraft-icon="grass"]')).toHaveAttribute('aria-hidden', 'true');
const labelled = screen.getByRole('img', { name: 'Emerald status' });
expect(labelled).not.toHaveAttribute('aria-hidden', 'true');
expect(labelled).toHaveAttribute('focusable', 'false');
expect(screen.getAllByRole('img')).toHaveLength(1);
});
it('still opens and closes the mobile sidebar and closes it after navigation', async () => {
const user = userEvent.setup();
const { container, navigate } = renderShell();
const navigation = within(await screen.findByRole('navigation', { name: 'Core management' }));
const sidebar = screen.getByRole('navigation', { name: 'Core management' }).closest('aside')!;
expect(sidebar).not.toHaveClass('sidebar--open');
await user.click(screen.getByRole('button', { name: 'Menu' }));
expect(sidebar).toHaveClass('sidebar--open');
expect(container.querySelector('.sidebar-backdrop')).toBeInTheDocument();
await user.click(navigation.getByRole('button', { name: 'Online players' }));
expect(navigate).toHaveBeenLastCalledWith('players');
expect(sidebar).not.toHaveClass('sidebar--open');
expect(container.querySelector('.sidebar-backdrop')).not.toBeInTheDocument();
await user.click(screen.getByRole('button', { name: 'Menu' }));
await user.click(within(sidebar).getByRole('button', { name: 'Close' }));
expect(sidebar).not.toHaveClass('sidebar--open');
await user.click(screen.getByRole('button', { name: 'Menu' }));
await user.click(container.querySelector<HTMLButtonElement>('.sidebar-backdrop')!);
expect(sidebar).not.toHaveClass('sidebar--open');
});
it('keeps both language controls operable without changing the active route', async () => {
const user = userEvent.setup();
renderShell({ route: 'triggers', locale: 'zh-CN' });
await screen.findByRole('navigation', { name: '核心管理' });
await user.click(screen.getByRole('button', { name: 'English' }));
expect(within(screen.getByRole('navigation', { name: 'Core management' }))
.getByRole('button', { name: 'Triggers' })).toHaveAttribute('aria-current', 'page');
expect(localStorage.getItem('xfesm.locale')).toBe('en-US');
await user.click(screen.getByRole('button', { name: '中文' }));
expect(within(screen.getByRole('navigation', { name: '核心管理' }))
.getByRole('button', { name: '触发器' })).toHaveAttribute('aria-current', 'page');
expect(localStorage.getItem('xfesm.locale')).toBe('zh-CN');
});
it('ties the themed connection indicators to real connection, reconnect, and SSE states', async () => {
const client = themeClient();
vi.mocked(client.session).mockRejectedValueOnce(new Error('Connection refused'));
let emitState: ((state: 'open' | 'error') => void) | undefined;
vi.mocked(client.subscribe).mockImplementation((_onEvent, onState) => { emitState = onState; return () => undefined; });
const user = userEvent.setup();
const { container } = renderShell({ client });
const hud = container.querySelector('.topbar__server')!;
const meter = container.querySelector('.experience-meter')!;
expect(hud).toHaveAttribute('data-connection', 'connecting');
expect(meter).toHaveAttribute('aria-hidden', 'true');
expect(meter).toHaveAttribute('data-connected', 'false');
await waitFor(() => expect(hud).toHaveAttribute('data-connection', 'offline'));
expect(hud).toHaveTextContent('Management API offline');
expect(meter).toHaveAttribute('data-connected', 'false');
expect(screen.getByRole('alert')).toHaveTextContent('Connection refused');
await user.click(screen.getByRole('button', { name: 'Reconnect' }));
await waitFor(() => expect(hud).toHaveAttribute('data-connection', 'online'));
expect(hud).toHaveTextContent('Live connection');
expect(meter).toHaveAttribute('data-connected', 'true');
await waitFor(() => expect(emitState).toBeDefined());
act(() => emitState?.('error'));
expect(hud).toHaveAttribute('data-connection', 'degraded');
expect(hud).toHaveTextContent('Connection degraded');
expect(meter).toHaveAttribute('data-connected', 'false');
act(() => emitState?.('open'));
expect(hud).toHaveAttribute('data-connection', 'online');
expect(meter).toHaveAttribute('data-connected', 'true');
});
it.each([
['triggers', 'main-content--triggers'],
['content', 'main-content--content'],
] as const)('retains the full-width workspace hook for the %s editor', async (route, className) => {
renderShell({ route });
await screen.findByRole('navigation', { name: 'Core management' });
const main = screen.getByRole('main');
expect(main).toHaveClass('main-content', className);
expect(main.parentElement).toHaveClass('workspace');
expect(main.parentElement?.parentElement).toHaveClass('app-shell');
});
it('keeps trigger focus mode inside the full-width shell contract and restores the normal layout on exit', async () => {
localStorage.setItem('xfesm.locale', 'en-US');
location.hash = '/triggers';
const client = themeClient();
const trigger: TriggerDefinition = {
id: 'theme-trigger', groupId: 'theme-group', name: 'Theme trigger', description: '', enabled: true,
mode: 'visual', schemaVersion: 2, event: { type: 'player.join', configuration: {} },
events: [{ nodeId: 'theme-event', type: 'player.join', configuration: {} }], declarations: [], functions: [], statements: [],
conditionMode: 'all', conditions: [], actions: [], script: '', revision: 0, createdBy: 'owner',
createdAt: timestamp, updatedAt: timestamp, migrated: false,
};
const catalog: TriggerCatalog = { defaultMessageSender: 'Server', events: ['player.join'], operators: [], actions: [], actionParameters: {}, variables: [],
schemaVersion: 2, descriptors: [] };
vi.spyOn(client, 'triggerWorkspace').mockResolvedValue({ totalTriggers: 1, groups: [{
id: 'theme-group', name: 'Theme group', description: '', enabled: true, revision: 0, createdBy: 'owner',
createdAt: timestamp, updatedAt: timestamp, migrated: false, triggers: [trigger],
}] });
vi.spyOn(client, 'triggerCatalog').mockResolvedValue(catalog);
vi.spyOn(client, 'menuWorkspace').mockResolvedValue({ menus: [], totalMenus: 0 });
vi.spyOn(client, 'economy').mockResolvedValue({ currencies: [], overview: { currencies: [], observedAt: timestamp } });
vi.spyOn(client, 'triggerExecutions').mockResolvedValue({ items: [] });
vi.spyOn(client, 'triggerEventCaptures').mockResolvedValue({ items: [] });
vi.spyOn(client, 'triggerLibraries').mockResolvedValue({ items: [] });
const user = userEvent.setup();
render(<I18nProvider><ServerProvider client={client}><App /></ServerProvider></I18nProvider>);
await user.click(await screen.findByRole('button', { name: /Theme trigger/ }));
const tree = screen.getByRole('region', { name: 'Program tree' });
const page = tree.closest('.trigger-page')!;
const main = screen.getByRole('main');
const shell = main.closest('.app-shell')!;
await user.click(screen.getByRole('button', { name: 'Focus editor' }));
expect(page).toHaveClass('trigger-page--focused');
expect(main).toHaveClass('main-content--triggers');
expect(tree.parentElement).toHaveClass('galaxy-workbench');
// These direct-child relationships drive the full-width focus-mode CSS selectors.
expect(shell.querySelector(':scope > .sidebar')).toBeInTheDocument();
expect(shell.querySelector(':scope > .workspace > .topbar')).toBeInTheDocument();
expect(shell.querySelector(':scope > .workspace > .main-content')).toBe(main);
expect(screen.getByRole('button', { name: 'Exit focus' })).toHaveAttribute('aria-pressed', 'true');
await user.click(screen.getByRole('button', { name: 'Exit focus' }));
await waitFor(() => expect(page).not.toHaveClass('trigger-page--focused'));
expect(tree).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Focus editor' })).toHaveAttribute('aria-pressed', 'false');
});
});
import { useState, type ReactNode } from 'react';
import { act, render, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { App } from '../app';
import { ServerProvider } from '../context/server-context';
import { ApiClient } from '../lib/api';
import { I18nProvider } from '../lib/i18n';
import type { SessionActor, TriggerCatalog, TriggerDefinition } from '../types';
import { AppShell, type RouteId } from './app-shell';
import { MinecraftIcon } from './minecraft-icon';
const timestamp = '2026-01-01T00:00:00Z';
function themeClient(roles: SessionActor['roles'] = ['owner'], permissions: string[] = []): ApiClient {
const client = new ApiClient();
vi.spyOn(client, 'session').mockResolvedValue({ authenticated: true, csrfToken: 'csrf', actor: {
id: 'theme-observer', displayName: 'Theme account', roles, permissions, totpVerified: true,
} });
vi.spyOn(client, 'status').mockResolvedValue({ sampledAt: timestamp, uptimeSeconds: 1, playersOnline: 2 });
vi.spyOn(client, 'features').mockResolvedValue({ consoleEnabled: true, moderationEnabled: false,
claimsEnabled: false, worldTrackingEnabled: false, rollbackEnabled: false });
vi.spyOn(client, 'subscribe').mockReturnValue(() => undefined);
return client;
}
function ShellHarness({ initialRoute, navigate, children }: {
initialRoute: RouteId; navigate: (route: RouteId) => void; children?: ReactNode;
}) {
const [route, setRoute] = useState(initialRoute);
return <AppShell route={route} navigate={(next) => { navigate(next); setRoute(next); }}>
{children ?? <h1>Workspace fixture</h1>}
</AppShell>;
}
function renderShell({ client = themeClient(), route = 'overview', locale = 'en-US' }: {
client?: ApiClient; route?: RouteId; locale?: 'en-US' | 'zh-CN';
} = {}) {
localStorage.setItem('xfesm.locale', locale);
const navigate = vi.fn();
const view = render(<I18nProvider><ServerProvider client={client}>
<ShellHarness initialRoute={route} navigate={navigate} />
</ServerProvider></I18nProvider>);
return { ...view, navigate };
}
describe('Minecraft-themed application chrome', () => {
afterEach(() => {
location.hash = '';
localStorage.removeItem('xfesm.locale');
sessionStorage.removeItem('xfesm.csrf');
vi.restoreAllMocks();
});
it('keeps permission filtering intact instead of exposing every themed navigation slot', async () => {
renderShell({ client: themeClient(['observer'], ['status_read', 'player_read', 'trigger_read']) });
const navigation = within(await screen.findByRole('navigation', { name: 'Core management' }));
for (const label of ['Overview', 'Online players', 'Triggers', 'Content studio', 'Settings']) {
expect(navigation.getByRole('button', { name: label })).toBeInTheDocument();
}
for (const label of ['Economy', 'UI menus', 'Command policies', 'Audit log', 'Secure console']) {
expect(navigation.queryByRole('button', { name: label })).not.toBeInTheDocument();
}
expect(screen.queryByRole('navigation', { name: 'Governance & recovery' })).not.toBeInTheDocument();
});
it('preserves a single active route and its accessible name when navigating themed buttons', async () => {
const user = userEvent.setup();
const { navigate } = renderShell({ route: 'triggers' });
const navigation = within(await screen.findByRole('navigation', { name: 'Core management' }));
const triggers = navigation.getByRole('button', { name: 'Triggers' });
expect(triggers).toHaveAttribute('aria-current', 'page');
expect(triggers).toHaveClass('nav-link--active');
await user.click(navigation.getByRole('button', { name: 'UI menus' }));
expect(navigate).toHaveBeenLastCalledWith('menus');
expect(navigation.getByRole('button', { name: 'UI menus' })).toHaveAttribute('aria-current', 'page');
expect(triggers).not.toHaveAttribute('aria-current');
expect(screen.getAllByRole('button', { current: 'page' })).toHaveLength(1);
});
it('keeps pixel navigation and brand icons decorative without duplicating accessible button names', async () => {
const { container } = renderShell({ route: 'triggers' });
const navigation = within(await screen.findByRole('navigation', { name: 'Core management' }));
const triggers = navigation.getByRole('button', { name: 'Triggers' });
const icon = triggers.querySelector('[data-minecraft-icon="redstone"]');
expect(icon).toBeInTheDocument();
expect(icon).toHaveAttribute('aria-hidden', 'true');
expect(triggers).toHaveAccessibleName('Triggers');
const pixels = container.querySelectorAll('.minecraft-icon');
expect(pixels.length).toBeGreaterThan(10);
for (const pixel of pixels) {
expect(pixel).toHaveAttribute('aria-hidden', 'true');
expect(pixel).toHaveAttribute('focusable', 'false');
expect(pixel).toHaveAttribute('viewBox', '0 0 16 16');
}
expect(screen.queryByRole('img')).not.toBeInTheDocument();
});
it('provides alternative text only when an individual pixel icon is intentionally labelled', () => {
const { container } = render(<><MinecraftIcon name="grass" /><MinecraftIcon name="emerald" label="Emerald status" /></>);
expect(container.querySelector('[data-minecraft-icon="grass"]')).toHaveAttribute('aria-hidden', 'true');
const labelled = screen.getByRole('img', { name: 'Emerald status' });
expect(labelled).not.toHaveAttribute('aria-hidden', 'true');
expect(labelled).toHaveAttribute('focusable', 'false');
expect(screen.getAllByRole('img')).toHaveLength(1);
});
it('still opens and closes the mobile sidebar and closes it after navigation', async () => {
const user = userEvent.setup();
const { container, navigate } = renderShell();
const navigation = within(await screen.findByRole('navigation', { name: 'Core management' }));
const sidebar = screen.getByRole('navigation', { name: 'Core management' }).closest('aside')!;
expect(sidebar).not.toHaveClass('sidebar--open');
await user.click(screen.getByRole('button', { name: 'Menu' }));
expect(sidebar).toHaveClass('sidebar--open');
expect(container.querySelector('.sidebar-backdrop')).toBeInTheDocument();
await user.click(navigation.getByRole('button', { name: 'Online players' }));
expect(navigate).toHaveBeenLastCalledWith('players');
expect(sidebar).not.toHaveClass('sidebar--open');
expect(container.querySelector('.sidebar-backdrop')).not.toBeInTheDocument();
await user.click(screen.getByRole('button', { name: 'Menu' }));
await user.click(within(sidebar).getByRole('button', { name: 'Close' }));
expect(sidebar).not.toHaveClass('sidebar--open');
await user.click(screen.getByRole('button', { name: 'Menu' }));
await user.click(container.querySelector<HTMLButtonElement>('.sidebar-backdrop')!);
expect(sidebar).not.toHaveClass('sidebar--open');
});
it('keeps both language controls operable without changing the active route', async () => {
const user = userEvent.setup();
renderShell({ route: 'triggers', locale: 'zh-CN' });
await screen.findByRole('navigation', { name: '核心管理' });
await user.click(screen.getByRole('button', { name: 'English' }));
expect(within(screen.getByRole('navigation', { name: 'Core management' }))
.getByRole('button', { name: 'Triggers' })).toHaveAttribute('aria-current', 'page');
expect(localStorage.getItem('xfesm.locale')).toBe('en-US');
await user.click(screen.getByRole('button', { name: '中文' }));
expect(within(screen.getByRole('navigation', { name: '核心管理' }))
.getByRole('button', { name: '触发器' })).toHaveAttribute('aria-current', 'page');
expect(localStorage.getItem('xfesm.locale')).toBe('zh-CN');
});
it('ties the themed connection indicators to real connection, reconnect, and SSE states', async () => {
const client = themeClient();
vi.mocked(client.session).mockRejectedValueOnce(new Error('Connection refused'));
let emitState: ((state: 'open' | 'error') => void) | undefined;
vi.mocked(client.subscribe).mockImplementation((_onEvent, onState) => { emitState = onState; return () => undefined; });
const user = userEvent.setup();
const { container } = renderShell({ client });
const hud = container.querySelector('.topbar__server')!;
const meter = container.querySelector('.experience-meter')!;
expect(hud).toHaveAttribute('data-connection', 'connecting');
expect(meter).toHaveAttribute('aria-hidden', 'true');
expect(meter).toHaveAttribute('data-connected', 'false');
await waitFor(() => expect(hud).toHaveAttribute('data-connection', 'offline'));
expect(hud).toHaveTextContent('Management API offline');
expect(meter).toHaveAttribute('data-connected', 'false');
expect(screen.getByRole('alert')).toHaveTextContent('Connection refused');
await user.click(screen.getByRole('button', { name: 'Reconnect' }));
await waitFor(() => expect(hud).toHaveAttribute('data-connection', 'online'));
expect(hud).toHaveTextContent('Live connection');
expect(meter).toHaveAttribute('data-connected', 'true');
await waitFor(() => expect(emitState).toBeDefined());
act(() => emitState?.('error'));
expect(hud).toHaveAttribute('data-connection', 'degraded');
expect(hud).toHaveTextContent('Connection degraded');
expect(meter).toHaveAttribute('data-connected', 'false');
act(() => emitState?.('open'));
expect(hud).toHaveAttribute('data-connection', 'online');
expect(meter).toHaveAttribute('data-connected', 'true');
});
it.each([
['triggers', 'main-content--triggers'],
['content', 'main-content--content'],
] as const)('retains the full-width workspace hook for the %s editor', async (route, className) => {
renderShell({ route });
await screen.findByRole('navigation', { name: 'Core management' });
const main = screen.getByRole('main');
expect(main).toHaveClass('main-content', className);
expect(main.parentElement).toHaveClass('workspace');
expect(main.parentElement?.parentElement).toHaveClass('app-shell');
});
it('keeps trigger focus mode inside the full-width shell contract and restores the normal layout on exit', async () => {
localStorage.setItem('xfesm.locale', 'en-US');
location.hash = '/triggers';
const client = themeClient();
const trigger: TriggerDefinition = {
id: 'theme-trigger', groupId: 'theme-group', name: 'Theme trigger', description: '', enabled: true,
mode: 'visual', schemaVersion: 2, event: { type: 'player.join', configuration: {} },
events: [{ nodeId: 'theme-event', type: 'player.join', configuration: {} }], declarations: [], functions: [], statements: [],
conditionMode: 'all', conditions: [], actions: [], script: '', revision: 0, createdBy: 'owner',
createdAt: timestamp, updatedAt: timestamp, migrated: false,
};
const catalog: TriggerCatalog = { defaultMessageSender: 'Server', events: ['player.join'], operators: [], actions: [], actionParameters: {}, variables: [],
schemaVersion: 2, descriptors: [] };
vi.spyOn(client, 'triggerWorkspace').mockResolvedValue({ totalTriggers: 1, groups: [{
id: 'theme-group', name: 'Theme group', description: '', enabled: true, revision: 0, createdBy: 'owner',
createdAt: timestamp, updatedAt: timestamp, migrated: false, triggers: [trigger],
}] });
vi.spyOn(client, 'triggerCatalog').mockResolvedValue(catalog);
vi.spyOn(client, 'menuWorkspace').mockResolvedValue({ menus: [], totalMenus: 0 });
vi.spyOn(client, 'economy').mockResolvedValue({ currencies: [], overview: { currencies: [], observedAt: timestamp } });
vi.spyOn(client, 'triggerExecutions').mockResolvedValue({ items: [] });
vi.spyOn(client, 'triggerEventCaptures').mockResolvedValue({ items: [] });
vi.spyOn(client, 'triggerLibraries').mockResolvedValue({ items: [] });
const user = userEvent.setup();
render(<I18nProvider><ServerProvider client={client}><App /></ServerProvider></I18nProvider>);
await user.click(await screen.findByRole('button', { name: /Theme trigger/ }));
const tree = screen.getByRole('region', { name: 'Program tree' });
const page = tree.closest('.trigger-page')!;
const main = screen.getByRole('main');
const shell = main.closest('.app-shell')!;
await user.click(screen.getByRole('button', { name: 'Focus editor' }));
expect(page).toHaveClass('trigger-page--focused');
expect(main).toHaveClass('main-content--triggers');
expect(tree.parentElement).toHaveClass('galaxy-workbench');
// These direct-child relationships drive the full-width focus-mode CSS selectors.
expect(shell.querySelector(':scope > .sidebar')).toBeInTheDocument();
expect(shell.querySelector(':scope > .workspace > .topbar')).toBeInTheDocument();
expect(shell.querySelector(':scope > .workspace > .main-content')).toBe(main);
expect(screen.getByRole('button', { name: 'Exit focus' })).toHaveAttribute('aria-pressed', 'true');
await user.click(screen.getByRole('button', { name: 'Exit focus' }));
await waitFor(() => expect(page).not.toHaveClass('trigger-page--focused'));
expect(tree).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Focus editor' })).toHaveAttribute('aria-pressed', 'false');
});
});