- 41 unit and component suites under admin/tests/{app,state,shell,list,form,relation,views,ui}
covering states and a11y roles; every src module is imported by a test
- typed fixture helper assigns each JSON fixture to its generated OpenAPI type
- fix: iconFor ignores inherited object members such as "constructor"
- fix: field controls import ./control instead of the registry (import cycle
left a renderer unregistered depending on module load order)
- fix: dropdown shows the placeholder for an unknown stored value next to an emptyOption
- fix: list announces a failed schema load even when the rows arrive after it
- tailwind no longer scans admin/tests; boardwalk/dist rebuilt
89 lines
3.6 KiB
TypeScript
89 lines
3.6 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils'
|
|
import UserMenu from '../../src/components/shell/UserMenu.vue'
|
|
import { currentUser } from '../../src/state/useAuth'
|
|
import { API, profile, requestsTo, resetState, routerAt, signIn, wait } from '../helpers'
|
|
|
|
async function mountMenu(user: Partial<typeof profile.data> | null) {
|
|
let calls: Request[] = []
|
|
if (user) {
|
|
calls = await signIn({
|
|
[`GET ${API}/auth/me`]: { body: { data: { ...profile.data, ...user }, meta: {} } },
|
|
[`POST ${API}/auth/logout`]: { body: { data: { status: 'logged_out' }, meta: {} } },
|
|
})
|
|
}
|
|
const router = await routerAt('/acme/demo/widgets')
|
|
const wrapper = mount(UserMenu, { global: { plugins: [router] }, attachTo: document.body })
|
|
await flushPromises()
|
|
return { wrapper, router, calls }
|
|
}
|
|
|
|
async function open(wrapper: ReturnType<typeof mount>): Promise<HTMLElement> {
|
|
const trigger = wrapper.find('[data-user-menu]')
|
|
await trigger.trigger('keydown', { key: 'Enter' })
|
|
await flushPromises()
|
|
const content = document.querySelector<HTMLElement>('[data-user-menu-content]')
|
|
expect(content).not.toBeNull()
|
|
return content!
|
|
}
|
|
|
|
beforeEach(() => {
|
|
resetState()
|
|
})
|
|
|
|
afterEach(() => {
|
|
document.body.innerHTML = ''
|
|
})
|
|
|
|
enableAutoUnmount(afterEach)
|
|
|
|
describe('user menu', () => {
|
|
it('labels the trigger with the name and shows initials, name and role', async () => {
|
|
const { wrapper } = await mountMenu({})
|
|
const trigger = wrapper.find('[data-user-menu]')
|
|
expect(trigger.attributes('aria-label')).toBe('Menu użytkownika: Dana Dev')
|
|
expect(trigger.attributes('aria-haspopup')).toBe('menu')
|
|
expect(trigger.attributes('disabled')).toBeUndefined()
|
|
expect(wrapper.find('[data-user-initials]').text()).toBe('DD')
|
|
expect(wrapper.find('[data-user-initials]').attributes('aria-hidden')).toBe('true')
|
|
expect(wrapper.find('[data-user-role]').text()).toBe('Developer')
|
|
})
|
|
|
|
it('falls back to the login for the name and initials and hides a missing role', async () => {
|
|
const { wrapper } = await mountMenu({ first_name: ' ', last_name: '', login: 'root', role: undefined })
|
|
expect(wrapper.find('[data-user-identity]').text()).toBe('root')
|
|
expect(wrapper.find('[data-user-initials]').text()).toBe('RO')
|
|
expect(wrapper.find('[data-user-role]').exists()).toBe(false)
|
|
})
|
|
|
|
it('uses a single initial for a single name', async () => {
|
|
const { wrapper } = await mountMenu({ first_name: 'ada', last_name: '' })
|
|
expect(wrapper.find('[data-user-initials]').text()).toBe('A')
|
|
})
|
|
|
|
it('is disabled without a signed-in admin', async () => {
|
|
const { wrapper } = await mountMenu(null)
|
|
expect(currentUser.value).toBeNull()
|
|
expect(wrapper.find('[data-user-menu]').attributes('disabled')).toBeDefined()
|
|
expect(wrapper.find('[data-user-initials]').text()).toBe('')
|
|
})
|
|
|
|
it('opens a menu with the e-mail and logs out to the login route', async () => {
|
|
const { wrapper, router, calls } = await mountMenu({})
|
|
const content = await open(wrapper)
|
|
expect(content.getAttribute('role')).toBe('menu')
|
|
expect(content.textContent).toContain('dev@example.test')
|
|
const item = content.querySelector<HTMLElement>('[data-action="logout"]')!
|
|
expect(item.getAttribute('role')).toBe('menuitem')
|
|
expect(item.textContent?.trim()).toBe('Wyloguj')
|
|
|
|
item.click()
|
|
await flushPromises()
|
|
await wait(0)
|
|
await flushPromises()
|
|
expect(requestsTo(calls, 'POST', `${API}/auth/logout`)).toHaveLength(1)
|
|
expect(currentUser.value).toBeNull()
|
|
expect(router.currentRoute.value.name).toBe('login')
|
|
})
|
|
})
|