Commit aeb7b865 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Turn on eslint playwright plugin and eslint react-query plugin (#2401)

* fix pw eslint rules

* turn on no-unstable-deps rule

* fix eslint warnings
parent 21e1fdee
......@@ -230,16 +230,13 @@ export default tseslint.config(
{
plugins: { '@tanstack/query': reactQueryPlugin },
rules: {
'@tanstack/query/no-unstable-deps': 'off', // TODO @tom2drum turn on this rule
},
},
{
plugins: { playwright: playwrightPlugin },
...playwrightPlugin.configs['flat/recommended'],
files: [ '**/*.pw.tsx' ],
rules: {
'playwright/valid-title': 'warn', // TODO @tom2drum turn on this rule
...playwrightPlugin.configs['flat/recommended'].rules,
'playwright/no-standalone-expect': 'off', // this rules does not work correctly with extended test functions
},
},
......
......@@ -18,7 +18,7 @@ test.use({ viewport: { width: 150, height: 350 } });
{ variant: 'radio_group', states: [ 'default', 'hovered', 'selected' ], withDarkMode: true },
].forEach(({ variant, colorScheme, withDarkMode, states }) => {
test.describe(`variant ${ variant }${ colorScheme ? ` with ${ colorScheme } color scheme` : '' }${ withDarkMode ? ' +@dark-mode' : '' }`, () => {
test('', async({ render }) => {
test('base view', async({ render }) => {
const component = await render(
<Flex p={ 2 } flexDir="column" rowGap={ 3 }>
{ states?.map((state) => {
......
......@@ -31,8 +31,8 @@ test.fixme('with icon', async({ render, page }) => {
);
const tooltip = page.getByText(/tooltip content/i);
expect(await tooltip.isVisible()).toBe(false);
await expect(tooltip).toBeHidden();
await component.locator('svg[aria-label="Trigger"]').hover();
expect(await tooltip.isVisible()).toBe(true);
await expect(tooltip).toBeVisible();
});
......@@ -115,7 +115,8 @@ test.describe('socket', () => {
socketServer.sendMessage(socket, channel, 'token_transfer', { token_transfers: [ tokenTransferMock.erc1155B, tokenTransferMock.erc1155C ] });
await page.waitForSelector('tbody tr:nth-child(3)');
const thirdRow = page.locator('tbody tr:nth-child(3)');
await thirdRow.waitFor();
const itemsCountNew = await page.locator('tbody tr').count();
expect(itemsCountNew).toBe(4);
......@@ -147,7 +148,8 @@ test.describe('socket', () => {
socketServer.sendMessage(socket, channel, 'token_transfer', { token_transfers: [ tokenTransferMock.erc1155B, tokenTransferMock.erc1155C ] });
await page.waitForSelector('tbody tr:nth-child(3)');
const thirdRow = page.locator('tbody tr:nth-child(3)');
await thirdRow.waitFor();
const itemsCountNew = await page.locator('tbody tr').count();
expect(itemsCountNew).toBe(3);
......@@ -183,7 +185,8 @@ test.describe('socket', () => {
socketServer.sendMessage(socket, channel, 'token_transfer', { token_transfers: [ tokenTransferMock.erc1155B, tokenTransferMock.erc20 ] });
await page.waitForSelector('tbody tr:nth-child(3)');
const thirdRow = page.locator('tbody tr:nth-child(3)');
await thirdRow.waitFor();
const itemsCountNew = await page.locator('tbody tr').count();
expect(itemsCountNew).toBe(3);
......@@ -221,7 +224,8 @@ test.describe('socket', () => {
{ token_transfers: [ tokenTransferMock.erc1155B, tokenTransferMock.erc20, tokenTransferMock.erc1155C, tokenTransferMock.erc721 ] },
);
await page.waitForSelector('tbody tr:nth-child(3)');
const thirdRow = page.locator('tbody tr:nth-child(3)');
await thirdRow.waitFor();
const itemsCountNew = await page.locator('tbody tr').count();
expect(itemsCountNew).toBe(3);
......
......@@ -166,7 +166,7 @@ test.describe('mobile', () => {
test.describe('update balances via socket', () => {
test.describe.configure({ mode: 'serial' });
test('', async({ render, page, createSocket, mockApiResponse }) => {
test('base flow', async({ render, page, createSocket, mockApiResponse }) => {
test.slow();
const hooksConfig = {
......
......@@ -48,7 +48,7 @@ test.describe('base view', () => {
test.describe('screen xl', () => {
test.use({ viewport: pwConfig.viewport.xl });
test('', async() => {
test('base view', async() => {
test.slow();
await expect(component).toHaveScreenshot();
});
......@@ -83,7 +83,8 @@ test.describe('socket', () => {
socketServer.sendMessage(socket, channel, 'transaction', { transactions: [ txMock.base2, txMock.base4 ] });
await page.waitForSelector('tbody tr:nth-child(3)');
const thirdRow = page.locator('tbody tr:nth-child(3)');
await thirdRow.waitFor();
const itemsCountNew = await page.locator('tbody tr').count();
expect(itemsCountNew).toBe(4);
......@@ -112,7 +113,8 @@ test.describe('socket', () => {
socketServer.sendMessage(socket, channel, 'transaction', { transactions: [ txMock.base, txMock.base2 ] });
await page.waitForSelector('tbody tr:nth-child(3)');
const thirdRow = page.locator('tbody tr:nth-child(3)');
await thirdRow.waitFor();
const itemsCountNew = await page.locator('tbody tr').count();
expect(itemsCountNew).toBe(3);
......@@ -141,7 +143,8 @@ test.describe('socket', () => {
socketServer.sendMessage(socket, channel, 'transaction', { transactions: [ txMock.base2, txMock.base3, txMock.base4 ] });
await page.waitForSelector('tbody tr:nth-child(3)');
const thirdRow = page.locator('tbody tr:nth-child(3)');
await thirdRow.waitFor();
const itemsCountNew = await page.locator('tbody tr').count();
expect(itemsCountNew).toBe(3);
......@@ -179,7 +182,8 @@ test.describe('socket', () => {
socketServer.sendMessage(socket, channel, 'transaction', { transactions: [ txMock.base2, txMock.base4 ] });
await page.waitForSelector('tbody tr:nth-child(3)');
const thirdRow = page.locator('tbody tr:nth-child(3)');
await thirdRow.waitFor();
const itemsCountNew = await page.locator('tbody tr').count();
expect(itemsCountNew).toBe(3);
......@@ -214,7 +218,8 @@ test.describe('socket', () => {
socketServer.sendMessage(socket, channel, 'transaction', { transactions: [ txMock.base2, txMock.base3, txMock.base4 ] });
await page.waitForSelector('tbody tr:nth-child(3)');
const thirdRow = page.locator('tbody tr:nth-child(3)');
await thirdRow.waitFor();
const itemsCountNew = await page.locator('tbody tr').count();
expect(itemsCountNew).toBe(3);
......
......@@ -52,7 +52,7 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
});
};
const mutation = useMutation({
const { mutateAsync, isPending } = useMutation({
mutationFn: updateApiKey,
onSuccess: async(data) => {
const response = data as unknown as ApiKey;
......@@ -89,8 +89,8 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
const onSubmit: SubmitHandler<Inputs> = useCallback(async(data) => {
setAlertVisible(false);
await mutation.mutateAsync(data);
}, [ mutation, setAlertVisible ]);
await mutateAsync(data);
}, [ mutateAsync, setAlertVisible ]);
return (
<FormProvider { ...formApi }>
......@@ -119,7 +119,7 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
size="lg"
type="submit"
isDisabled={ !formApi.formState.isDirty }
isLoading={ mutation.isPending }
isLoading={ isPending }
>
{ data ? 'Save' : 'Generate API key' }
</Button>
......
......@@ -157,14 +157,12 @@ export default function useBlockTxsQuery({ heightOrHash, blockQuery, tab }: Para
((apiQuery.isError || apiQuery.isPlaceholderData) && apiQuery.errorUpdateCount > 0)
) && rpcQuery.data && publicClient);
const rpcQueryWithPages: QueryWithPagesResult<'block_txs'> = React.useMemo(() => {
return {
const rpcQueryWithPages: QueryWithPagesResult<'block_txs'> = {
...rpcQuery as UseQueryResult<BlockTransactionsResponse, ResourceError>,
pagination: emptyPagination,
onFilterChange: () => {},
onSortingChange: () => {},
};
}, [ rpcQuery ]);
const query = isRpcQuery ? rpcQueryWithPages : apiQuery;
......
......@@ -124,14 +124,12 @@ export default function useBlockWithdrawalsQuery({ heightOrHash, blockQuery, tab
((apiQuery.isError || apiQuery.isPlaceholderData) && apiQuery.errorUpdateCount > 0)
) && rpcQuery.data && publicClient);
const rpcQueryWithPages: QueryWithPagesResult<'block_withdrawals'> = React.useMemo(() => {
return {
const rpcQueryWithPages: QueryWithPagesResult<'block_withdrawals'> = {
...rpcQuery as UseQueryResult<BlockWithdrawalsResponse, ResourceError>,
pagination: emptyPagination,
onFilterChange: () => {},
onSortingChange: () => {},
};
}, [ rpcQuery ]);
const query = isRpcQuery ? rpcQueryWithPages : apiQuery;
......
......@@ -62,7 +62,7 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose, onSuccess, setAlertVisi
});
};
const mutation = useMutation({
const { mutateAsync, isPending } = useMutation({
mutationFn: customAbiKey,
onSuccess: async(data) => {
const response = data as unknown as CustomAbi;
......@@ -101,8 +101,8 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose, onSuccess, setAlertVisi
const onSubmit: SubmitHandler<Inputs> = useCallback(async(formData) => {
setAlertVisible(false);
const id = data && 'id' in data ? String(data.id) : undefined;
await mutation.mutateAsync({ ...formData, id });
}, [ mutation, data, setAlertVisible ]);
await mutateAsync({ ...formData, id });
}, [ mutateAsync, data, setAlertVisible ]);
return (
<FormProvider { ...formApi }>
......@@ -140,7 +140,7 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose, onSuccess, setAlertVisi
size="lg"
type="submit"
isDisabled={ !formApi.formState.isDirty }
isLoading={ mutation.isPending }
isLoading={ isPending }
>
{ data && 'id' in data ? 'Save' : 'Create custom ABI' }
</Button>
......
......@@ -40,7 +40,7 @@ test.describe('default view', () => {
test.describe('screen xl', () => {
test.use({ viewport: pwConfig.viewport.xl });
test('', async({ page }) => {
test('base view', async({ page }) => {
await expect(component).toHaveScreenshot({
mask: [ page.locator(pwConfig.adsBannerSelector) ],
maskColor: pwConfig.maskColor,
......
......@@ -39,7 +39,7 @@ const DeleteModal: React.FC<Props> = ({
onClose();
}, [ onClose, setAlertVisible ]);
const mutation = useMutation({
const { mutate, isPending } = useMutation({
mutationFn,
onSuccess: async() => {
onSuccess();
......@@ -52,8 +52,8 @@ const DeleteModal: React.FC<Props> = ({
const onDeleteClick = useCallback(() => {
setAlertVisible(false);
mutation.mutate();
}, [ setAlertVisible, mutation ]);
mutate();
}, [ setAlertVisible, mutate ]);
const isMobile = useIsMobile();
......@@ -71,7 +71,7 @@ const DeleteModal: React.FC<Props> = ({
<Button
size="lg"
onClick={ onDeleteClick }
isLoading={ mutation.isPending }
isLoading={ isPending }
// FIXME: chackra's button is disabled when isLoading
isDisabled={ false }
>
......
......@@ -19,7 +19,7 @@ test.use({ viewport: { width: 180, height: 140 } });
test.describe('icon size', () => {
iconSizes.forEach((size) => {
test(size, async({ render }) => {
test(`${ size }`, async({ render }) => {
const component = await render(
<AddressEntity
address={ addressMock.withoutName }
......
......@@ -10,7 +10,7 @@ test.use({ viewport: { width: 180, height: 30 } });
test.describe('icon sizes', () => {
iconSizes.forEach((size) => {
test(size, async({ render }) => {
test(`${ size }`, async({ render }) => {
const component = await render(
<BlockEntity
number={ 17943507 }
......
......@@ -12,7 +12,7 @@ test.use({ viewport: { width: 180, height: 30 } });
test.describe('icon size', () => {
iconSizes.forEach((size) => {
test(size, async({ render }) => {
test(`${ size }`, async({ render }) => {
const component = await render(
<EnsEntity
domain={ name }
......@@ -61,8 +61,9 @@ test('customization', async({ render }) => {
await expect(component).toHaveScreenshot();
});
test.describe('', () => {
test.describe('tooltip test', () => {
test.use({ viewport: { width: 300, height: 400 } });
test('with protocol info', async({ render, page, mockAssetResponse }) => {
await mockAssetResponse(domainMock.ensDomainA.protocol?.icon_url as string, './playwright/mocks/image_s.jpg');
......
......@@ -11,7 +11,7 @@ test.use({ viewport: { width: 180, height: 30 } });
test.describe('icon sizes', () => {
iconSizes.forEach((size) => {
test(size, async({ render }) => {
test(`${ size }`, async({ render }) => {
const component = await render(
<NftEntity
hash={ hash }
......
......@@ -12,7 +12,7 @@ test.use({ viewport: { width: 300, height: 100 } });
test.describe('icon size', () => {
iconSizes.forEach((size) => {
test(size, async({ render }) => {
test(`${ size }`, async({ render }) => {
const component = await render(
<TokenEntity
token={ tokenMock.tokenInfo }
......
......@@ -11,7 +11,7 @@ test.use({ viewport: { width: 180, height: 30 } });
test.describe('icon size', () => {
iconSizes.forEach((size) => {
test(size, async({ render }) => {
test(`${ size }`, async({ render }) => {
const component = await render(
<TxEntity
hash={ hash }
......
......@@ -11,7 +11,7 @@ test.use({ viewport: { width: 180, height: 30 } });
test.describe('icon size', () => {
iconSizes.forEach((size) => {
test(size, async({ render }) => {
test(`${ size }`, async({ render }) => {
const component = await render(
<UserOpEntity
hash={ hash }
......
......@@ -32,7 +32,7 @@ test.describe('with custom links, max cols', () => {
test.describe('screen xl', () => {
test.use({ viewport: pwConfig.viewport.xl });
test('', async({ page }) => {
test('base view', async({ page }) => {
await expect(page).toHaveScreenshot();
});
});
......
......@@ -89,7 +89,7 @@ authTest.describe('auth', () => {
test.describe('with tooltips', () => {
test.use({ viewport: pwConfig.viewport.xl });
test('', async({ render, page }) => {
test('base view', async({ render, page }) => {
const component = await render(
<Flex w="100%" minH="100vh" alignItems="stretch">
<NavigationDesktop/>
......@@ -120,14 +120,14 @@ test.describe('with submenu', () => {
await page.locator('div[aria-label="Blockchain link group"]').hover();
});
test('', async() => {
test('base view', async() => {
await expect(component).toHaveScreenshot();
});
test.describe('xl screen', () => {
test.use({ viewport: pwConfig.viewport.xl });
test('', async() => {
test('base view', async() => {
await expect(component).toHaveScreenshot();
});
});
......
......@@ -78,14 +78,14 @@ test.describe('custom logo with dark option -@default +@dark-mode', () => {
component = await render(<NetworkLogo/>);
});
test('', async() => {
test('base view', async() => {
await expect(component.locator('a')).toHaveScreenshot();
});
test.describe('screen xl', () => {
test.use({ viewport: pwConfig.viewport.xl });
test('', async() => {
test('base view', async() => {
await expect(component.locator('a')).toHaveScreenshot();
});
});
......
......@@ -6,9 +6,7 @@ import * as pwConfig from 'playwright/utils/config';
import TxsTable from './TxsTable';
test.describe('base view', () => {
test('+@dark-mode', async({ render }) => {
test('base view +@dark-mode', async({ render }) => {
const component = await render(
<TxsTable
txs={ [ txMock.base, txMock.withWatchListNames ] }
......@@ -23,12 +21,12 @@ test.describe('base view', () => {
await component.getByText('kitty').first().hover();
await expect(component).toHaveScreenshot();
});
});
test.describe('screen xl', () => {
test.describe('screen xl', () => {
test.use({ viewport: pwConfig.viewport.xl });
test('', async({ render }) => {
test('base view', async({ render }) => {
const component = await render(
<TxsTable
txs={ [ txMock.base, txMock.withWatchListNames ] }
......@@ -44,5 +42,4 @@ test.describe('base view', () => {
await expect(component).toHaveScreenshot();
});
});
});
......@@ -79,7 +79,7 @@ export default function useDescribeTxs(items: Array<Transaction> | undefined, vi
}
return tx;
}), [ items, describeQuery ]);
}), [ items, describeQuery.data, describeQuery.isLoading ]);
if (!translateEnabled || isPlaceholderData) {
return items;
......
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