Skip to content

Commit

Permalink
Add tests for query hooks and fix pagination in useSuiClientInfiniteQ… (
Browse files Browse the repository at this point in the history
MystenLabs#14344)

…uery

## Description 

Describe the changes or additions included in this PR.

## Test Plan 

How did you test the new or updated feature?

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
  • Loading branch information
hayes-mysten authored Oct 24, 2023
1 parent 767885c commit 09c1030
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/selfish-readers-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@mysten/dapp-kit': patch
---

fix pagination in useSuiClientInfiniteQuery
22 changes: 10 additions & 12 deletions sdk/dapp-kit/src/hooks/useSuiClientInfiniteQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,13 @@ export type SuiRpcPaginatedMethodName = {
}[keyof SuiClient];

export type SuiRpcPaginatedMethods = {
[K in SuiRpcPaginatedMethodName]: SuiClient[K] extends (input: infer P) => Promise<{
data?: infer R;
nextCursor?: infer Cursor | null;
hasNextPage: boolean;
}>
[K in SuiRpcPaginatedMethodName]: SuiClient[K] extends (
input: infer Params,
) => Promise<infer Result extends { nextCursor?: infer Cursor | null }>
? {
name: K;
result: {
data?: R;
nextCursor?: Cursor | null;
hasNextPage: boolean;
};
params: P;
result: Result;
params: Params;
cursor: Cursor;
}
: never;
Expand Down Expand Up @@ -57,7 +51,11 @@ export function useSuiClientInfiniteQuery<T extends keyof SuiRpcPaginatedMethods
...options,
queryKey: [suiContext.network, method, params, ...queryKey],
enabled,
queryFn: () => suiContext.client[method](params as never),
queryFn: ({ pageParam }) =>
suiContext.client[method]({
...(params ?? {}),
cursor: pageParam,
} as never),
getNextPageParam: (lastPage) => {
return (lastPage as PaginatedResult).nextCursor ?? null;
},
Expand Down
82 changes: 82 additions & 0 deletions sdk/dapp-kit/test/hooks/useSuiClientInfiniteQuery.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
import { getFullnodeUrl, SuiClient } from '@mysten/sui.js/client';
import { act, renderHook, waitFor } from '@testing-library/react';

import { useSuiClientInfiniteQuery } from '../../src/hooks/useSuiClientInfiniteQuery.js';
import { createWalletProviderContextWrapper } from '../test-utils.js';

describe('useSuiClientInfiniteQuery', () => {
it('should fetch data', async () => {
const suiClient = new SuiClient({ url: getFullnodeUrl('mainnet') });
const wrapper = createWalletProviderContextWrapper({}, suiClient);

const queryTransactionBlocks = vi.spyOn(suiClient, 'queryTransactionBlocks');

const pages = [
{
data: [{ digest: '0x123' }],
hasNextPage: true,
nextCursor: 'page2',
},
{
data: [{ digest: '0x456' }],
hasNextPage: false,
nextCursor: null,
},
];

queryTransactionBlocks.mockResolvedValueOnce(pages[0]);

const { result } = renderHook(
() =>
useSuiClientInfiniteQuery('queryTransactionBlocks', {
filter: {
FromAddress: '0x123',
},
}),
{ wrapper },
);

expect(result.current.isLoading).toBe(true);
expect(result.current.isError).toBe(false);
expect(result.current.data).toBe(undefined);
expect(queryTransactionBlocks).toHaveBeenCalledWith({
filter: {
FromAddress: '0x123',
},
});

await waitFor(() => expect(result.current.isSuccess).toBe(true));

expect(result.current.isLoading).toBe(false);
expect(result.current.isError).toBe(false);
expect(result.current.data).toEqual({
pageParams: [undefined],
pages: [pages[0]],
});

queryTransactionBlocks.mockResolvedValueOnce(pages[1]);

await act(() => {
result.current.fetchNextPage();
});

await waitFor(() => expect(result.current.isFetchingNextPage).toBe(false));

expect(result.current.isLoading).toBe(false);
expect(result.current.isError).toBe(false);
expect(result.current.data).toEqual({
pageParams: [undefined, 'page2'],
pages: [pages[0], pages[1]],
});
expect(result.current.data?.pages[0].data[0].digest).toBe('0x123');

expect(queryTransactionBlocks).toHaveBeenCalledWith({
filter: {
FromAddress: '0x123',
},
cursor: 'page2',
});
});
});
49 changes: 49 additions & 0 deletions sdk/dapp-kit/test/hooks/useSuiClientMutation.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
import { getFullnodeUrl, SuiClient } from '@mysten/sui.js/client';
import { act, renderHook, waitFor } from '@testing-library/react';

import { useSuiClientMutation } from '../../src/hooks/useSuiClientMutation.js';
import { createWalletProviderContextWrapper } from '../test-utils.js';

describe('useSuiClientMutation', () => {
it('should fetch data', async () => {
const suiClient = new SuiClient({ url: getFullnodeUrl('mainnet') });
const wrapper = createWalletProviderContextWrapper({}, suiClient);

const queryTransactionBlocks = vi.spyOn(suiClient, 'queryTransactionBlocks');

queryTransactionBlocks.mockResolvedValueOnce({
data: [{ digest: '0x123' }],
hasNextPage: true,
nextCursor: 'page2',
});

const { result } = renderHook(() => useSuiClientMutation('queryTransactionBlocks'), {
wrapper,
});

act(() => {
result.current.mutate({
filter: {
FromAddress: '0x123',
},
});
});

await waitFor(() => expect(result.current.status).toBe('success'));

expect(queryTransactionBlocks).toHaveBeenCalledWith({
filter: {
FromAddress: '0x123',
},
});
expect(result.current.isLoading).toBe(false);
expect(result.current.isError).toBe(false);
expect(result.current.data).toEqual({
data: [{ digest: '0x123' }],
hasNextPage: true,
nextCursor: 'page2',
});
});
});
51 changes: 51 additions & 0 deletions sdk/dapp-kit/test/hooks/useSuiClientQuery.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
import { getFullnodeUrl, SuiClient } from '@mysten/sui.js/client';
import { renderHook, waitFor } from '@testing-library/react';

import { useSuiClientQuery } from '../../src/hooks/useSuiClientQuery.js';
import { createWalletProviderContextWrapper } from '../test-utils.js';

describe('useSuiClientQuery', () => {
it('should fetch data', async () => {
const suiClient = new SuiClient({ url: getFullnodeUrl('mainnet') });
const wrapper = createWalletProviderContextWrapper({}, suiClient);

const queryTransactionBlocks = vi.spyOn(suiClient, 'queryTransactionBlocks');

queryTransactionBlocks.mockResolvedValueOnce({
data: [{ digest: '0x123' }],
hasNextPage: true,
nextCursor: 'page2',
});

const { result } = renderHook(
() =>
useSuiClientQuery('queryTransactionBlocks', {
filter: {
FromAddress: '0x123',
},
}),
{ wrapper },
);

expect(result.current.isLoading).toBe(true);
expect(result.current.isError).toBe(false);
expect(result.current.data).toBe(undefined);
expect(queryTransactionBlocks).toHaveBeenCalledWith({
filter: {
FromAddress: '0x123',
},
});

await waitFor(() => expect(result.current.isSuccess).toBe(true));

expect(result.current.isLoading).toBe(false);
expect(result.current.isError).toBe(false);
expect(result.current.data).toEqual({
data: [{ digest: '0x123' }],
hasNextPage: true,
nextCursor: 'page2',
});
});
});

0 comments on commit 09c1030

Please sign in to comment.