diff --git a/ui/pages/Tokens.pw.tsx b/ui/pages/Tokens.pw.tsx
index 58c3fe6cd4..53e0215580 100644
--- a/ui/pages/Tokens.pw.tsx
+++ b/ui/pages/Tokens.pw.tsx
@@ -7,24 +7,40 @@ import { test, expect } from 'playwright/lib';
import Tokens from './Tokens';
-test.beforeEach(async({ mockTextAd }) => {
+test.beforeEach(async({ mockTextAd, mockAssetResponse }) => {
await mockTextAd();
+ await mockAssetResponse(tokens.tokenInfoERC20a.icon_url as string, './playwright/mocks/image_svg.svg');
});
+const allTokens = {
+ items: [
+ tokens.tokenInfoERC20a, tokens.tokenInfoERC20b, tokens.tokenInfoERC20c, tokens.tokenInfoERC20d,
+ tokens.tokenInfoERC721a, tokens.tokenInfoERC721b, tokens.tokenInfoERC721c,
+ tokens.tokenInfoERC1155a, tokens.tokenInfoERC1155b, tokens.tokenInfoERC1155WithoutName,
+ ],
+ next_page_params: {
+ holder_count: 1,
+ items_count: 1,
+ name: 'a',
+ market_cap: '0',
+ },
+};
+
test('base view +@mobile +@dark-mode', async({ render, mockApiResponse }) => {
- const allTokens = {
- items: [
- tokens.tokenInfoERC20a, tokens.tokenInfoERC20b, tokens.tokenInfoERC20c, tokens.tokenInfoERC20d,
- tokens.tokenInfoERC721a, tokens.tokenInfoERC721b, tokens.tokenInfoERC721c,
- tokens.tokenInfoERC1155a, tokens.tokenInfoERC1155b, tokens.tokenInfoERC1155WithoutName,
- ],
- next_page_params: {
- holder_count: 1,
- items_count: 1,
- name: 'a',
- market_cap: '0',
- },
- };
+
+ await mockApiResponse('tokens', allTokens);
+
+ const component = await render(
+
+
+
+
,
+ );
+
+ await expect(component).toHaveScreenshot();
+});
+
+test('with search +@mobile +@dark-mode', async({ render, mockApiResponse }) => {
const filteredTokens = {
items: [
tokens.tokenInfoERC20a, tokens.tokenInfoERC20b, tokens.tokenInfoERC20c,
@@ -42,10 +58,9 @@ test('base view +@mobile +@dark-mode', async({ render, mockApiResponse }) => {
,
);
- await expect(component).toHaveScreenshot();
-
await component.getByRole('textbox', { name: 'Token name or symbol' }).focus();
await component.getByRole('textbox', { name: 'Token name or symbol' }).fill('foo');
+ await component.getByRole('textbox', { name: 'Token name or symbol' }).blur();
await expect(component).toHaveScreenshot();
});
diff --git a/ui/pages/__screenshots__/Tokens.pw.tsx_dark-color-mode_base-view-mobile-dark-mode-1.png b/ui/pages/__screenshots__/Tokens.pw.tsx_dark-color-mode_base-view-mobile-dark-mode-1.png
index ca396488ac..4a76b74064 100644
Binary files a/ui/pages/__screenshots__/Tokens.pw.tsx_dark-color-mode_base-view-mobile-dark-mode-1.png and b/ui/pages/__screenshots__/Tokens.pw.tsx_dark-color-mode_base-view-mobile-dark-mode-1.png differ
diff --git a/ui/pages/__screenshots__/Tokens.pw.tsx_dark-color-mode_base-view-mobile-dark-mode-2.png b/ui/pages/__screenshots__/Tokens.pw.tsx_dark-color-mode_base-view-mobile-dark-mode-2.png
deleted file mode 100644
index 5545d2c47c..0000000000
Binary files a/ui/pages/__screenshots__/Tokens.pw.tsx_dark-color-mode_base-view-mobile-dark-mode-2.png and /dev/null differ
diff --git a/ui/pages/__screenshots__/Tokens.pw.tsx_dark-color-mode_with-search-mobile-dark-mode-1.png b/ui/pages/__screenshots__/Tokens.pw.tsx_dark-color-mode_with-search-mobile-dark-mode-1.png
new file mode 100644
index 0000000000..bebe8a71cf
Binary files /dev/null and b/ui/pages/__screenshots__/Tokens.pw.tsx_dark-color-mode_with-search-mobile-dark-mode-1.png differ
diff --git a/ui/pages/__screenshots__/Tokens.pw.tsx_default_base-view-mobile-dark-mode-1.png b/ui/pages/__screenshots__/Tokens.pw.tsx_default_base-view-mobile-dark-mode-1.png
index 359dae45df..dddce9d35e 100644
Binary files a/ui/pages/__screenshots__/Tokens.pw.tsx_default_base-view-mobile-dark-mode-1.png and b/ui/pages/__screenshots__/Tokens.pw.tsx_default_base-view-mobile-dark-mode-1.png differ
diff --git a/ui/pages/__screenshots__/Tokens.pw.tsx_default_base-view-mobile-dark-mode-2.png b/ui/pages/__screenshots__/Tokens.pw.tsx_default_base-view-mobile-dark-mode-2.png
deleted file mode 100644
index 5c5a727d96..0000000000
Binary files a/ui/pages/__screenshots__/Tokens.pw.tsx_default_base-view-mobile-dark-mode-2.png and /dev/null differ
diff --git a/ui/pages/__screenshots__/Tokens.pw.tsx_default_bridged-tokens-base-view-1.png b/ui/pages/__screenshots__/Tokens.pw.tsx_default_bridged-tokens-base-view-1.png
index 47e895c8dc..cb8ab1c9cf 100644
Binary files a/ui/pages/__screenshots__/Tokens.pw.tsx_default_bridged-tokens-base-view-1.png and b/ui/pages/__screenshots__/Tokens.pw.tsx_default_bridged-tokens-base-view-1.png differ
diff --git a/ui/pages/__screenshots__/Tokens.pw.tsx_default_bridged-tokens-base-view-2.png b/ui/pages/__screenshots__/Tokens.pw.tsx_default_bridged-tokens-base-view-2.png
index a029be2866..3724329db4 100644
Binary files a/ui/pages/__screenshots__/Tokens.pw.tsx_default_bridged-tokens-base-view-2.png and b/ui/pages/__screenshots__/Tokens.pw.tsx_default_bridged-tokens-base-view-2.png differ
diff --git a/ui/pages/__screenshots__/Tokens.pw.tsx_default_with-search-mobile-dark-mode-1.png b/ui/pages/__screenshots__/Tokens.pw.tsx_default_with-search-mobile-dark-mode-1.png
new file mode 100644
index 0000000000..5597c05d2c
Binary files /dev/null and b/ui/pages/__screenshots__/Tokens.pw.tsx_default_with-search-mobile-dark-mode-1.png differ
diff --git a/ui/pages/__screenshots__/Tokens.pw.tsx_mobile_base-view-mobile-dark-mode-1.png b/ui/pages/__screenshots__/Tokens.pw.tsx_mobile_base-view-mobile-dark-mode-1.png
index 70e89b251a..f1e9a4cd7b 100644
Binary files a/ui/pages/__screenshots__/Tokens.pw.tsx_mobile_base-view-mobile-dark-mode-1.png and b/ui/pages/__screenshots__/Tokens.pw.tsx_mobile_base-view-mobile-dark-mode-1.png differ
diff --git a/ui/pages/__screenshots__/Tokens.pw.tsx_mobile_base-view-mobile-dark-mode-2.png b/ui/pages/__screenshots__/Tokens.pw.tsx_mobile_base-view-mobile-dark-mode-2.png
deleted file mode 100644
index 1af1787cd2..0000000000
Binary files a/ui/pages/__screenshots__/Tokens.pw.tsx_mobile_base-view-mobile-dark-mode-2.png and /dev/null differ
diff --git a/ui/pages/__screenshots__/Tokens.pw.tsx_mobile_with-search-mobile-dark-mode-1.png b/ui/pages/__screenshots__/Tokens.pw.tsx_mobile_with-search-mobile-dark-mode-1.png
new file mode 100644
index 0000000000..1fc18184a0
Binary files /dev/null and b/ui/pages/__screenshots__/Tokens.pw.tsx_mobile_with-search-mobile-dark-mode-1.png differ
diff --git a/ui/shared/pagination/useQueryWithPages.test.tsx b/ui/shared/pagination/useQueryWithPages.test.tsx
index f0b263d511..8fadab934d 100644
--- a/ui/shared/pagination/useQueryWithPages.test.tsx
+++ b/ui/shared/pagination/useQueryWithPages.test.tsx
@@ -367,7 +367,7 @@ describe('if there are multiple pages', () => {
describe('if there is page query param in URL', () => {
it('sets this param as the page number', async() => {
- useRouter.mockReturnValueOnce({ ...router, query: { page: '3' } });
+ useRouter.mockReturnValue({ ...router, query: { page: '3' } });
const params: Params<'address_txs'> = {
resourceName: 'address_txs',
@@ -614,6 +614,56 @@ describe('queries with sorting', () => {
});
});
+describe('router query changes', () => {
+ it('refetches correct page when page number changes in URL', async() => {
+ const routerPush = jest.fn(() => Promise.resolve());
+ const router = {
+ pathname: '/current-route',
+ push: routerPush,
+ query: {
+ page: '3',
+ next_page_params: encodeURIComponent(JSON.stringify(responses.page_2.next_page_params)),
+ },
+ };
+ useRouter.mockReturnValue(router);
+
+ const params: Params<'address_txs'> = {
+ resourceName: 'address_txs',
+ pathParams: { hash: addressMock.hash },
+ };
+
+ fetch.once(JSON.stringify(responses.page_3), responseInit);
+ fetch.once(JSON.stringify(responses.page_2), responseInit);
+
+ const { result, rerender } = renderHook(() => useQueryWithPages(params), { wrapper });
+ await waitForApiResponse();
+
+ expect(result.current.data).toEqual(responses.page_3);
+ expect(result.current.pagination.page).toBe(3);
+
+ // Simulate URL change to page 2
+ useRouter.mockReturnValue({
+ ...router,
+ query: {
+ page: '2',
+ next_page_params: encodeURIComponent(JSON.stringify(responses.page_1.next_page_params)),
+ },
+ });
+
+ rerender();
+ await waitForApiResponse();
+
+ expect(result.current.data).toEqual(responses.page_2);
+ expect(result.current.pagination).toMatchObject({
+ page: 2,
+ canGoBackwards: false,
+ hasNextPage: true,
+ isLoading: false,
+ isVisible: true,
+ });
+ });
+});
+
async function waitForApiResponse() {
await flushPromises();
await act(flushPromises);
diff --git a/ui/shared/pagination/useQueryWithPages.ts b/ui/shared/pagination/useQueryWithPages.ts
index ddf4b3a7e4..df554bb91b 100644
--- a/ui/shared/pagination/useQueryWithPages.ts
+++ b/ui/shared/pagination/useQueryWithPages.ts
@@ -7,6 +7,8 @@ import { animateScroll } from 'react-scroll';
import type { PaginationParams } from './types';
+import type { Route } from 'nextjs-routes';
+
import type { PaginatedResources, PaginationFilters, PaginationSorting, ResourceError, ResourcePayload } from 'lib/api/resources';
import { RESOURCES, SORTING_FIELDS } from 'lib/api/resources';
import type { Params as UseApiQueryParams } from 'lib/api/useApiQuery';
@@ -26,6 +28,10 @@ type NextPageParams = Record;
const INITIAL_PAGE_PARAMS = { '1': {} };
+function getPageFromQuery(query: Route['query']) {
+ return query?.page && !Array.isArray(query.page) ? Number(query.page) : 1;
+}
+
function getPaginationParamsFromQuery(queryString: string | Array | undefined) {
if (queryString) {
try {
@@ -64,7 +70,7 @@ export default function useQueryWithPages({
const queryClient = useQueryClient();
const router = useRouter();
- const [ page, setPage ] = React.useState(router.query.page && !Array.isArray(router.query.page) ? Number(router.query.page) : 1);
+ const [ page, setPage ] = React.useState(getPageFromQuery(router.query));
const [ pageParams, setPageParams ] = React.useState>({
[page]: getPaginationParamsFromQuery(router.query.next_page_params),
});
@@ -221,5 +227,17 @@ export default function useQueryWithPages({
}, 0);
}, []);
+ React.useEffect(() => {
+ const pageFromQuery = getPageFromQuery(router.query);
+ const nextPageParamsFromQuery = getPaginationParamsFromQuery(router.query.next_page_params);
+
+ setPage(pageFromQuery);
+ setPageParams(prev => ({
+ ...prev,
+ [pageFromQuery]: nextPageParamsFromQuery,
+ }));
+ setHasPages(pageFromQuery > 1);
+ }, [ router.query ]);
+
return { ...queryResult, pagination, onFilterChange, onSortingChange };
}