test(permission): cover settings confirmation paths

This commit is contained in:
Yichen Jiang
2026-07-31 13:45:22 +08:00
parent 7aa126e0d5
commit 8ab6473660
3 changed files with 17 additions and 10 deletions

View File

@@ -41,7 +41,7 @@ export type PermissionRowProps =
export function PermissionRow({ load, select, usePermission, t }: PermissionRowProps) { export function PermissionRow({ load, select, usePermission, t }: PermissionRowProps) {
const state = usePermission(snapshot => snapshot) const state = usePermission(snapshot => snapshot)
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const [confirmation, setConfirmation] = useState<string | null>(null) const [confirmingFullAccess, setConfirmingFullAccess] = useState(false)
const [acknowledged, setAcknowledged] = useState(false) const [acknowledged, setAcknowledged] = useState(false)
useEffect(() => { useEffect(() => {
@@ -52,12 +52,12 @@ export function PermissionRow({ load, select, usePermission, t }: PermissionRowP
if (state.writable && state.status !== 'unavailable') return if (state.writable && state.status !== 'unavailable') return
setOpen(false) setOpen(false)
setAcknowledged(false) setAcknowledged(false)
setConfirmation(null) setConfirmingFullAccess(false)
}, [state.status, state.writable]) }, [state.status, state.writable])
if (state.status === 'unavailable') return null if (state.status === 'unavailable') return null
const selected = state.options.find(option => option.id === state.currentValue) const selected = state.options.find(option => option.id === state.currentValue)
const busy = state.status === 'loading' || state.status === 'saving' || confirmation !== null const busy = state.status === 'loading' || state.status === 'saving' || confirmingFullAccess
const label = selected?.label const label = selected?.label
?? (busy ? t('loading') : t('unavailable')) ?? (busy ? t('loading') : t('unavailable'))
const description: string = state.error ?? t('description') const description: string = state.error ?? t('description')
@@ -79,7 +79,7 @@ export function PermissionRow({ load, select, usePermission, t }: PermissionRowP
if (id === state.currentValue) return if (id === state.currentValue) return
if (id === FULL_ACCESS_PRESET) { if (id === FULL_ACCESS_PRESET) {
setAcknowledged(false) setAcknowledged(false)
setConfirmation(id) setConfirmingFullAccess(true)
return return
} }
void select(id) void select(id)
@@ -102,7 +102,7 @@ export function PermissionRow({ load, select, usePermission, t }: PermissionRowP
/> />
</div> </div>
<RiskConfirmation <RiskConfirmation
open={confirmation !== null} open={confirmingFullAccess}
title={t('confirm.title')} title={t('confirm.title')}
description={t('confirm.description')} description={t('confirm.description')}
acknowledgeLabel={t('confirm.acknowledge')} acknowledgeLabel={t('confirm.acknowledge')}
@@ -113,14 +113,12 @@ export function PermissionRow({ load, select, usePermission, t }: PermissionRowP
onAcknowledgedChange={setAcknowledged} onAcknowledgedChange={setAcknowledged}
onCancel={() => { onCancel={() => {
setAcknowledged(false) setAcknowledged(false)
setConfirmation(null) setConfirmingFullAccess(false)
}} }}
onConfirm={() => { onConfirm={() => {
if (!acknowledged || confirmation === null) return
const preset = confirmation
setAcknowledged(false) setAcknowledged(false)
setConfirmation(null) setConfirmingFullAccess(false)
void select(preset) void select(FULL_ACCESS_PRESET)
}} }}
/> />
</> </>

View File

@@ -104,6 +104,8 @@ describe('ui-permission browser plugin', () => {
expect(injected?.hooks.permission).toBeDefined() expect(injected?.hooks.permission).toBeDefined()
expect(typeof injected?.load).toBe('function') expect(typeof injected?.load).toBe('function')
expect(typeof injected?.select).toBe('function') expect(typeof injected?.select).toBe('function')
await injected!.load()
await injected!.select('read-only')
}) })
it('availability follows the projection key; options mark the current value active and exclude custom', async () => { it('availability follows the projection key; options mark the current value active and exclude custom', async () => {

View File

@@ -75,6 +75,9 @@ describe('PermissionRow', () => {
fireEvent.click(button) fireEvent.click(button)
expect(button.getAttribute('aria-expanded')).toBe('false') expect(button.getAttribute('aria-expanded')).toBe('false')
fireEvent.click(button) fireEvent.click(button)
fireEvent.click(screen.getByRole('menuitem', { name: 'Read Only' }))
expect(mutate).not.toHaveBeenCalled()
fireEvent.click(button)
fireEvent.click(screen.getByRole('menuitem', { name: 'Workspace Write' })) fireEvent.click(screen.getByRole('menuitem', { name: 'Workspace Write' }))
await screen.findByRole('button', { name: 'Workspace Write' }) await screen.findByRole('button', { name: 'Workspace Write' })
expect(mutate).toHaveBeenCalledOnce() expect(mutate).toHaveBeenCalledOnce()
@@ -92,6 +95,10 @@ describe('PermissionRow', () => {
fireEvent.click(await screen.findByRole('button', { name: 'Read Only' })) fireEvent.click(await screen.findByRole('button', { name: 'Read Only' }))
fireEvent.click(screen.getByRole('menuitem', { name: 'Full access' })) fireEvent.click(screen.getByRole('menuitem', { name: 'Full access' }))
expect(mutate).not.toHaveBeenCalled() expect(mutate).not.toHaveBeenCalled()
fireEvent.click(screen.getByRole('button', { name: 'Cancel' }))
expect(screen.queryByRole('dialog', { name: 'Enable Full access?' })).toBeNull()
fireEvent.click(screen.getByRole('button', { name: 'Read Only' }))
fireEvent.click(screen.getByRole('menuitem', { name: 'Full access' }))
const dialog = screen.getByRole('dialog', { name: 'Enable Full access?' }) const dialog = screen.getByRole('dialog', { name: 'Enable Full access?' })
const enable = screen.getByRole('button', { name: 'Enable Full access' }) const enable = screen.getByRole('button', { name: 'Enable Full access' })
expect((enable as HTMLButtonElement).disabled).toBe(true) expect((enable as HTMLButtonElement).disabled).toBe(true)