Commit 0643a728 authored by Max Alekseenko's avatar Max Alekseenko

Merge branch 'main' into dapp-rating

parents 48a26fdd cabfcc32
/* eslint-disable max-len */
import type { RpcBlock } from 'viem';
import type { Block, BlocksResponse } from 'types/api/block';
export const base: Block = {
......@@ -144,6 +146,11 @@ export const withBlobTxs: Block = {
blob_tx_count: 1,
};
export const withWithdrawals: Block = {
...base,
withdrawals_count: 2,
};
export const baseListResponse: BlocksResponse = {
items: [
base,
......@@ -151,3 +158,107 @@ export const baseListResponse: BlocksResponse = {
],
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',
},
],
};
......@@ -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>;
......@@ -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;
......
......@@ -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) {
......@@ -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,
},
});
}
});
......
......@@ -45,7 +45,7 @@ const ContractVerificationFieldCode = ({ isVyper }: Props) => {
{ isVyper ? null : (
<>
<span>We recommend using flattened code. This is necessary if your code utilizes a library or inherits dependencies. Use the </span>
<Link href="https://github.com/poanetwork/solidity-flattener" target="_blank">POA solidity flattener</Link>
<Link href="https://hardhat.org/hardhat-runner/docs/advanced/flattening" target="_blank">Hardhat flattener</Link>
<span> or the </span>
<Link href="https://www.npmjs.com/package/truffle-flattener" target="_blank">Truffle flattener</Link>
</>
......
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';
......@@ -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,
});
});
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();
});
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';
......@@ -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">
......@@ -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);
});
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