feat: add authenticated list reading
This commit is contained in:
@@ -4,11 +4,12 @@ import {
|
||||
createRouter,
|
||||
RouterProvider,
|
||||
} from '@tanstack/react-router'
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { routeTree } from '../routeTree.gen'
|
||||
|
||||
const usePostFeed = vi.hoisted(() => vi.fn())
|
||||
const useListChoices = vi.hoisted(() => vi.fn())
|
||||
|
||||
vi.mock('../features/posts/use-post-feed', async (importOriginal) => {
|
||||
const original =
|
||||
@@ -16,6 +17,12 @@ vi.mock('../features/posts/use-post-feed', async (importOriginal) => {
|
||||
return { ...original, usePostFeed }
|
||||
})
|
||||
|
||||
vi.mock('../features/posts/use-list-choices', async (importOriginal) => {
|
||||
const original =
|
||||
await importOriginal<typeof import('../features/posts/use-list-choices')>()
|
||||
return { ...original, useListChoices }
|
||||
})
|
||||
|
||||
vi.mock('./__root', async () => {
|
||||
const { createRootRouteWithContext, Outlet } = await import(
|
||||
'@tanstack/react-router'
|
||||
@@ -41,6 +48,7 @@ describe('post feed route wiring', () => {
|
||||
beforeEach(() => {
|
||||
vi.stubGlobal('scrollTo', vi.fn())
|
||||
usePostFeed.mockReset()
|
||||
useListChoices.mockReset()
|
||||
usePostFeed.mockReturnValue({
|
||||
data: undefined,
|
||||
error: null,
|
||||
@@ -52,6 +60,13 @@ describe('post feed route wiring', () => {
|
||||
isPending: false,
|
||||
refetch: vi.fn(),
|
||||
} as never)
|
||||
useListChoices.mockReturnValue({
|
||||
data: [{ id: '1234567890', name: 'My List', memberCount: 10 }],
|
||||
error: null,
|
||||
isError: false,
|
||||
isPending: false,
|
||||
refetch: vi.fn(),
|
||||
} as never)
|
||||
})
|
||||
|
||||
afterEach(() => vi.unstubAllGlobals())
|
||||
@@ -76,6 +91,44 @@ describe('post feed route wiring', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('keeps an empty list URL disabled', async () => {
|
||||
await renderRoute('/list?target=')
|
||||
|
||||
expect(
|
||||
await screen.findByRole('heading', { name: 'どのリストを読みますか?' }),
|
||||
).toBeVisible()
|
||||
expect(usePostFeed).toHaveBeenCalledWith(undefined)
|
||||
})
|
||||
|
||||
it('turns a manually entered list URL into a deliberate request', async () => {
|
||||
await renderRoute('/list?target=1234567890')
|
||||
|
||||
await waitFor(() =>
|
||||
expect(usePostFeed).toHaveBeenCalledWith({
|
||||
kind: 'list',
|
||||
target: '1234567890',
|
||||
}),
|
||||
)
|
||||
expect(
|
||||
await screen.findByRole('link', { name: 'リスト', current: 'page' }),
|
||||
).toBeVisible()
|
||||
})
|
||||
|
||||
it('turns a selected authenticated list into a deliberate request', async () => {
|
||||
await renderRoute('/list?target=')
|
||||
|
||||
fireEvent.click(
|
||||
await screen.findByRole('link', { name: /My List.*10 メンバー/ }),
|
||||
)
|
||||
|
||||
await waitFor(() =>
|
||||
expect(usePostFeed).toHaveBeenCalledWith({
|
||||
kind: 'list',
|
||||
target: '1234567890',
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('forwards every manually entered search control', async () => {
|
||||
await renderRoute('/search?q=AI%20lang%3Aja&product=Top&following=true')
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { AppShell } from '#/components/app-shell'
|
||||
import { ListForm } from '#/features/posts/components/list-form'
|
||||
import { ListPicker } from '#/features/posts/components/list-picker'
|
||||
import { PostFeed } from '#/features/posts/components/post-feed'
|
||||
import { listRouteSearchSchema } from '#/features/posts/inputs'
|
||||
|
||||
export const Route = createFileRoute('/list')({
|
||||
validateSearch: (search) => listRouteSearchSchema.parse(search),
|
||||
component: ListRoute,
|
||||
})
|
||||
|
||||
function ListRoute() {
|
||||
const { target } = Route.useSearch()
|
||||
const navigate = Route.useNavigate()
|
||||
return (
|
||||
<AppShell active="list">
|
||||
<h1>どのリストを読みますか?</h1>
|
||||
<p className="intro">
|
||||
自分のリストを選ぶか、リストURLを入力してください。
|
||||
</p>
|
||||
<ListPicker selectedId={target || undefined} />
|
||||
<ListForm
|
||||
initialTarget={target}
|
||||
key={target}
|
||||
onSubmit={(nextTarget) => navigate({ search: { target: nextTarget } })}
|
||||
/>
|
||||
<PostFeed request={target ? { kind: 'list', target } : undefined} />
|
||||
</AppShell>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user