- settingsSectionOf: null cases, category order, link entry placement - SettingsPanel: labels, links, current entry, empty category, collapse - AppShell: hidden cases, settings-link controllers, collapse, offset, narrow, focus hand-off
100 lines
3.6 KiB
TypeScript
100 lines
3.6 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils'
|
|
import SettingsPanel from '../../src/components/shell/SettingsPanel.vue'
|
|
import { SIDEBAR_KEY, setCollapsed, sidebarCollapsed } from '../../src/state/useSidebar'
|
|
import {
|
|
setSettings,
|
|
settingsEntry,
|
|
settingsLinkFor,
|
|
settingsSectionOf,
|
|
type SettingsSection,
|
|
} from '../../src/state/useSettings'
|
|
import { settingsFixture } from '../fixtures/typed'
|
|
import { resetState, routerAt, signIn } from '../helpers'
|
|
|
|
beforeEach(() => {
|
|
resetState()
|
|
setCollapsed(false)
|
|
})
|
|
|
|
afterEach(() => {
|
|
setCollapsed(false)
|
|
document.body.innerHTML = ''
|
|
})
|
|
|
|
enableAutoUnmount(afterEach)
|
|
|
|
const locales = {
|
|
...settingsFixture.list.data[0]!,
|
|
code: 'locales',
|
|
label: 'Locales',
|
|
model: '',
|
|
controller: 'acme.lang.locales',
|
|
order: 15,
|
|
}
|
|
|
|
async function mountPanel(path: string, section: SettingsSection) {
|
|
await signIn()
|
|
const router = await routerAt(path)
|
|
const wrapper = mount(SettingsPanel, { props: { section }, global: { plugins: [router] }, attachTo: document.body })
|
|
await flushPromises()
|
|
return wrapper
|
|
}
|
|
|
|
describe('settings panel', () => {
|
|
it('is a labelled region with the category and its pages in section order', async () => {
|
|
setSettings(settingsFixture.list.data)
|
|
const wrapper = await mountPanel('/settings/search', settingsSectionOf(settingsEntry('search'))!)
|
|
const aside = wrapper.find('aside')
|
|
expect(aside.attributes('aria-label')).toBe('Sekcje')
|
|
expect(aside.attributes('data-settings-panel')).toBeDefined()
|
|
expect(aside.find('span').text()).toBe('System')
|
|
const links = wrapper.findAll('a')
|
|
expect(links.map((link) => [link.text(), link.attributes('href'), link.attributes('data-settings-panel-item')])).toEqual([
|
|
['Mail', '/settings/mail', 'mail'],
|
|
['Search', '/settings/search', 'search'],
|
|
])
|
|
expect(links[0]!.attributes('aria-current')).toBeUndefined()
|
|
expect(links[1]!.attributes('aria-current')).toBe('page')
|
|
})
|
|
|
|
it('links a settings link entry to its controller and highlights only it', async () => {
|
|
setSettings([...settingsFixture.list.data, locales])
|
|
const wrapper = await mountPanel('/acme/lang/locales', settingsSectionOf(settingsLinkFor('acme.lang.locales'))!)
|
|
const links = wrapper.findAll('a')
|
|
expect(links.map((link) => [link.text(), link.attributes('href')])).toEqual([
|
|
['Mail', '/settings/mail'],
|
|
['Locales', '/acme/lang/locales'],
|
|
['Search', '/settings/search'],
|
|
])
|
|
expect(links.filter((link) => link.attributes('aria-current') === 'page').map((link) => link.text())).toEqual([
|
|
'Locales',
|
|
])
|
|
})
|
|
|
|
it('falls back to "Ustawienia" for an empty category', async () => {
|
|
const [search, mail] = settingsFixture.list.data
|
|
const section: SettingsSection = {
|
|
category: '',
|
|
current: { ...mail!, category: '' },
|
|
entries: [
|
|
{ ...mail!, category: '' },
|
|
{ ...search!, category: '' },
|
|
],
|
|
}
|
|
const wrapper = await mountPanel('/settings/mail', section)
|
|
expect(wrapper.find('aside span').text()).toBe('Ustawienia')
|
|
})
|
|
|
|
it('collapses on "Zwiń menu" and persists the choice', async () => {
|
|
setSettings(settingsFixture.list.data)
|
|
const wrapper = await mountPanel('/settings/mail', settingsSectionOf(settingsEntry('mail'))!)
|
|
const button = wrapper.find('[data-sidebar-collapse]')
|
|
expect(button.attributes('aria-label')).toBe('Zwiń menu')
|
|
expect(button.attributes('type')).toBe('button')
|
|
await button.trigger('click')
|
|
expect(sidebarCollapsed.value).toBe(true)
|
|
expect(window.localStorage.getItem(SIDEBAR_KEY)).toBe('true')
|
|
})
|
|
})
|