mirror of
https://github.com/langgenius/dify.git
synced 2026-09-05 08:48:10 +08:00
189 lines
5.0 KiB
TypeScript
189 lines
5.0 KiB
TypeScript
import { screen } from '@testing-library/react'
|
|
import { renderWithConsoleQuery as render } from '@/test/console/query-data'
|
|
import RosterPage from '../page'
|
|
|
|
const infiniteOptions = vi.hoisted(() => vi.fn((options) => options))
|
|
const useInfiniteQueryOptions = vi.hoisted(() => vi.fn())
|
|
const queryValues = vi.hoisted(() => ({
|
|
created_by_me: false,
|
|
filter: 'all',
|
|
keyword: '',
|
|
sort_by: 'last_modified',
|
|
}))
|
|
const rosterQueryState = vi.hoisted(() => ({
|
|
data: {
|
|
pages: [
|
|
{
|
|
data: [],
|
|
has_more: false,
|
|
page: 1,
|
|
publication_counts: { drafts: 2, published: 1 },
|
|
},
|
|
],
|
|
} as
|
|
| {
|
|
pages: Array<{
|
|
data: never[]
|
|
has_more: boolean
|
|
page: number
|
|
publication_counts: { drafts: number; published: number }
|
|
}>
|
|
}
|
|
| undefined,
|
|
}))
|
|
|
|
vi.mock('@/service/client', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('@/service/client')>()
|
|
const agentQuery = actual.consoleQuery.agent
|
|
const agentQueryWithInputCapture = new Proxy(agentQuery, {
|
|
get(target, property, receiver) {
|
|
if (property !== 'get') return Reflect.get(target, property, receiver)
|
|
|
|
return {
|
|
...agentQuery.get,
|
|
infiniteOptions,
|
|
}
|
|
},
|
|
})
|
|
|
|
return {
|
|
...actual,
|
|
consoleQuery: new Proxy(actual.consoleQuery, {
|
|
get(target, property, receiver) {
|
|
if (property === 'agent') return agentQueryWithInputCapture
|
|
|
|
return Reflect.get(target, property, receiver)
|
|
},
|
|
}),
|
|
}
|
|
})
|
|
|
|
vi.mock('@/context/i18n', () => ({
|
|
useDocLink: () => (path: string) => path,
|
|
}))
|
|
|
|
vi.mock('nuqs', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('nuqs')>()
|
|
return {
|
|
...actual,
|
|
useQueryState: (name: keyof typeof queryValues) => [queryValues[name], vi.fn()],
|
|
}
|
|
})
|
|
|
|
vi.mock('@tanstack/react-query', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('@tanstack/react-query')>()
|
|
return {
|
|
...actual,
|
|
useInfiniteQuery: (options: unknown) => {
|
|
useInfiniteQueryOptions(options)
|
|
return {
|
|
data: rosterQueryState.data,
|
|
error: null,
|
|
fetchNextPage: vi.fn(),
|
|
hasNextPage: false,
|
|
isFetchNextPageError: false,
|
|
isFetching: false,
|
|
isFetchingNextPage: false,
|
|
isLoadingError: false,
|
|
isPending: false,
|
|
isRefetchError: false,
|
|
refetch: vi.fn(),
|
|
}
|
|
},
|
|
}
|
|
})
|
|
|
|
vi.mock('../components/agent-roster-list', () => ({
|
|
AgentRosterList: () => <div>Agent roster</div>,
|
|
}))
|
|
|
|
vi.mock('../components/roster-toolbar', () => ({
|
|
RosterToolbar: ({
|
|
publicationCounts,
|
|
}: {
|
|
publicationCounts: { drafts: number; published: number }
|
|
}) => (
|
|
<div>{`Roster toolbar: ${publicationCounts.published} published, ${publicationCounts.drafts} drafts`}</div>
|
|
),
|
|
}))
|
|
|
|
describe('RosterPage', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
queryValues.created_by_me = false
|
|
queryValues.filter = 'all'
|
|
queryValues.keyword = ''
|
|
queryValues.sort_by = 'last_modified'
|
|
rosterQueryState.data = {
|
|
pages: [
|
|
{
|
|
data: [],
|
|
has_more: false,
|
|
page: 1,
|
|
publication_counts: { drafts: 2, published: 1 },
|
|
},
|
|
],
|
|
}
|
|
})
|
|
|
|
it('uses the localized roster title for the page heading', () => {
|
|
render(<RosterPage />)
|
|
|
|
expect(screen.getByRole('heading', { name: 'agentV2.roster.title' })).toBeInTheDocument()
|
|
expect(screen.getByRole('region', { name: 'agentV2.roster.title' })).toBeInTheDocument()
|
|
})
|
|
|
|
it('reconciles the route title with client branding', () => {
|
|
render(<RosterPage />, {
|
|
systemFeatures: {
|
|
branding: {
|
|
enabled: true,
|
|
application_title: 'Acme',
|
|
},
|
|
},
|
|
})
|
|
|
|
expect(document.title).toBe('agentV2.roster.title - Acme')
|
|
})
|
|
|
|
it('uses the generated publication filter and server-owned counts', () => {
|
|
queryValues.filter = 'drafts'
|
|
|
|
render(<RosterPage />)
|
|
|
|
const options = infiniteOptions.mock.lastCall?.[0]
|
|
expect(options).toBeDefined()
|
|
if (!options || typeof options.input !== 'function')
|
|
throw new Error('Expected paginated query input')
|
|
|
|
expect(options.input(1)).toEqual({
|
|
query: {
|
|
limit: 30,
|
|
page: 1,
|
|
publication_status: 'drafts',
|
|
sort_by: 'last_modified',
|
|
},
|
|
})
|
|
expect(screen.getByText('Roster toolbar: 1 published, 2 drafts')).toBeInTheDocument()
|
|
})
|
|
|
|
it('configures the roster query to keep previous filter data', () => {
|
|
render(<RosterPage />)
|
|
|
|
const options = useInfiniteQueryOptions.mock.lastCall?.[0] as {
|
|
placeholderData?: (previousData: object) => object | undefined
|
|
}
|
|
const previousData = { pages: [{ data: ['previous agent'] }] }
|
|
|
|
expect(options.placeholderData?.(previousData)).toBe(previousData)
|
|
})
|
|
|
|
it('renders stable zero counts before the first server response', () => {
|
|
rosterQueryState.data = undefined
|
|
|
|
render(<RosterPage />)
|
|
|
|
expect(screen.getByText('Roster toolbar: 0 published, 0 drafts')).toBeInTheDocument()
|
|
})
|
|
})
|