Files
summercms/admin/tests/shell/SettingsPanel.test.ts
Jakub Zych 85476fa3fe test(quick-261022-imo): settings section panel coverage
- 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
2026-10-22 13:52:20 +02:00

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')
})
})