178 lines
5.8 KiB
TypeScript
178 lines
5.8 KiB
TypeScript
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
|
import { beforeEach, expect, it, vi } from 'vitest'
|
|
import type { Connection } from '../connections/model'
|
|
import { ColumnEditor } from './column-editor'
|
|
|
|
const lists = vi.hoisted(() => vi.fn())
|
|
vi.mock('@tanstack/react-start', () => ({ useServerFn: (fn: unknown) => fn }))
|
|
vi.mock('#/features/platforms/mastodon-server-functions', () => ({
|
|
loadMastodonLists: lists,
|
|
}))
|
|
vi.mock('#/features/posts/use-list-choices', () => ({
|
|
useListChoices: () => ({
|
|
isPending: false,
|
|
isError: false,
|
|
data: [],
|
|
refetch: vi.fn(),
|
|
}),
|
|
}))
|
|
const connections: Connection[] = [
|
|
{
|
|
id: 'twitter',
|
|
platform: 'twitter',
|
|
origin: 'https://relay.invalid',
|
|
accountId: null,
|
|
displayName: 'Twitter account',
|
|
status: 'connected',
|
|
},
|
|
{
|
|
id: 'mastodon-first',
|
|
platform: 'mastodon',
|
|
origin: 'https://mastodon.invalid',
|
|
accountId: '1',
|
|
displayName: '@first',
|
|
status: 'connected',
|
|
},
|
|
{
|
|
id: 'mastodon-second',
|
|
platform: 'mastodon',
|
|
origin: 'https://mastodon.invalid',
|
|
accountId: '2',
|
|
displayName: '@second',
|
|
status: 'connected',
|
|
},
|
|
]
|
|
|
|
beforeEach(() => {
|
|
lists
|
|
.mockReset()
|
|
.mockImplementation(
|
|
async ({ data }: { data: { connectionId: string } }) => ({
|
|
lists: [
|
|
{
|
|
id: data.connectionId === 'mastodon-first' ? '10' : '20',
|
|
name: data.connectionId,
|
|
isPrivate: true,
|
|
},
|
|
],
|
|
}),
|
|
)
|
|
})
|
|
|
|
function show() {
|
|
const onSave = vi.fn().mockResolvedValue(true)
|
|
render(
|
|
<QueryClientProvider
|
|
client={
|
|
new QueryClient({ defaultOptions: { queries: { retry: false } } })
|
|
}
|
|
>
|
|
<ColumnEditor
|
|
connections={connections}
|
|
onSave={onSave}
|
|
onCancel={vi.fn()}
|
|
/>
|
|
</QueryClientProvider>,
|
|
)
|
|
fireEvent.change(screen.getByLabelText('カラム名'), {
|
|
target: { value: '調査' },
|
|
})
|
|
return onSave
|
|
}
|
|
|
|
it('creates a Mastodon search without Twitter ordering or following fields', async () => {
|
|
const save = show()
|
|
fireEvent.change(screen.getByLabelText('接続プロファイル'), {
|
|
target: { value: 'mastodon-first' },
|
|
})
|
|
expect(screen.queryByLabelText('表示順')).toBeNull()
|
|
expect(screen.queryByLabelText('フォロー中のみ')).toBeNull()
|
|
expect(screen.getByText(/結果が0件でも/)).toBeVisible()
|
|
fireEvent.change(screen.getByLabelText('Mastodonの検索条件'), {
|
|
target: { value: 'WebMCP' },
|
|
})
|
|
fireEvent.submit(screen.getByRole('form', { name: 'カラムを追加' }))
|
|
await waitFor(() =>
|
|
expect(save).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
connectionId: 'mastodon-first',
|
|
source: { platform: 'mastodon', kind: 'search', query: 'WebMCP' },
|
|
}),
|
|
),
|
|
)
|
|
})
|
|
|
|
it('creates hashtags and resets unsupported source kind when changing to Twitter', async () => {
|
|
const save = show()
|
|
fireEvent.change(screen.getByLabelText('接続プロファイル'), {
|
|
target: { value: 'mastodon-first' },
|
|
})
|
|
fireEvent.change(screen.getByLabelText('カラムの種類'), {
|
|
target: { value: 'hashtag' },
|
|
})
|
|
fireEvent.change(screen.getByLabelText('ハッシュタグ'), {
|
|
target: { value: 'WebMCP' },
|
|
})
|
|
fireEvent.submit(screen.getByRole('form', { name: 'カラムを追加' }))
|
|
await waitFor(() =>
|
|
expect(save).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
source: { platform: 'mastodon', kind: 'hashtag', target: 'WebMCP' },
|
|
}),
|
|
),
|
|
)
|
|
fireEvent.change(screen.getByLabelText('接続プロファイル'), {
|
|
target: { value: 'twitter' },
|
|
})
|
|
expect(screen.getByLabelText('カラムの種類')).toHaveValue('search')
|
|
expect(screen.getByLabelText('Twitterの検索条件')).toHaveValue('')
|
|
expect(screen.queryByRole('option', { name: 'ハッシュタグ' })).toBeNull()
|
|
})
|
|
|
|
it('loads lists for each account and clears the selected list when the binding changes', async () => {
|
|
show()
|
|
fireEvent.change(screen.getByLabelText('接続プロファイル'), {
|
|
target: { value: 'mastodon-first' },
|
|
})
|
|
fireEvent.change(screen.getByLabelText('カラムの種類'), {
|
|
target: { value: 'list' },
|
|
})
|
|
fireEvent.click(await screen.findByRole('button', { name: 'mastodon-first' }))
|
|
expect(screen.getByLabelText('リスト')).toHaveValue('10')
|
|
fireEvent.change(screen.getByLabelText('接続プロファイル'), {
|
|
target: { value: 'mastodon-second' },
|
|
})
|
|
expect(screen.getByLabelText('リスト')).toHaveValue('')
|
|
fireEvent.click(
|
|
await screen.findByRole('button', { name: 'mastodon-second' }),
|
|
)
|
|
expect(screen.getByLabelText('リスト')).toHaveValue('20')
|
|
expect(lists).toHaveBeenCalledWith({
|
|
data: { connectionId: 'mastodon-second' },
|
|
})
|
|
})
|
|
|
|
it('preserves title and Twitter search options after a rejected save', async () => {
|
|
const save = show()
|
|
save.mockResolvedValue(false)
|
|
fireEvent.change(screen.getByLabelText('Twitterの検索条件'), {
|
|
target: { value: 'from:owner WebMCP' },
|
|
})
|
|
fireEvent.change(screen.getByLabelText('表示順'), {
|
|
target: { value: 'Top' },
|
|
})
|
|
fireEvent.click(screen.getByLabelText('フォロー中のみ'))
|
|
fireEvent.submit(screen.getByRole('form', { name: 'カラムを追加' }))
|
|
await waitFor(() => expect(save).toHaveBeenCalledOnce())
|
|
expect(screen.getByLabelText('カラム名')).toHaveValue('調査')
|
|
expect(screen.getByLabelText('Twitterの検索条件')).toHaveValue(
|
|
'from:owner WebMCP',
|
|
)
|
|
expect(screen.getByLabelText('表示順')).toHaveValue('Top')
|
|
expect(screen.getByLabelText('フォロー中のみ')).toBeChecked()
|
|
fireEvent.submit(screen.getByRole('form', { name: 'カラムを追加' }))
|
|
await waitFor(() => expect(save).toHaveBeenCalledTimes(2))
|
|
expect(save.mock.calls[1]?.[0].source).toEqual(save.mock.calls[0]?.[0].source)
|
|
})
|