feat(SPA): users page and invite modal
This commit is contained in:
1 parent
acdef18b37
commit
6afffc1984
20 files changed
+1880
-55
No files matched your search
@@ -36,29 +36,39 @@ afterEach(async () => {
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
describe('DashboardShell renders the three navigation destinations', () => {
|
||||
it('lists Home, Articles and Integration, with only Articles carrying aria-current', async () => {
|
||||
describe('DashboardShell renders the four navigation destinations', () => {
|
||||
it('lists Home, Articles, Users and Integration in order, with only Articles carrying aria-current', async () => {
|
||||
const wrapper = await mountShell('/article')
|
||||
|
||||
const hrefs = wrapper
|
||||
.findAll('nav[aria-label="Main"] a')
|
||||
.map((link) => link.attributes('href'))
|
||||
expect(hrefs).toEqual(['/home', '/article', '/users', '/integration'])
|
||||
|
||||
const home = wrapper.find('a[href="/home"]')
|
||||
const articles = wrapper.find('a[href="/article"]')
|
||||
const users = wrapper.find('a[href="/users"]')
|
||||
const integration = wrapper.find('a[href="/integration"]')
|
||||
|
||||
expect(home.exists()).toBe(true)
|
||||
expect(articles.exists()).toBe(true)
|
||||
expect(integration.exists()).toBe(true)
|
||||
|
||||
expect(articles.attributes('aria-current')).toBe('page')
|
||||
expect(home.attributes('aria-current')).toBeUndefined()
|
||||
expect(users.attributes('aria-current')).toBeUndefined()
|
||||
expect(integration.attributes('aria-current')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('marks Users with aria-current on /users', async () => {
|
||||
const wrapper = await mountShell('/users')
|
||||
|
||||
const users = wrapper.find('a[href="/users"]')
|
||||
expect(users.text()).toContain('Users')
|
||||
expect(users.attributes('aria-current')).toBe('page')
|
||||
expect(wrapper.find('a[href="/article"]').attributes('aria-current')).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('DashboardShell shows the offline banner when the browser reports offline', () => {
|
||||
it('shows the banner while offline and hides it once back online', async () => {
|
||||
const onLineSpy = vi
|
||||
.spyOn(navigator, 'onLine', 'get')
|
||||
.mockReturnValue(false)
|
||||
const onLineSpy = vi.spyOn(navigator, 'onLine', 'get').mockReturnValue(false)
|
||||
|
||||
const wrapper = await mountShell('/article')
|
||||
|
||||
@@ -79,16 +89,12 @@ describe('The sidebar header renders AppLogo and the "RenewCMS" wordmark', () =>
|
||||
const wrapper = await mountShell('/home')
|
||||
|
||||
const header = wrapper.find('[data-slot="header"]')
|
||||
expect(
|
||||
header.find('svg[role="img"][aria-label="RenewCMS"]').exists(),
|
||||
).toBe(true)
|
||||
expect(header.find('svg[role="img"][aria-label="RenewCMS"]').exists()).toBe(true)
|
||||
expect(header.text()).toContain('RenewCMS')
|
||||
expect(header.find('a').exists()).toBe(false)
|
||||
|
||||
const headerHtml = header.html()
|
||||
expect(headerHtml.indexOf('<svg')).toBeLessThan(
|
||||
headerHtml.indexOf('RenewCMS</span>'),
|
||||
)
|
||||
expect(headerHtml.indexOf('<svg')).toBeLessThan(headerHtml.indexOf('RenewCMS</span>'))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -97,9 +103,7 @@ describe('The sidebar collapse trigger toggles the rail and exposes aria-expande
|
||||
await mountShell('/home')
|
||||
|
||||
const collapseButton = () =>
|
||||
document.body.querySelector(
|
||||
'[data-testid="sidebar-collapse"]',
|
||||
) as HTMLButtonElement
|
||||
document.body.querySelector('[data-testid="sidebar-collapse"]') as HTMLButtonElement
|
||||
|
||||
expect(collapseButton().getAttribute('aria-expanded')).toBe('true')
|
||||
|
||||
@@ -120,13 +124,11 @@ describe('A successful logout clears the session and navigates to /login', () =>
|
||||
await mountShell('/home')
|
||||
|
||||
const logOutItem = () =>
|
||||
Array.from(
|
||||
document.body.querySelectorAll('[role="menuitem"]'),
|
||||
).find((el) => el.textContent?.trim() === 'Log out') as HTMLElement
|
||||
Array.from(document.body.querySelectorAll('[role="menuitem"]')).find(
|
||||
(el) => el.textContent?.trim() === 'Log out',
|
||||
) as HTMLElement
|
||||
|
||||
const trigger = document.body.querySelector(
|
||||
'button[aria-haspopup]',
|
||||
) as HTMLButtonElement
|
||||
const trigger = document.body.querySelector('button[aria-haspopup]') as HTMLButtonElement
|
||||
trigger.click()
|
||||
await flushPromises()
|
||||
|
||||
@@ -151,28 +153,16 @@ describe('Collapsed sidebar hides the wordmark and username text but keeps an ac
|
||||
collapseButton.click()
|
||||
await flushPromises()
|
||||
|
||||
const header = document.body.querySelector(
|
||||
'[data-slot="header"]',
|
||||
) as HTMLElement
|
||||
expect(
|
||||
header.querySelector('svg[role="img"][aria-label="RenewCMS"]'),
|
||||
).toBeTruthy()
|
||||
const header = document.body.querySelector('[data-slot="header"]') as HTMLElement
|
||||
expect(header.querySelector('svg[role="img"][aria-label="RenewCMS"]')).toBeTruthy()
|
||||
expect(header.textContent).not.toContain('RenewCMS')
|
||||
expect(header.querySelector('span[aria-hidden="true"]')).toBeNull()
|
||||
|
||||
const footer = document.body.querySelector(
|
||||
'[data-slot="footer"]',
|
||||
) as HTMLElement
|
||||
const footer = document.body.querySelector('[data-slot="footer"]') as HTMLElement
|
||||
expect(footer.textContent).not.toContain('marta')
|
||||
|
||||
const userMenuTrigger = footer.querySelector(
|
||||
'button[aria-haspopup]',
|
||||
) as HTMLButtonElement
|
||||
expect(userMenuTrigger.getAttribute('aria-label')).toBe(
|
||||
'marta — account menu',
|
||||
)
|
||||
expect(
|
||||
footer.querySelector('[data-slot="fallback"]')?.textContent,
|
||||
).toBe('MA')
|
||||
const userMenuTrigger = footer.querySelector('button[aria-haspopup]') as HTMLButtonElement
|
||||
expect(userMenuTrigger.getAttribute('aria-label')).toBe('marta — account menu')
|
||||
expect(footer.querySelector('[data-slot="fallback"]')?.textContent).toBe('MA')
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user