import React from 'react' import { render, waitFor } from '@testing-library/react' import { beforeEach, describe, expect, it, vi } from 'vitest' import useLazyProfileFavourites from './useLazyProfileFavourites' function Harness({ username = 'alice', initial = null, enabled = false }) { const state = useLazyProfileFavourites({ username, initialFavourites: initial, enabled, }) return {JSON.stringify(state)} } describe('useLazyProfileFavourites', () => { beforeEach(() => { vi.restoreAllMocks() }) it('does not request before activation and requests page one once on activation', async () => { const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: true, json: async () => ({ data: [{ id: 1 }], next_cursor: 'c1' }), }) const view = render() expect(fetchMock).not.toHaveBeenCalled() view.rerender() await waitFor(() => expect(fetchMock).toHaveBeenCalledTimes(1)) expect(fetchMock).toHaveBeenCalledWith('/api/profile/alice/favourites', expect.objectContaining({ credentials: 'same-origin', })) }) it('uses SSR data without a page-one request and survives rerenders', async () => { const fetchMock = vi.spyOn(globalThis, 'fetch') const view = render() view.rerender() await waitFor(() => expect(JSON.parse(view.getByTestId('state').textContent).items).toEqual([{ id: 9 }])) expect(fetchMock).not.toHaveBeenCalled() }) it('does not refetch after switching away and back', async () => { const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: true, json: async () => ({ data: [{ id: 3 }], next_cursor: null }), }) const view = render() await waitFor(() => expect(fetchMock).toHaveBeenCalledTimes(1)) view.rerender() view.rerender() await waitFor(() => expect(JSON.parse(view.getByTestId('state').textContent).items).toEqual([{ id: 3 }])) expect(fetchMock).toHaveBeenCalledTimes(1) }) it('resets profile state and ignores a stale response', async () => { let resolveRequest const fetchMock = vi.spyOn(globalThis, 'fetch').mockImplementation(() => new Promise((resolve) => { resolveRequest = resolve })) const view = render() await waitFor(() => expect(fetchMock).toHaveBeenCalledTimes(1)) view.rerender() expect(JSON.parse(view.getByTestId('state').textContent).items).toEqual([]) resolveRequest({ ok: true, json: async () => ({ data: [{ id: 1 }], next_cursor: null }) }) await waitFor(() => expect(JSON.parse(view.getByTestId('state').textContent).items).toEqual([])) }) })