171 lines
5.3 KiB
TypeScript
171 lines
5.3 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||
import { flushPromises } from '@vue/test-utils'
|
||
import router from '@/router'
|
||
import { useApi } from '@/composables/useApi'
|
||
import { initializeLocale, setLocale } from '@/i18n'
|
||
import {
|
||
EXPORT_PATH,
|
||
LIST_PATH,
|
||
SUMMARY_PATH,
|
||
callsTo,
|
||
days,
|
||
findButton,
|
||
mountActivity,
|
||
queryObject,
|
||
rows,
|
||
stripCards,
|
||
textOf,
|
||
unmountActivity,
|
||
} from './activityHarness'
|
||
import { activityItems, makeItem, pageOf, summaryDefault } from './activityFixtures'
|
||
|
||
vi.mock('@/composables/useApi', async (importOriginal) => {
|
||
const actual = await importOriginal<typeof import('@/composables/useApi')>()
|
||
return { ...actual, useApi: vi.fn() }
|
||
})
|
||
|
||
let toastAdd: ReturnType<typeof vi.fn>
|
||
|
||
vi.mock('@nuxt/ui/composables', async (importOriginal) => {
|
||
const actual = await importOriginal<typeof import('@nuxt/ui/composables')>()
|
||
return { ...actual, useToast: () => ({ add: toastAdd }) }
|
||
})
|
||
|
||
beforeEach(() => {
|
||
toastAdd = vi.fn()
|
||
localStorage.clear()
|
||
initializeLocale()
|
||
})
|
||
|
||
afterEach(async () => {
|
||
unmountActivity()
|
||
vi.mocked(useApi).mockReset()
|
||
localStorage.clear()
|
||
initializeLocale()
|
||
await router.push('/login')
|
||
})
|
||
|
||
describe('My activity: a role that is not owner or admin sees its own events', () => {
|
||
it.each([['editor'], [undefined]])('role %s', async (role) => {
|
||
await mountActivity({
|
||
role,
|
||
list: () => pageOf(activityItems, { total: 41 }),
|
||
})
|
||
|
||
expect(textOf(document.body.querySelector('h1'))).toBe('My activity')
|
||
expect(textOf(document.body.querySelector('nav[aria-label="breadcrumb"]'))).toBe(
|
||
'My activity',
|
||
)
|
||
expect(textOf(document.body)).toContain("Everything you've done on this site.")
|
||
expect(stripCards()).toHaveLength(0)
|
||
expect(textOf(document.body)).not.toContain('All people')
|
||
expect(findButton('Export')).toBeUndefined()
|
||
const headers = Array.from(document.body.querySelectorAll('[role="columnheader"]')).map(
|
||
textOf,
|
||
)
|
||
expect(headers).toEqual(['When', 'Action', 'Target', 'Outcome'])
|
||
expect(document.body.querySelector('[data-testid="activity-actor"]')).toBeNull()
|
||
expect(callsTo(SUMMARY_PATH)).toHaveLength(0)
|
||
expect(callsTo(EXPORT_PATH)).toHaveLength(0)
|
||
expect(queryObject(callsTo(LIST_PATH)[0])).toEqual({
|
||
range: '7d',
|
||
page: '1',
|
||
size: '25',
|
||
})
|
||
expect(textOf(document.body.querySelector('[data-testid="activity-pager"]'))).toContain(
|
||
'Showing 1–25 of 41',
|
||
)
|
||
})
|
||
|
||
it('shows no actor line on the cards below md', async () => {
|
||
await mountActivity({ role: 'editor', desktop: false })
|
||
|
||
expect(rows()).toHaveLength(activityItems.length)
|
||
expect(document.body.querySelector('[data-testid="activity-actor"]')).toBeNull()
|
||
})
|
||
|
||
it('shows its own empty copy', async () => {
|
||
await mountActivity({
|
||
role: 'editor',
|
||
list: () => pageOf([], { total: 0 }),
|
||
})
|
||
|
||
expect(textOf(document.body)).toContain('No activity yet')
|
||
expect(textOf(document.body)).toContain(
|
||
'Your actions will appear here once you start working on the site.',
|
||
)
|
||
})
|
||
|
||
it('shows the same details panel with the user position', async () => {
|
||
await mountActivity({
|
||
role: 'editor',
|
||
list: () => pageOf(activityItems, { total: 41 }),
|
||
})
|
||
rows()[0]!.click()
|
||
await flushPromises()
|
||
await vi.waitFor(() => expect(document.body.querySelector('[role="dialog"]')).toBeTruthy())
|
||
|
||
expect(textOf(document.body.querySelector('[role="dialog"]'))).toContain('Event 1 of 41')
|
||
expect((findButton('Previous event') as HTMLButtonElement).disabled).toBe(true)
|
||
expect(textOf(document.body.querySelector('[data-testid="activity-actor"]'))).toBe(
|
||
'MAMarta Alves',
|
||
)
|
||
})
|
||
})
|
||
|
||
describe('The French interface', () => {
|
||
it('composes the chrome, the strip, the sentences and the day separators in French', async () => {
|
||
setLocale('fr')
|
||
await mountActivity({
|
||
summary: () => summaryDefault,
|
||
list: () =>
|
||
pageOf([
|
||
makeItem({ id: 1, created_at: '2026-10-03T12:30:00Z' }),
|
||
makeItem({
|
||
id: 2,
|
||
created_at: '2026-10-03T12:20:00Z',
|
||
outcome: 'failed',
|
||
target: {
|
||
type: 'article',
|
||
id: '8',
|
||
name: 'Spring release',
|
||
exists: true,
|
||
},
|
||
}),
|
||
]),
|
||
})
|
||
|
||
expect(textOf(document.body.querySelector('h1'))).toBe('Activité')
|
||
expect(textOf(findButton('Exporter'))).toBe('Exporter')
|
||
const strip = stripCards().map(textOf)
|
||
expect(strip[0]).toContain('Actions au total')
|
||
expect(strip[1]).toContain('Personnes actives')
|
||
expect(strip[1]).toContain('7 personnes')
|
||
expect(strip[2]).toContain('Actions en échec')
|
||
expect(strip[3]).toContain('Événements de sécurité')
|
||
expect(strip[3]).toContain('11 signalés')
|
||
expect(days()).toEqual(['3 oct. 2026'])
|
||
const sentences = Array.from(
|
||
document.body.querySelectorAll('[data-testid="activity-sentence"]'),
|
||
).map(textOf)
|
||
expect(sentences).toEqual([
|
||
'Article publié : Spring release',
|
||
"Échec de la publication de l'article Spring release",
|
||
])
|
||
const search = document.body.querySelector<HTMLInputElement>('input[type="text"]')!
|
||
expect(search.placeholder).toBe("Rechercher dans l'activité")
|
||
expect(textOf(document.body.querySelector('[data-testid="activity-pager"]'))).toContain(
|
||
'Lignes par page',
|
||
)
|
||
expect(textOf(rows()[0]!)).toContain('Réussie')
|
||
expect(textOf(rows()[1]!)).toContain('Échec')
|
||
})
|
||
|
||
it('shows the French My activity title', async () => {
|
||
setLocale('fr')
|
||
await mountActivity({ role: 'editor' })
|
||
|
||
expect(textOf(document.body.querySelector('h1'))).toBe('Mon activité')
|
||
})
|
||
})
|