feat: release toolbox portal 0.1.0
This commit is contained in:
122
src/App.test.tsx
Normal file
122
src/App.test.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import App from './App';
|
||||
import { PREFERENCES_KEY } from './preferences';
|
||||
import { catalogue, catalogueFetch } from './test/fixtures';
|
||||
|
||||
afterEach(() => vi.unstubAllGlobals());
|
||||
|
||||
describe('portal UI', () => {
|
||||
it('renders app cards and persists accessible pin/hide controls', async () => {
|
||||
vi.stubGlobal('fetch', vi.fn(catalogueFetch()));
|
||||
const user = userEvent.setup();
|
||||
render(<App />);
|
||||
expect(
|
||||
await screen.findByRole('heading', { name: 'PDF Workbench' })
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
'Local processing · no file uploads declared · no telemetry declared'
|
||||
)
|
||||
).toBeInTheDocument();
|
||||
const sourceLinks = screen.getAllByRole('link', {
|
||||
name: 'Source and license',
|
||||
});
|
||||
expect(sourceLinks).toHaveLength(2);
|
||||
expect(
|
||||
sourceLinks.find(
|
||||
(link) =>
|
||||
link.getAttribute('href') ===
|
||||
'https://git.add-ideas.de/zemion/pdf-tools'
|
||||
)
|
||||
).toHaveAttribute('rel', 'noopener noreferrer');
|
||||
expect(
|
||||
sourceLinks.find((link) =>
|
||||
link.getAttribute('href')?.endsWith('/toolbox-portal/src/tag/v0.1.0')
|
||||
)
|
||||
).toBeDefined();
|
||||
const launch = screen.getByRole('link', { name: /open tool/i });
|
||||
expect(
|
||||
new URL(launch.getAttribute('href')!).searchParams.get('toolbox')
|
||||
).toContain('toolbox.catalog.json');
|
||||
|
||||
await user.click(screen.getByRole('button', { name: 'Pin PDF Workbench' }));
|
||||
await waitFor(() =>
|
||||
expect(localStorage.getItem(PREFERENCES_KEY)).toContain(
|
||||
'de.add-ideas.pdf-tools'
|
||||
)
|
||||
);
|
||||
expect(screen.getByText('Pinned')).toBeInTheDocument();
|
||||
|
||||
await user.click(
|
||||
screen.getByRole('button', { name: 'Hide PDF Workbench' })
|
||||
);
|
||||
expect(
|
||||
screen.queryByRole('heading', { name: 'PDF Workbench' })
|
||||
).not.toBeInTheDocument();
|
||||
fireEvent.click(screen.getByRole('checkbox', { name: /show hidden/i }));
|
||||
expect(
|
||||
screen.getByRole('heading', { name: 'PDF Workbench' })
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows a recoverable catalogue error', async () => {
|
||||
const fetchMock = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce(new Response('no', { status: 503 }))
|
||||
.mockImplementation(catalogueFetch());
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
render(<App />);
|
||||
expect(
|
||||
await screen.findByRole('heading', { name: 'Toolbox unavailable' })
|
||||
).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Try again' }));
|
||||
expect(
|
||||
await screen.findByRole('heading', { name: 'PDF Workbench' })
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows a dedicated empty state for a valid catalogue', async () => {
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
vi.fn(
|
||||
catalogueFetch({
|
||||
'/toolbox.catalog.json': Response.json({ ...catalogue, apps: [] }),
|
||||
})
|
||||
)
|
||||
);
|
||||
render(<App />);
|
||||
expect(
|
||||
await screen.findByRole('heading', { name: 'No tools yet' })
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('contains preference focus and restores it to Personalize', async () => {
|
||||
vi.stubGlobal('fetch', vi.fn(catalogueFetch()));
|
||||
const user = userEvent.setup();
|
||||
const { container } = render(<App />);
|
||||
const personalize = screen.getByRole('button', { name: 'Personalize' });
|
||||
|
||||
await user.click(personalize);
|
||||
const dialog = screen.getByRole('dialog', {
|
||||
name: 'Personalize your toolbox',
|
||||
});
|
||||
const close = screen.getByRole('button', { name: 'Close preferences' });
|
||||
expect(close).toHaveFocus();
|
||||
expect(container.querySelector('.site-shell')).toHaveAttribute('inert');
|
||||
expect(dialog).toBeInTheDocument();
|
||||
expect(screen.getByText(/does not transmit them/i)).toHaveTextContent(
|
||||
/Trusted code in another Toolbox app on this site can access same-origin storage/i
|
||||
);
|
||||
|
||||
const reset = screen.getByRole('button', { name: 'Reset' });
|
||||
reset.focus();
|
||||
await user.tab();
|
||||
expect(close).toHaveFocus();
|
||||
|
||||
await user.keyboard('{Escape}');
|
||||
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
|
||||
expect(personalize).toHaveFocus();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user