|
| 1 | +import { render, screen, waitFor } from '@testing-library/react' |
| 2 | +import userEvent from '@testing-library/user-event' |
| 3 | +import { describe, expect, it, vi } from 'vitest' |
| 4 | +import { Options } from '../Options' |
| 5 | +import { setChromeStorageSync, chromeMock } from 'test/mocks/chrome' |
| 6 | + |
| 7 | +const SETTINGS_KEY = 'settings' |
| 8 | + |
| 9 | +describe('Options page', () => { |
| 10 | + it('loads stored settings and allows saving changes', async () => { |
| 11 | + setChromeStorageSync({ |
| 12 | + [SETTINGS_KEY]: { |
| 13 | + autoRender: false, |
| 14 | + hostPatterns: ['https://example.com/*'], |
| 15 | + }, |
| 16 | + }) |
| 17 | + |
| 18 | + const user = userEvent.setup() |
| 19 | + |
| 20 | + render(<Options />) |
| 21 | + |
| 22 | + const toggle = await screen.findByRole('checkbox', { name: /auto-render mermaid diagrams/i }) |
| 23 | + expect(toggle).not.toBeChecked() |
| 24 | + |
| 25 | + await user.click(toggle) |
| 26 | + expect(toggle).toBeChecked() |
| 27 | + |
| 28 | + const patternInputs = screen.getAllByPlaceholderText('https://example.com/*') |
| 29 | + const newPatternInput = patternInputs.at(-1) |
| 30 | + expect(newPatternInput).toBeDefined() |
| 31 | + await user.clear(newPatternInput as HTMLInputElement) |
| 32 | + await user.type(newPatternInput as HTMLInputElement, 'https://docs.example.com/*') |
| 33 | + |
| 34 | + const addButton = screen.getByRole('button', { name: /add pattern/i }) |
| 35 | + await user.click(addButton) |
| 36 | + |
| 37 | + const saveButton = screen.getByRole('button', { name: /save changes/i }) |
| 38 | + await user.click(saveButton) |
| 39 | + |
| 40 | + await waitFor(() => { |
| 41 | + expect(chromeMock.storage.sync.set).toHaveBeenCalled() |
| 42 | + }) |
| 43 | + |
| 44 | + const payload = chromeMock.storage.sync.set.mock.calls.at(-1)?.[0] as Record<string, unknown> |
| 45 | + expect(payload?.[SETTINGS_KEY]).toMatchObject({ |
| 46 | + autoRender: true, |
| 47 | + hostPatterns: ['https://example.com/*', 'https://docs.example.com/*'], |
| 48 | + }) |
| 49 | + }) |
| 50 | + |
| 51 | + it('shows an error message when loading settings fails', async () => { |
| 52 | + // Mock console methods to suppress expected error logs during this test |
| 53 | + const consoleMocks = { |
| 54 | + warn: vi.spyOn(console, 'warn').mockImplementation(() => {}), |
| 55 | + error: vi.spyOn(console, 'error').mockImplementation(() => {}) |
| 56 | + } |
| 57 | + |
| 58 | + chromeMock.storage.sync.get.mockRejectedValueOnce(new Error('nope')) |
| 59 | + |
| 60 | + render(<Options />) |
| 61 | + |
| 62 | + await waitFor(() => { |
| 63 | + expect(screen.getByText(/unable to load settings/i)).toBeInTheDocument() |
| 64 | + }) |
| 65 | + |
| 66 | + // Restore console methods |
| 67 | + consoleMocks.warn.mockRestore() |
| 68 | + consoleMocks.error.mockRestore() |
| 69 | + }) |
| 70 | +}) |
0 commit comments