Skip to content

Commit 2ad2e77

Browse files
committed
So far so good
1 parent d1fa423 commit 2ad2e77

File tree

4 files changed

+90
-55
lines changed

4 files changed

+90
-55
lines changed

packages/openapi-react-query/src/index.ts

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import {
33
type UseMutationResult,
44
type UseQueryOptions,
55
type UseQueryResult,
6+
type InfiniteData,
7+
type InfiniteQueryObserverResult,
68
type UseInfiniteQueryOptions,
79
type UseInfiniteQueryResult,
810
type UseSuspenseQueryOptions,
@@ -103,34 +105,34 @@ export type UseInfiniteQueryMethod<Paths extends Record<string, Record<HttpMetho
103105
url: Path,
104106
...[init, options, queryClient]: RequiredKeysOf<Init> extends never
105107
? [
106-
InitWithUnknowns<Init>?,
107-
Omit<
108-
UseInfiniteQueryOptions<
109-
Response["data"],
110-
Response["error"],
111-
Response["data"],
112-
number,
113-
QueryKey<Paths, Method, Path>
114-
>,
115-
"queryKey" | "queryFn"
116-
>?,
117-
QueryClient?,
108+
InitWithUnknowns<Init>?,
109+
Omit<
110+
UseInfiniteQueryOptions<
111+
Response["data"],
112+
Response["error"],
113+
Response["data"],
114+
number,
115+
QueryKey<Paths, Method, Path>
116+
>,
117+
"queryKey" | "queryFn"
118+
>?,
119+
QueryClient?,
118120
]
119121
: [
120-
InitWithUnknowns<Init>,
121-
Omit<
122-
UseInfiniteQueryOptions<
123-
Response["data"],
124-
Response["error"],
125-
Response["data"],
126-
number,
127-
QueryKey<Paths, Method, Path>
128-
>,
129-
"queryKey" | "queryFn"
130-
>?,
131-
QueryClient?,
122+
InitWithUnknowns<Init>,
123+
Omit<
124+
UseInfiniteQueryOptions<
125+
Response["data"],
126+
Response["error"],
127+
Response["data"],
128+
number,
129+
QueryKey<Paths, Method, Path>
130+
>,
131+
"queryKey" | "queryFn"
132+
>?,
133+
QueryClient?,
132134
]
133-
) => UseInfiniteQueryResult<Response["data"], Response["error"]>;
135+
) => UseInfiniteQueryResult<InfiniteData<Response["data"]>, Response["error"]>;
134136

135137
export type UseSuspenseQueryMethod<Paths extends Record<string, Record<HttpMethod, {}>>, Media extends MediaType> = <
136138
Method extends HttpMethod,

packages/openapi-react-query/test/fixtures/api.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export interface paths {
1515
parameters: {
1616
query: {
1717
limit: number;
18+
cursor?: number;
1819
};
1920
header?: never;
2021
path?: never;

packages/openapi-react-query/test/fixtures/api.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ paths:
1111
required: true
1212
schema:
1313
type: integer
14+
- in: query
15+
name: cursor
16+
required: false
17+
schema:
18+
type: integer
1419
responses:
1520
'200':
1621
description: Successful response

packages/openapi-react-query/test/index.test.tsx

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { server, baseUrl, useMockRequestHandler } from "./fixtures/mock-server.j
33
import type { paths } from "./fixtures/api.js";
44
import createClient from "../src/index.js";
55
import createFetchClient from "openapi-fetch";
6-
import { act, fireEvent, render, renderHook, screen, waitFor } from "@testing-library/react";
6+
import { fireEvent, render, renderHook, screen, waitFor, act } from "@testing-library/react";
77
import {
88
QueryClient,
99
QueryClientProvider,
@@ -823,64 +823,91 @@ describe("client", () => {
823823
});
824824
});
825825
describe("useInfiniteQuery", () => {
826-
it("should fetch data correctly with pagination", async () => {
826+
it("should fetch data correctly with pagination and include cursor", async () => {
827827
const fetchClient = createFetchClient<paths>({ baseUrl });
828828
const client = createClient(fetchClient);
829829

830-
useMockRequestHandler({
830+
// Track request URLs using the mock handler
831+
let firstRequestUrl: URL | undefined;
832+
let secondRequestUrl: URL | undefined;
833+
834+
// First page request handler
835+
const firstRequestHandler = useMockRequestHandler({
831836
baseUrl,
832837
method: "get",
833838
path: "/paginated-data",
834839
status: 200,
835840
body: { items: [1, 2, 3], nextPage: 1 },
836841
});
837842

838-
const { result } = renderHook(
839-
() => client.useInfiniteQuery("get", "/paginated-data", { params: { query: { limit: 3 } } }),
843+
const { result, rerender } = renderHook(
844+
() => client.useInfiniteQuery("get", "/paginated-data",
845+
{
846+
params: {
847+
query: {
848+
limit: 3
849+
}
850+
}
851+
},
852+
{
853+
getNextPageParam: (lastPage) => lastPage.nextPage,
854+
initialPageParam: 0,
855+
}),
840856
{ wrapper },
841857
);
842858

859+
// Wait for initial query to complete
843860
await waitFor(() => expect(result.current.isSuccess).toBe(true));
844861

845-
expect((result.current.data as any).pages[0]).toEqual({ items: [1, 2, 3], nextPage: 1 });
862+
// Verify first request
863+
firstRequestUrl = firstRequestHandler.getRequestUrl();
864+
expect(firstRequestUrl?.searchParams.get('limit')).toBe('3');
865+
expect(firstRequestUrl?.searchParams.get('cursor')).toBe('0');
846866

847-
// Set up mock for second page
848-
useMockRequestHandler({
867+
// Set up mock for second page before triggering next page fetch
868+
const secondRequestHandler = useMockRequestHandler({
849869
baseUrl,
850870
method: "get",
851871
path: "/paginated-data",
852872
status: 200,
853873
body: { items: [4, 5, 6], nextPage: 2 },
854874
});
855875

856-
await result.current.fetchNextPage();
876+
// Fetch next page
877+
await act(async () => {
878+
await result.current.fetchNextPage();
879+
// Force a rerender to ensure state is updated
880+
rerender();
881+
});
857882

858-
await waitFor(() => expect(result.current.isFetching).toBe(false));
883+
// Wait for second page to be fetched and verify loading states
884+
await waitFor(() => {
885+
expect(result.current.isFetching).toBe(false);
886+
expect(result.current.hasNextPage).toBe(true);
887+
expect(result.current.data?.pages).toHaveLength(2);
888+
});
859889

860-
expect((result.current.data as any).pages).toHaveLength(2);
861-
expect((result.current.data as any).pages[1]).toEqual({ items: [4, 5, 6], nextPage: 2 });
862-
});
890+
// Verify second request
891+
secondRequestUrl = secondRequestHandler.getRequestUrl();
892+
expect(secondRequestUrl?.searchParams.get('limit')).toBe('3');
893+
expect(secondRequestUrl?.searchParams.get('cursor')).toBe('1');
863894

864-
it("should handle errors correctly", async () => {
865-
const fetchClient = createFetchClient<paths>({ baseUrl });
866-
const client = createClient(fetchClient);
895+
expect(result.current.data).toBeDefined();
896+
expect(result.current.data!.pages[0].nextPage).toBe(1);
867897

868-
useMockRequestHandler({
869-
baseUrl,
870-
method: "get",
871-
path: "/paginated-data",
872-
status: 500,
873-
body: { code: 500, message: "Internal Server Error" },
874-
});
875898

876-
const { result } = renderHook(
877-
() => client.useInfiniteQuery("get", "/paginated-data", { params: { query: { limit: 3 } } }),
878-
{ wrapper },
879-
);
899+
expect(result.current.data).toBeDefined();
900+
expect(result.current.data!.pages[1].nextPage).toBe(2);
880901

881-
await waitFor(() => expect(result.current.isError).toBe(true));
902+
// Verify the complete data structure
903+
expect(result.current.data?.pages).toEqual([
904+
{ items: [1, 2, 3], nextPage: 1 },
905+
{ items: [4, 5, 6], nextPage: 2 }
906+
]);
882907

883-
expect(result.current.error).toEqual({ code: 500, message: "Internal Server Error" });
908+
// Verify we can access all items through pages
909+
const allItems = result.current.data?.pages.flatMap(page => page.items);
910+
expect(allItems).toEqual([1, 2, 3, 4, 5, 6]);
884911
});
885-
});
912+
})
886913
});

0 commit comments

Comments
 (0)