Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RPC tests #2101

Merged
merged 4 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions mocks/blocks/block.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* eslint-disable max-len */
import type { RpcBlock } from 'viem';

import type { Block, BlocksResponse } from 'types/api/block';

export const base: Block = {
Expand Down Expand Up @@ -144,10 +146,119 @@ export const withBlobTxs: Block = {
blob_tx_count: 1,
};

export const withWithdrawals: Block = {
...base,
withdrawals_count: 2,
};

export const baseListResponse: BlocksResponse = {
items: [
base,
base2,
],
next_page_params: null,
};

export const rpcBlockBase: RpcBlock = {
difficulty: '0x37fcc04bef8',
extraData: '0x476574682f76312e302e312d38326566323666362f6c696e75782f676f312e34',
gasLimit: '0x2fefd8',
gasUsed: '0x0',
hash: '0xfbafb4b7b6f6789338d15ff046f40dc608a42b1a33b093e109c6d7a36cd76f61',
logsBloom: '0x0',
miner: '0xe6a7a1d47ff21b6321162aea7c6cb457d5476bca',
mixHash: '0x038956b9df89d0c1f980fd656d045e912beafa515cff7d7fd3c5f34ffdcb9e4b',
nonce: '0xd8d3392f340bbb22',
number: '0x1869f',
parentHash: '0x576fd45e598c9f86835f50fe2c6e6d11df2d4c4b01f19e4241b7e793d852f9e4',
receiptsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
size: '0x225',
stateRoot: '0x32356228651d64cc5e6e7be87a556ecdbf40e876251dc867ba9e4bb82a0124a3',
timestamp: '0x55d19741',
totalDifficulty: '0x259e89748daae17',
transactions: [
'0x0e70849f10e22fe2e53fe6755f86a572aa6bb2fc472f0b87d9e561efa1fc2e1f',
'0xae5624c77f06d0164301380afa7780ebe49debe77eb3d5167004d69bd188a09f',
],
transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
uncles: [],
baseFeePerGas: null,
blobGasUsed: `0x0`,
excessBlobGas: `0x0`,
sealFields: [],
withdrawals: [
{ address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', amount: '0x12128cd', index: '0x3216bbb', validatorIndex: '0x4dca3' },
{ address: '0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f', amount: '0x12027dd', index: '0x3216bbc', validatorIndex: '0x4dca4' },
],
};

export const rpcBlockWithTxsInfo: RpcBlock = {
...rpcBlockBase,
transactions: [
{
accessList: [
{
address: '0x7af661a6463993e05a171f45d774cf37e761c83f',
storageKeys: [
'0x0000000000000000000000000000000000000000000000000000000000000007',
'0x000000000000000000000000000000000000000000000000000000000000000c',
'0x0000000000000000000000000000000000000000000000000000000000000008',
'0x0000000000000000000000000000000000000000000000000000000000000006',
'0x0000000000000000000000000000000000000000000000000000000000000009',
'0x000000000000000000000000000000000000000000000000000000000000000a',
],
},
{
address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
storageKeys: [
'0x0d726f311404f8052d44e7004a6ffb747709a6d3666a62ce3f5aad13374680ab',
'0x1a824a6850dcbd9223afea4418727593881e2911ed2e734272a263153159fe26',
'0xfae3a383c82daf853bbd8bbcd21280410599b135c274c01354ea7d3a5e09f43c',
],
},
],
blockHash: '0xeb37ebc94e31773e5c5703073fd3911b2ab596f099d00d18b55ae3ac8203c1d5',
blockNumber: '0x136058d',
chainId: '0x1',
from: '0x111527f1386c6725a2f5986230f3060bdcac041f',
gas: '0xf4240',
gasPrice: '0x1780b2ff9',
hash: '0x0e70849f10e22fe2e53fe6755f86a572aa6bb2fc472f0b87d9e561efa1fc2e1f',
input: '0x258d7af661a6463993e05a171f45d774cf37e761c83f402ab3277301b3574863a151d042dc870fb1b3f0c72cbbdd53a85898f62415fe124406f6608d8802269d1283cdb2a5a329649e5cb4cdcee91ab6',
// maxFeePerGas: '0x3ac1bf7ee',
// maxPriorityFeePerGas: '0x0',
nonce: '0x127b2',
r: '0x3c47223f880a3fb7b1eca368d9d7320d2278f0b679109d9ed0af4080ee386f23',
s: '0x587a441f9472b312ff302d7132547aa250ea06c6203c76831d56a46ec188e664',
to: '0x000000d40b595b94918a28b27d1e2c66f43a51d3',
transactionIndex: '0x0',
type: '0x1',
v: '0x1',
value: '0x31',
yParity: '0x1',
},
{
accessList: [],
blockHash: '0xeb37ebc94e31773e5c5703073fd3911b2ab596f099d00d18b55ae3ac8203c1d5',
blockNumber: '0x136058d',
chainId: '0x1',
from: '0xe25d2cb47b606bb6fd9272125457a7230e26f956',
gas: '0x47bb0',
gasPrice: '0x1ba875cb6',
hash: '0xae5624c77f06d0164301380afa7780ebe49debe77eb3d5167004d69bd188a09f',
input: '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000006696237b00000000000000000000000000000000000000000000000000000000000000040b080604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000006d1aaedfab0f00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000d84d4e8e1e8f268e027c29fa4d48c4b7e4d422990000000000000000000000000000000000000000000000000000000000000060000000000000000000000000d84d4e8e1e8f268e027c29fa4d48c4b7e4d42299000000000000000000000000000000fee13a103a10d593b9ae06b3e05f2e7e1c00000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000060000000000000000000000000d84d4e8e1e8f268e027c29fa4d48c4b7e4d42299000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000006cd4db3c8c8d',
// maxFeePerGas: '0x23493c9cd',
// maxPriorityFeePerGas: '0x427c2cbd',
nonce: '0x32b',
r: '0x6566181b3cfd01702b24a2124ea7698b8cc815c7f37d1ea55800f176ca7a94cf',
s: '0x34f8dd837f37746ccd18f4fa71e05de98a2212f1c931f740598e491518616bb3',
to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad',
transactionIndex: '0x1',
type: '0x1',
v: '0x1',
value: '0xb1a2bc2ec50000',
yParity: '0x1',
},
],
};
5 changes: 3 additions & 2 deletions playwright/fixtures/mockApiResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface Options<R extends ResourceName> {
pathParams?: Parameters<typeof buildUrl<R>>[1];
queryParams?: Parameters<typeof buildUrl<R>>[2];
times?: number;
status?: number;
}

export type MockApiResponseFixture = <R extends ResourceName>(resourceName: R, responseMock: ResourcePayload<R>, options?: Options<R>) => Promise<string>;
Expand All @@ -16,8 +17,8 @@ const fixture: TestFixture<MockApiResponseFixture, { page: Page }> = async({ pag
const apiUrl = buildUrl(resourceName, options?.pathParams, options?.queryParams);

await page.route(apiUrl, (route) => route.fulfill({
status: 200,
body: JSON.stringify(responseMock),
status: options?.status ?? 200,
json: responseMock,
}), { times: options?.times });

return apiUrl;
Expand Down
13 changes: 6 additions & 7 deletions playwright/fixtures/mockRpcResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ type Params = PublicRpcSchema[number];

export type MockRpcResponseFixture = (params: Params) => Promise<void>;

// WIP
const fixture: TestFixture<MockRpcResponseFixture, { page: Page }> = async({ page }, use) => {
await use(async({ Method, ReturnType }) => {
await use(async(rpcMock) => {
const rpcUrl = getEnvValue('NEXT_PUBLIC_NETWORK_RPC_URL');

if (!rpcUrl) {
Expand All @@ -31,18 +30,18 @@ const fixture: TestFixture<MockRpcResponseFixture, { page: Page }> = async({ pag
const payload = {
id,
jsonrpc: '2.0',
method: Method,
// TODO: add params to match actual payload
method: rpcMock.Method,
...(rpcMock.Parameters ? { params: rpcMock.Parameters } : {}),
};

if (_isEqual(json, payload) && id !== undefined) {
return route.fulfill({
status: 200,
body: JSON.stringify({
json: {
id,
jsonrpc: '2.0',
result: ReturnType,
}),
result: rpcMock.ReturnType,
},
});
}
});
Expand Down
23 changes: 23 additions & 0 deletions ui/pages/Address.pw.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React from 'react';
import { numberToHex } from 'viem';

import config from 'configs/app';
import * as addressMock from 'mocks/address/address';
import * as addressCountersMock from 'mocks/address/counters';
import * as addressTabCountersMock from 'mocks/address/tabCounters';
import * as socketServer from 'playwright/fixtures/socketServer';
import { test, expect } from 'playwright/lib';
import * as pwConfig from 'playwright/utils/config';

import Address from './Address';

Expand All @@ -31,3 +34,23 @@ test.describe('fetched bytecode', () => {
expect(request).toBeTruthy();
});
});

test('degradation view', async({ render, page, mockRpcResponse, mockApiResponse }) => {
await mockApiResponse('address', null as never, { pathParams: { hash: addressMock.hash }, status: 500 });
await mockApiResponse('address_counters', addressCountersMock.forValidator, { pathParams: { hash: addressMock.hash } });
await mockApiResponse('address_tabs_counters', null as never, { pathParams: { hash: addressMock.hash }, status: 500 });
await mockApiResponse('address_txs', null as never, { pathParams: { hash: addressMock.hash }, status: 500 });
await mockRpcResponse({
Method: 'eth_getBalance',
Parameters: [ addressMock.hash, 'latest' ],
ReturnType: numberToHex(1234567890123456),
});

const component = await render(<Address/>, { hooksConfig });
await page.waitForResponse(config.chain.rpcUrl as string);

await expect(component).toHaveScreenshot({
mask: [ page.locator(pwConfig.adsBannerSelector) ],
maskColor: pwConfig.maskColor,
});
});
77 changes: 77 additions & 0 deletions ui/pages/Block.pw.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from 'react';
import { numberToHex } from 'viem';

import config from 'configs/app';
import * as blockMock from 'mocks/blocks/block';
import { ENVS_MAP } from 'playwright/fixtures/mockEnvs';
import { test, expect } from 'playwright/lib';

import Block from './Block';

const height = String(blockMock.base.height);
const hooksConfig = {
router: {
query: { height_or_hash: height },
},
};

test.beforeEach(async({ mockTextAd }) => {
await mockTextAd();
});

test('degradation view, details tab', async({ render, mockApiResponse, mockRpcResponse, page }) => {
await mockApiResponse('block', null as never, { pathParams: { height_or_hash: height }, status: 500 });
await mockRpcResponse({
Method: 'eth_getBlockByNumber',
Parameters: [ numberToHex(Number(height)), false ],
ReturnType: blockMock.rpcBlockBase,
});

const component = await render(<Block/>, { hooksConfig });
await page.waitForResponse(config.chain.rpcUrl as string);

await expect(component).toHaveScreenshot();
});

test('degradation view, txs tab', async({ render, mockApiResponse, mockRpcResponse, page }) => {
const hooksConfig = {
router: {
query: { height_or_hash: height, tab: 'txs' },
},
};

await mockApiResponse('block', blockMock.base, { pathParams: { height_or_hash: height } });
await mockApiResponse('block_txs', null as never, { pathParams: { height_or_hash: height }, status: 500 });
await mockRpcResponse({
Method: 'eth_getBlockByNumber',
Parameters: [ numberToHex(Number(height)), true ],
ReturnType: blockMock.rpcBlockWithTxsInfo,
});

const component = await render(<Block/>, { hooksConfig });
await page.waitForResponse(config.chain.rpcUrl as string);

await expect(component).toHaveScreenshot();
});

test('degradation view, withdrawals tab', async({ render, mockApiResponse, mockRpcResponse, mockEnvs, page }) => {
const hooksConfig = {
router: {
query: { height_or_hash: height, tab: 'withdrawals' },
},
};

await mockEnvs(ENVS_MAP.beaconChain);
await mockApiResponse('block', blockMock.withWithdrawals, { pathParams: { height_or_hash: height } });
await mockApiResponse('block_withdrawals', null as never, { pathParams: { height_or_hash: height }, status: 500 });
await mockRpcResponse({
Method: 'eth_getBlockByNumber',
Parameters: [ numberToHex(Number(height)), false ],
ReturnType: blockMock.rpcBlockBase,
});

const component = await render(<Block/>, { hooksConfig });
await page.waitForResponse(config.chain.rpcUrl as string);

await expect(component).toHaveScreenshot();
});
12 changes: 9 additions & 3 deletions ui/pages/MarketplaceApp.pw.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Flex } from '@chakra-ui/react';
import React from 'react';
import { numberToHex } from 'viem';

import config from 'configs/app';
import { apps as appsMock } from 'mocks/apps/apps';
import { test, expect, devices } from 'playwright/lib';

Expand All @@ -15,13 +17,17 @@ const hooksConfig = {

const MARKETPLACE_CONFIG_URL = 'https://marketplace-config.json';

const testFn: Parameters<typeof test>[1] = async({ render, mockConfigResponse, mockAssetResponse, mockEnvs }) => {
const testFn: Parameters<typeof test>[1] = async({ render, mockConfigResponse, mockAssetResponse, mockEnvs, mockRpcResponse }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_MARKETPLACE_ENABLED', 'true' ],
[ 'NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', MARKETPLACE_CONFIG_URL ],
]);
await mockConfigResponse('NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', MARKETPLACE_CONFIG_URL, JSON.stringify(appsMock));
await mockAssetResponse(appsMock[0].url, './mocks/apps/app.html');
await mockRpcResponse({
Method: 'eth_chainId',
ReturnType: numberToHex(Number(config.chain.id)),
});

const component = await render(
<Flex flexDirection="column" mx={{ base: 4, lg: 6 }} h="100vh">
Expand All @@ -33,9 +39,9 @@ const testFn: Parameters<typeof test>[1] = async({ render, mockConfigResponse, m
await expect(component).toHaveScreenshot();
};

test.fixme('base view +@dark-mode', testFn);
test('base view +@dark-mode', testFn);

test.describe('mobile', () => {
test.use({ viewport: devices['iPhone 13 Pro'].viewport });
test.fixme('base view', testFn);
test('base view', testFn);
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading