refac: DELETE /v1/user/{id}?expected_role_id=N, user.remove audit event, 409 target_role_not_found, GetAll returns its error, Own-scope visibility filter moved into repos, JSON tags removed from use-case types
This commit is contained in:
1 parent
5d6f378fce
commit
b39a41be88
124 files changed
+8816
-523
No files matched your search
@@ -8,6 +8,7 @@ import { useSessionStore, type Session } from '@/stores/session'
|
||||
import { ApiError, NetworkError, authRedirectPending, useApi } from '@/composables/useApi'
|
||||
import { DESKTOP_WIDTH, MOBILE_WIDTH, setViewportWidth } from '@/components/__tests__/viewport'
|
||||
import { accessFor, customAccess } from '@/test/access'
|
||||
import type { Access } from '@/lib/permissions'
|
||||
|
||||
vi.mock('@/composables/useApi', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@/composables/useApi')>()
|
||||
@@ -942,25 +943,67 @@ function roleRequests(request: ReturnType<typeof vi.fn>) {
|
||||
return request.mock.calls.filter(([path]) => String(path).startsWith('/v1/role'))
|
||||
}
|
||||
|
||||
function sessionWith(access: Access): Session {
|
||||
return { ...MARTA, access }
|
||||
}
|
||||
|
||||
function roleCard() {
|
||||
return [...document.body.querySelectorAll('h2')]
|
||||
.find((heading) => heading.textContent?.trim() === 'Your role')!
|
||||
.closest('section')!
|
||||
}
|
||||
|
||||
function roleBadges() {
|
||||
return [...roleCard().querySelectorAll('span[data-slot="base"]')]
|
||||
.map((badge) => badge.textContent?.trim())
|
||||
.filter((text) => text)
|
||||
}
|
||||
|
||||
describe('Profile: your role', () => {
|
||||
it('shows the role card with the badge, the assigner and the keys sentence', async () => {
|
||||
it.each([
|
||||
['a custom role', contributor(MARTA_ASSIGNER), ['Contributor', 'Custom']],
|
||||
[
|
||||
'the locked Owner',
|
||||
sessionWith({
|
||||
role: { id: 1, name: 'Owner', built_in: true, locked: true },
|
||||
permissions: customAccess('content.read=all').permissions,
|
||||
}),
|
||||
['owner', 'Locked', 'Built-in'],
|
||||
],
|
||||
[
|
||||
'a built-in Writer',
|
||||
sessionWith({
|
||||
role: { id: 3, name: 'Writer', built_in: true, locked: false },
|
||||
permissions: customAccess('content.read=all').permissions,
|
||||
}),
|
||||
['writer', 'Built-in'],
|
||||
],
|
||||
])('shows the badge and the tags for %s in one row', async (_label, session, expected) => {
|
||||
await mountApp({ session })
|
||||
|
||||
expect(roleBadges()).toEqual(expected)
|
||||
expect(roleCard().textContent).toContain(KEYS_SENTENCE)
|
||||
expect(buttonByText(/^See what I can do$/)).toBeDefined()
|
||||
expect(roleCard().querySelector('[class*="i-lucide-list-checks"], svg')).not.toBeNull()
|
||||
})
|
||||
|
||||
it('hides Locked when not locked and Custom when built in', async () => {
|
||||
await mountApp({ session: contributor(MARTA_ASSIGNER) })
|
||||
|
||||
expect(pageText()).toContain('Your role')
|
||||
expect(pageText()).toContain('Contributor')
|
||||
expect(pageText()).toContain('Assigned by Marta Alves')
|
||||
expect(pageText()).toContain(KEYS_SENTENCE)
|
||||
expect(buttonByText(/^See what I can do$/)).toBeDefined()
|
||||
expect(roleCard().textContent).not.toContain('Locked')
|
||||
expect(roleCard().textContent).not.toContain('Built-in')
|
||||
})
|
||||
|
||||
it.each([
|
||||
['an object', MARTA_ASSIGNER],
|
||||
['null', null],
|
||||
['an absent key', undefined],
|
||||
])('renders no Assigned by text for %s', async (_label, assigner) => {
|
||||
])('shows no summary line and no Assigned by text with %s', async (_label, assigner) => {
|
||||
await mountApp({ session: contributor(assigner) })
|
||||
|
||||
expect(pageText()).toContain('Your role')
|
||||
expect(pageText()).not.toContain('Assigned by')
|
||||
expect(pageText()).not.toContain('Creates content and edits only their own.')
|
||||
})
|
||||
|
||||
it('places the card after the Account card', async () => {
|
||||
@@ -970,21 +1013,23 @@ describe('Profile: your role', () => {
|
||||
expect(titles.indexOf('Your role')).toBe(titles.indexOf('Account') + 1)
|
||||
})
|
||||
|
||||
it('follows a refreshed session for the assigner and the role', async () => {
|
||||
it('follows a refreshed session for the badge, the tags and the summary', async () => {
|
||||
await mountApp({ session: contributor(MARTA_ASSIGNER) })
|
||||
expect(roleBadges()).toEqual(['Contributor', 'Custom'])
|
||||
|
||||
useSessionStore().session = {
|
||||
...contributor({ id: 2, name: 'Jonas Weber' }),
|
||||
const writer: Access = {
|
||||
role: { id: 3, name: 'Writer', built_in: true, locked: false },
|
||||
permissions: customAccess('content.read=all').permissions,
|
||||
}
|
||||
await flushPromises()
|
||||
expect(pageText()).toContain('Assigned by Jonas Weber')
|
||||
expect(pageText()).not.toContain('Assigned by Marta Alves')
|
||||
|
||||
const writer = customAccess('content.read=all', 'Writer')
|
||||
useSessionStore().session = { ...MARTA, access: writer }
|
||||
await flushPromises()
|
||||
expect(pageText()).toContain('Writer')
|
||||
expect(pageText()).not.toContain('Assigned by')
|
||||
|
||||
expect(roleBadges()).toEqual(['writer', 'Built-in'])
|
||||
buttonByText(/^See what I can do$/)!.click()
|
||||
await flushPromises()
|
||||
expect(document.body.querySelector('[role="dialog"]')?.textContent).toContain(
|
||||
'A summary of your role, Writer. Read-only.',
|
||||
)
|
||||
})
|
||||
|
||||
it('opens the summary dialog from the session grants without reading roles, and Close returns focus', async () => {
|
||||
|
||||
Reference in new issue
Block a user