Commit 24398f23 authored by tom's avatar tom

rewrite tests

parent 98cf4870
...@@ -17,13 +17,13 @@ interface SocketMessageParamsGeneric<Event extends string | undefined, Payload e ...@@ -17,13 +17,13 @@ interface SocketMessageParamsGeneric<Event extends string | undefined, Payload e
handler: (payload: Payload) => void; handler: (payload: Payload) => void;
} }
interface AddressCoinBalancePayload { export interface AddressCoinBalancePayload {
coin_balance: { coin_balance: {
block_number: number; block_number: number;
block_timestamp: string; block_timestamp?: string;
delta: string; delta?: string;
transaction_hash: string | null; transaction_hash?: string | null;
value: string; value?: string;
}; };
} }
......
...@@ -45,6 +45,21 @@ export const erc20c: AddressTokenBalance = { ...@@ -45,6 +45,21 @@ export const erc20c: AddressTokenBalance = {
value: '9852000000000000000000', value: '9852000000000000000000',
}; };
export const erc20d: AddressTokenBalance = {
token: {
address: '0xCc7bb2D219A0FC08033E130629C2B854b7bA9195',
decimals: '18',
exchange_rate: null,
holders: '102625',
name: 'Zeta',
symbol: 'ZETA',
total_supply: '2100000000000000000000000000',
type: 'ERC-20',
},
token_id: null,
value: '39000000000000000000',
};
export const erc721a: AddressTokenBalance = { export const erc721a: AddressTokenBalance = {
token: { token: {
address: '0xDe7cAc71E072FCBd4453E5FB3558C2684d1F88A0', address: '0xDe7cAc71E072FCBd4453E5FB3558C2684d1F88A0',
......
...@@ -2,6 +2,7 @@ import type { TestFixture } from '@playwright/test'; ...@@ -2,6 +2,7 @@ import type { TestFixture } from '@playwright/test';
import type { WebSocket } from 'ws'; import type { WebSocket } from 'ws';
import { WebSocketServer } from 'ws'; import { WebSocketServer } from 'ws';
import type { AddressCoinBalancePayload } from 'lib/socket/types';
import type { NewBlockSocketResponse } from 'types/api/block'; import type { NewBlockSocketResponse } from 'types/api/block';
type ReturnType = () => Promise<WebSocket>; type ReturnType = () => Promise<WebSocket>;
...@@ -55,6 +56,8 @@ export const joinChannel = async(socket: WebSocket, channelName: string) => { ...@@ -55,6 +56,8 @@ export const joinChannel = async(socket: WebSocket, channelName: string) => {
}); });
}; };
export function sendMessage(socket: WebSocket, channel: Channel, msg: 'coin_balance', payload: AddressCoinBalancePayload): void;
export function sendMessage(socket: WebSocket, channel: Channel, msg: 'token_balance', payload: { block_number: number }): void;
export function sendMessage(socket: WebSocket, channel: Channel, msg: 'transaction', payload: { transaction: number }): void; export function sendMessage(socket: WebSocket, channel: Channel, msg: 'transaction', payload: { transaction: number }): void;
export function sendMessage(socket: WebSocket, channel: Channel, msg: 'pending_transaction', payload: { pending_transaction: number }): void; export function sendMessage(socket: WebSocket, channel: Channel, msg: 'pending_transaction', payload: { pending_transaction: number }): void;
export function sendMessage(socket: WebSocket, channel: Channel, msg: 'new_block', payload: NewBlockSocketResponse): void; export function sendMessage(socket: WebSocket, channel: Channel, msg: 'new_block', payload: NewBlockSocketResponse): void;
......
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import React from 'react';
import { QueryKeys } from 'types/client/queries';
import useFetch from 'lib/hooks/useFetch';
const MockAddressPage = ({ children }: { children: JSX.Element }): JSX.Element => {
const router = useRouter();
const fetch = useFetch();
const { data } = useQuery(
[ QueryKeys.address, router.query.id ],
async() => await fetch(`/node-api/addresses/${ router.query.id }`),
{
enabled: Boolean(router.query.id),
},
);
if (!data) {
return <div/>;
}
return children;
};
export default MockAddressPage;
import { test as base, expect } from '@playwright/experimental-ct-react'; import { test as base, expect, devices } from '@playwright/experimental-ct-react';
import React from 'react'; import React from 'react';
import * as tokenBalanceMock from 'mocks/address/tokenBalance'; import * as tokenBalanceMock from 'mocks/address/tokenBalance';
import * as socketServer from 'playwright/fixtures/socketServer';
import TestApp from 'playwright/TestApp'; import TestApp from 'playwright/TestApp';
import MockAddressPage from 'ui/address/testUtils/MockAddressPage';
import TokenSelectDesktop from './TokenSelectDesktop'; import TokenSelect from './TokenSelect';
const ASSET_URL = 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/poa/assets/0xb2a90505dc6680a7a695f7975d0d32EeF610f456/logo.png'; const ASSET_URL = 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/poa/assets/0xb2a90505dc6680a7a695f7975d0d32EeF610f456/logo.png';
const TOKENS_API_URL = '/node-api/addresses/1/token-balances';
const ADDRESS_API_URL = '/node-api/addresses/1';
const hooksConfig = {
router: {
query: { id: '1' },
},
};
const CLIPPING_AREA = { x: 0, y: 0, width: 360, height: 500 }; const CLIPPING_AREA = { x: 0, y: 0, width: 360, height: 500 };
const test = base.extend({ const test = base.extend({
...@@ -17,6 +26,15 @@ const test = base.extend({ ...@@ -17,6 +26,15 @@ const test = base.extend({
path: './playwright/image_s.jpg', path: './playwright/image_s.jpg',
}); });
}); });
await page.route(ADDRESS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify({ hash: '1' }),
}), { times: 1 });
await page.route(TOKENS_API_URL, async(route) => route.fulfill({
status: 200,
body: JSON.stringify(tokenBalanceMock.baseList),
}), { times: 1 });
use(page); use(page);
}, },
}); });
...@@ -24,10 +42,14 @@ const test = base.extend({ ...@@ -24,10 +42,14 @@ const test = base.extend({
test('base view +@dark-mode', async({ mount, page }) => { test('base view +@dark-mode', async({ mount, page }) => {
await mount( await mount(
<TestApp> <TestApp>
<TokenSelectDesktop data={ tokenBalanceMock.baseList }/> <MockAddressPage>
<TokenSelect/>
</MockAddressPage>
</TestApp>, </TestApp>,
{ hooksConfig },
); );
await page.getByRole('button').click();
await page.getByRole('button', { name: /select/i }).click();
await page.getByText('USD Coin').hover(); await page.getByText('USD Coin').hover();
await expect(page).toHaveScreenshot({ clip: CLIPPING_AREA }); await expect(page).toHaveScreenshot({ clip: CLIPPING_AREA });
...@@ -37,13 +59,36 @@ test('base view +@dark-mode', async({ mount, page }) => { ...@@ -37,13 +59,36 @@ test('base view +@dark-mode', async({ mount, page }) => {
await expect(page).toHaveScreenshot({ clip: CLIPPING_AREA }); await expect(page).toHaveScreenshot({ clip: CLIPPING_AREA });
}); });
test.describe('mobile', () => {
test.use({ viewport: devices['iPhone 13 Pro'].viewport });
test('base view', async({ mount, page }) => {
await mount(
<TestApp>
<MockAddressPage>
<TokenSelect/>
</MockAddressPage>
</TestApp>,
{ hooksConfig },
);
await page.getByRole('button', { name: /select/i }).click();
await page.getByText('USD Coin').hover();
await expect(page).toHaveScreenshot();
});
});
test('sort', async({ mount, page }) => { test('sort', async({ mount, page }) => {
await mount( await mount(
<TestApp> <TestApp>
<TokenSelectDesktop data={ tokenBalanceMock.baseList }/> <MockAddressPage>
<TokenSelect/>
</MockAddressPage>
</TestApp>, </TestApp>,
{ hooksConfig },
); );
await page.getByRole('button').click(); await page.getByRole('button', { name: /select/i }).click();
await page.locator('a[aria-label="Sort ERC-20 tokens"]').click(); await page.locator('a[aria-label="Sort ERC-20 tokens"]').click();
await expect(page).toHaveScreenshot({ clip: CLIPPING_AREA }); await expect(page).toHaveScreenshot({ clip: CLIPPING_AREA });
...@@ -58,11 +103,81 @@ test('sort', async({ mount, page }) => { ...@@ -58,11 +103,81 @@ test('sort', async({ mount, page }) => {
test('filter', async({ mount, page }) => { test('filter', async({ mount, page }) => {
await mount( await mount(
<TestApp> <TestApp>
<TokenSelectDesktop data={ tokenBalanceMock.baseList }/> <MockAddressPage>
<TokenSelect/>
</MockAddressPage>
</TestApp>, </TestApp>,
{ hooksConfig },
); );
await page.getByRole('button').click(); await page.getByRole('button', { name: /select/i }).click();
await page.getByPlaceholder('Search by token name').type('c'); await page.getByPlaceholder('Search by token name').type('c');
await expect(page).toHaveScreenshot({ clip: CLIPPING_AREA }); await expect(page).toHaveScreenshot({ clip: CLIPPING_AREA });
}); });
test.describe('socket', () => {
const testWithSocket = test.extend<socketServer.SocketServerFixture>({
createSocket: socketServer.createSocket,
});
testWithSocket.describe.configure({ mode: 'serial' });
testWithSocket('new item after token balance update', async({ page, mount, createSocket }) => {
await mount(
<TestApp withSocket>
<MockAddressPage>
<TokenSelect/>
</MockAddressPage>
</TestApp>,
{ hooksConfig },
);
await page.route(TOKENS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify([
...tokenBalanceMock.baseList,
tokenBalanceMock.erc20d,
]),
}));
const socket = await createSocket();
const channel = await socketServer.joinChannel(socket, 'addresses:1');
socketServer.sendMessage(socket, channel, 'token_balance', {
block_number: 1,
});
const button = page.getByRole('button', { name: /select/i });
const text = await button.innerText();
expect(text).toContain('10');
});
testWithSocket('new item after coin balance update', async({ page, mount, createSocket }) => {
await mount(
<TestApp withSocket>
<MockAddressPage>
<TokenSelect/>
</MockAddressPage>
</TestApp>,
{ hooksConfig },
);
await page.route(TOKENS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify([
...tokenBalanceMock.baseList,
tokenBalanceMock.erc20d,
]),
}));
const socket = await createSocket();
const channel = await socketServer.joinChannel(socket, 'addresses:1');
socketServer.sendMessage(socket, channel, 'coin_balance', {
coin_balance: {
block_number: 1,
},
});
const button = page.getByRole('button', { name: /select/i });
const text = await button.innerText();
expect(text).toContain('10');
});
});
...@@ -24,6 +24,7 @@ const TokenSelectButton = ({ isOpen, onClick, data }: Props, ref: React.Forwarde ...@@ -24,6 +24,7 @@ const TokenSelectButton = ({ isOpen, onClick, data }: Props, ref: React.Forwarde
variant="outline" variant="outline"
colorScheme="gray" colorScheme="gray"
onClick={ onClick } onClick={ onClick }
aria-label="Token select"
> >
<Icon as={ tokensIcon } boxSize={ 4 } mr={ 2 }/> <Icon as={ tokensIcon } boxSize={ 4 } mr={ 2 }/>
<Text fontWeight={ 600 }>{ data.length }</Text> <Text fontWeight={ 600 }>{ data.length }</Text>
......
import { test as base, expect, devices } from '@playwright/experimental-ct-react';
import React from 'react';
import * as tokenBalanceMock from 'mocks/address/tokenBalance';
import TestApp from 'playwright/TestApp';
import TokenSelectMobile from './TokenSelectMobile';
const ASSET_URL = 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/poa/assets/0xb2a90505dc6680a7a695f7975d0d32EeF610f456/logo.png';
const test = base.extend({
page: async({ page }, use) => {
await page.route(ASSET_URL, (route) => {
return route.fulfill({
status: 200,
path: './playwright/image_s.jpg',
});
});
use(page);
},
});
test.use(devices['iPhone 13 Pro']);
test('base view +@dark-mode', async({ mount, page }) => {
await mount(
<TestApp>
<TokenSelectMobile data={ tokenBalanceMock.baseList }/>
</TestApp>,
);
await page.getByRole('button').click();
await page.getByText('USD Coin').hover();
await expect(page).toHaveScreenshot();
});
...@@ -17,7 +17,7 @@ const hooksConfig = { ...@@ -17,7 +17,7 @@ const hooksConfig = {
}, },
}; };
export const test = base.extend<socketServer.SocketServerFixture>({ const test = base.extend<socketServer.SocketServerFixture>({
createSocket: socketServer.createSocket, createSocket: socketServer.createSocket,
}); });
......
...@@ -26,7 +26,7 @@ test('between addresses +@mobile +@dark-mode', async({ mount, page }) => { ...@@ -26,7 +26,7 @@ test('between addresses +@mobile +@dark-mode', async({ mount, page }) => {
{ hooksConfig }, { hooksConfig },
); );
await page.waitForResponse(API_URL), await page.waitForResponse(API_URL);
await page.getByText('View details').click(); await page.getByText('View details').click();
await expect(component).toHaveScreenshot(); await expect(component).toHaveScreenshot();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment