Files
SkinbaseNova/resources/js/lib/useLazyProfileCollections.test.jsx
T
test 37100ced3f Lazy-load profile collections until the tab is opened.
Keep the profile payload smaller on first paint and fetch collections through a dedicated API when the collections tab is needed.
2026-09-20 14:49:33 +02:00

71 lines
2.8 KiB
React

import React from 'react'
import { render, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import useLazyProfileCollections from './useLazyProfileCollections'
function Harness({ username = 'alice', initial = null, enabled = false }) {
const state = useLazyProfileCollections({
username,
initialCollections: initial,
enabled,
})
return <output data-testid="state">{JSON.stringify(state)}</output>
}
describe('useLazyProfileCollections', () => {
beforeEach(() => vi.restoreAllMocks())
it('does not request while the profile remains on Posts', () => {
const fetchMock = vi.spyOn(globalThis, 'fetch')
render(<Harness />)
expect(fetchMock).not.toHaveBeenCalled()
})
it('requests once on first Collections activation and reuses the result', async () => {
const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue({
ok: true,
json: async () => ({ data: [{ id: 1, title: 'One' }] }),
})
const view = render(<Harness />)
view.rerender(<Harness enabled />)
await waitFor(() => expect(fetchMock).toHaveBeenCalledTimes(1))
await waitFor(() => expect(JSON.parse(view.getByTestId('state').textContent).items).toHaveLength(1))
view.rerender(<Harness enabled={false} />)
view.rerender(<Harness enabled />)
expect(fetchMock).toHaveBeenCalledTimes(1)
})
it('treats an empty response as loaded and does not refetch', async () => {
const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: true, json: async () => ({ data: [] }) })
const view = render(<Harness enabled />)
await waitFor(() => expect(JSON.parse(view.getByTestId('state').textContent).loaded).toBe(true))
view.rerender(<Harness enabled={false} />)
view.rerender(<Harness enabled />)
expect(fetchMock).toHaveBeenCalledTimes(1)
})
it('uses direct Collections SSR data without a lazy request', () => {
const fetchMock = vi.spyOn(globalThis, 'fetch')
const initial = [{ id: 9, title: 'SSR collection' }]
const view = render(<Harness initial={initial} enabled />)
expect(fetchMock).not.toHaveBeenCalled()
expect(JSON.parse(view.getByTestId('state').textContent).items).toEqual(initial)
})
it('ignores a stale response after profile navigation', async () => {
let resolveAlice
const fetchMock = vi.spyOn(globalThis, 'fetch').mockImplementation(() => new Promise((resolve) => { resolveAlice = resolve }))
const view = render(<Harness username="alice" enabled />)
await waitFor(() => expect(fetchMock).toHaveBeenCalledTimes(1))
view.rerender(<Harness username="bob" enabled />)
resolveAlice({ ok: true, json: async () => ({ data: [{ id: 'alice' }] }) })
await waitFor(() => expect(JSON.parse(view.getByTestId('state').textContent).items).toEqual([]))
})
})