feat: add home page and refactor workspace entry UI
This commit is contained in:
107
tests/unit/optimistic/asset-actions-generate.test.ts
Normal file
107
tests/unit/optimistic/asset-actions-generate.test.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { QueryClient } from '@tanstack/react-query'
|
||||
import { queryKeys } from '@/lib/query/keys'
|
||||
import type { TaskTargetOverlayMap } from '@/lib/query/task-target-overlay'
|
||||
|
||||
const {
|
||||
apiFetchMock,
|
||||
useQueryClientMock,
|
||||
} = vi.hoisted(() => ({
|
||||
apiFetchMock: vi.fn(),
|
||||
useQueryClientMock: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@tanstack/react-query', async () => {
|
||||
const actual = await vi.importActual<typeof import('@tanstack/react-query')>('@tanstack/react-query')
|
||||
return {
|
||||
...actual,
|
||||
useQueryClient: () => useQueryClientMock(),
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('@/lib/api-fetch', () => ({
|
||||
apiFetch: apiFetchMock,
|
||||
}))
|
||||
|
||||
import { useAssetActions } from '@/lib/query/hooks/useAssets'
|
||||
|
||||
function getOverlay(
|
||||
queryClient: QueryClient,
|
||||
projectId: string,
|
||||
key: string,
|
||||
) {
|
||||
const map = queryClient.getQueryData<TaskTargetOverlayMap>(
|
||||
queryKeys.tasks.targetStateOverlay(projectId),
|
||||
) || {}
|
||||
return map[key] || null
|
||||
}
|
||||
|
||||
function createOkResponse() {
|
||||
return {
|
||||
ok: true,
|
||||
json: async () => ({ success: true }),
|
||||
} as Response
|
||||
}
|
||||
|
||||
describe('useAssetActions.generate optimistic overlay', () => {
|
||||
beforeEach(() => {
|
||||
useQueryClientMock.mockReset()
|
||||
apiFetchMock.mockReset()
|
||||
apiFetchMock.mockResolvedValue(createOkResponse())
|
||||
})
|
||||
|
||||
it('keeps global prop in generating state immediately after submit', async () => {
|
||||
const queryClient = new QueryClient()
|
||||
useQueryClientMock.mockReturnValue(queryClient)
|
||||
|
||||
const actions = useAssetActions({ scope: 'global', kind: 'prop' })
|
||||
await actions.generate({ id: 'prop-1' })
|
||||
|
||||
expect(apiFetchMock).toHaveBeenCalledWith('/api/assets/prop-1/generate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
scope: 'global',
|
||||
kind: 'prop',
|
||||
projectId: undefined,
|
||||
id: 'prop-1',
|
||||
}),
|
||||
})
|
||||
|
||||
const overlay = getOverlay(queryClient, 'global-asset-hub', 'GlobalLocation:prop-1')
|
||||
expect(overlay?.phase).toBe('queued')
|
||||
expect(overlay?.intent).toBe('generate')
|
||||
})
|
||||
|
||||
it('targets project prop generation overlay at the shared location-image task target', async () => {
|
||||
const queryClient = new QueryClient()
|
||||
useQueryClientMock.mockReturnValue(queryClient)
|
||||
|
||||
const actions = useAssetActions({
|
||||
scope: 'project',
|
||||
projectId: 'project-1',
|
||||
kind: 'prop',
|
||||
})
|
||||
await actions.generate({ id: 'prop-2' })
|
||||
|
||||
const overlay = getOverlay(queryClient, 'project-1', 'LocationImage:prop-2')
|
||||
expect(overlay?.phase).toBe('queued')
|
||||
expect(overlay?.intent).toBe('generate')
|
||||
})
|
||||
|
||||
it('clears the overlay when prop generation submission fails', async () => {
|
||||
const queryClient = new QueryClient()
|
||||
useQueryClientMock.mockReturnValue(queryClient)
|
||||
apiFetchMock.mockResolvedValueOnce({
|
||||
ok: false,
|
||||
json: async () => ({}),
|
||||
} as Response)
|
||||
|
||||
const actions = useAssetActions({ scope: 'global', kind: 'prop' })
|
||||
|
||||
await expect(actions.generate({ id: 'prop-3' })).rejects.toThrow('Failed to generate asset render')
|
||||
|
||||
const overlay = getOverlay(queryClient, 'global-asset-hub', 'GlobalLocation:prop-3')
|
||||
expect(overlay).toBeNull()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user