114 lines
6.3 KiB
TypeScript
114 lines
6.3 KiB
TypeScript
import '@testing-library/jest-dom/vitest';
|
|
import { fireEvent, render, screen, waitFor, within } from '@testing-library/svelte';
|
|
import { describe, expect, it, vi } from 'vitest';
|
|
import ProjectWorkbench from './ProjectWorkbench.svelte';
|
|
|
|
describe('ProjectWorkbench', () => {
|
|
it('renders project rail, channel sidebar, topbar, and inspector', () => {
|
|
render(ProjectWorkbench, { props: { currentUser: { account: 'david@example.com' } } });
|
|
|
|
expect(screen.getByLabelText('Project list')).toBeInTheDocument();
|
|
expect(screen.getByRole('button', { name: 'Project A1' })).toHaveAttribute('aria-pressed', 'true');
|
|
expect(screen.getByLabelText('Project channels')).toBeInTheDocument();
|
|
expect(screen.getByRole('button', { name: 'Message Flow 36' })).toBeInTheDocument();
|
|
expect(screen.getByLabelText('Global search')).toBeDisabled();
|
|
expect(screen.getByLabelText('Object inspector')).toBeInTheDocument();
|
|
});
|
|
|
|
it('refreshes channels when switching projects', async () => {
|
|
render(ProjectWorkbench, { props: { currentUser: { account: 'david@example.com' } } });
|
|
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Project A2' }));
|
|
|
|
expect(screen.getByRole('button', { name: 'Project A2' })).toHaveAttribute('aria-pressed', 'true');
|
|
expect(screen.getByText('Ops Dashboard')).toBeInTheDocument();
|
|
});
|
|
|
|
it('marks active channel with aria-pressed', async () => {
|
|
render(ProjectWorkbench, { props: { currentUser: { account: 'david@example.com' } } });
|
|
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Work Plan 8' }));
|
|
|
|
expect(screen.getByRole('button', { name: 'Work Plan 8' })).toHaveAttribute('aria-pressed', 'true');
|
|
});
|
|
|
|
it('shows inspected task details in the inspector', async () => {
|
|
render(ProjectWorkbench, { props: { currentUser: { account: 'david@example.com' } } });
|
|
const inspector = screen.getByLabelText('Object inspector');
|
|
|
|
expect(within(inspector).getByRole('button', { name: 'Discussion' })).toHaveAttribute('aria-pressed', 'true');
|
|
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Work Plan 8' }));
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Inspect Confirm homepage information architecture' }));
|
|
|
|
expect(within(inspector).getByRole('heading', { name: 'Confirm homepage information architecture' })).toBeInTheDocument();
|
|
|
|
await fireEvent.click(within(inspector).getByRole('button', { name: 'Properties' }));
|
|
|
|
expect(within(inspector).getByRole('button', { name: 'Properties' })).toHaveAttribute('aria-pressed', 'true');
|
|
expect(within(inspector).getByText('Status')).toBeInTheDocument();
|
|
expect(within(inspector).getByText('Open')).toBeInTheDocument();
|
|
expect(within(inspector).getByText('Owner')).toBeInTheDocument();
|
|
expect(within(inspector).getByText('David')).toBeInTheDocument();
|
|
});
|
|
|
|
it('clears the inspector when the project or channel changes', async () => {
|
|
render(ProjectWorkbench, { props: { currentUser: { account: 'david@example.com' } } });
|
|
const inspector = screen.getByLabelText('Object inspector');
|
|
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Work Plan 8' }));
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Inspect Confirm homepage information architecture' }));
|
|
expect(within(inspector).getByRole('heading', { name: 'Confirm homepage information architecture' })).toBeInTheDocument();
|
|
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Project A2' }));
|
|
expect(within(inspector).getByRole('heading', { name: 'Inspector' })).toBeInTheDocument();
|
|
expect(within(inspector).queryByRole('heading', { name: 'Confirm homepage information architecture' })).not.toBeInTheDocument();
|
|
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Work Plan 8' }));
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Inspect Confirm homepage information architecture' }));
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Message Flow 36' }));
|
|
expect(within(inspector).getByRole('heading', { name: 'Inspector' })).toBeInTheDocument();
|
|
});
|
|
|
|
it('preserves task completion when switching channels within a project', async () => {
|
|
render(ProjectWorkbench, { props: { currentUser: { account: 'david@example.com' } } });
|
|
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Work Plan 8' }));
|
|
const task = screen.getByRole('checkbox', { name: 'Mark Confirm homepage information architecture complete' });
|
|
await fireEvent.click(task);
|
|
expect(task).toBeChecked();
|
|
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Message Flow 36' }));
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Work Plan 8' }));
|
|
expect(screen.getByRole('checkbox', { name: 'Mark Confirm homepage information architecture complete' })).toBeChecked();
|
|
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Project A2' }));
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Work Plan 8' }));
|
|
expect(screen.getByRole('checkbox', { name: 'Mark Confirm homepage information architecture complete' })).not.toBeChecked();
|
|
});
|
|
|
|
it('provides Copy link feedback and disables unavailable archive actions', async () => {
|
|
const originalClipboard = Object.getOwnPropertyDescriptor(navigator, 'clipboard');
|
|
Object.defineProperty(navigator, 'clipboard', {
|
|
configurable: true,
|
|
value: { writeText: vi.fn().mockResolvedValue(undefined) } as Clipboard,
|
|
});
|
|
render(ProjectWorkbench, { props: { currentUser: { account: 'david@example.com' } } });
|
|
const inspector = screen.getByLabelText('Object inspector');
|
|
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Work Plan 8' }));
|
|
await fireEvent.click(screen.getByRole('button', { name: 'Inspect Confirm homepage information architecture' }));
|
|
await fireEvent.click(within(inspector).getByRole('button', { name: 'More' }));
|
|
await fireEvent.click(within(inspector).getByRole('button', { name: 'Copy link' }));
|
|
|
|
await waitFor(() => expect(within(inspector).getByRole('status')).toHaveTextContent('Link copied to clipboard.'));
|
|
expect(within(inspector).getByRole('button', { name: 'Archive is unavailable in this preview' })).toBeDisabled();
|
|
|
|
if (originalClipboard) {
|
|
Object.defineProperty(navigator, 'clipboard', originalClipboard);
|
|
} else {
|
|
Reflect.deleteProperty(navigator, 'clipboard');
|
|
}
|
|
});
|
|
});
|