Commit 1970d436 authored by tom's avatar tom

fix some tests

parent 16665b32
......@@ -10,10 +10,12 @@ const baseUrl = [
appPort && ':' + appPort,
].filter(Boolean).join('');
const isDev = getEnvValue('NEXT_PUBLIC_APP_ENV') === 'development';
const isPw = getEnvValue('NEXT_PUBLIC_APP_INSTANCE') === 'pw';
const spriteHash = getEnvValue('NEXT_PUBLIC_ICON_SPRITE_HASH');
const app = Object.freeze({
isDev,
isPw,
protocol: appSchema,
host: appHost,
port: appPort,
......
......@@ -2,6 +2,7 @@ import { Tooltip as ChakraTooltip, Portal } from '@chakra-ui/react';
import { useClickAway } from '@uidotdev/usehooks';
import * as React from 'react';
import config from 'configs/app';
import useIsMobile from 'lib/hooks/useIsMobile';
export interface TooltipProps extends ChakraTooltip.RootProps {
......@@ -37,7 +38,7 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
...rest
} = props;
const [ open, setOpen ] = React.useState(defaultOpen);
const [ open, setOpen ] = React.useState<boolean>(defaultOpen);
const isMobile = useIsMobile();
const triggerRef = useClickAway<HTMLButtonElement>(() => setOpen(false));
......@@ -58,6 +59,7 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
const positioning = {
...rest.positioning,
overflowPadding: 4,
offset: {
mainAxis: 4,
...rest.positioning?.offset,
......@@ -67,9 +69,11 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
return (
<ChakraTooltip.Root
openDelay={ 100 }
closeDelay={ 100 }
// FIXME: chakra closes tooltip too fast, so Playwright is not able to make a screenshot of its content
// so we need to increase the close delay in Playwright environment
closeDelay={ config.app.isPw ? 10_000 : 100 }
open={ open }
onOpenChange={ isMobile ? undefined : handleOpenChange }
onOpenChange={ handleOpenChange }
closeOnClick={ false }
closeOnPointerDown={ true }
variant={ variant }
......
......@@ -114,8 +114,8 @@ test('base view +@mobile +@dark-mode', async({ render }) => {
await component.getByPlaceholder('uint256').last().fill('42');
await component.getByRole('button', { name: '×' }).last().click();
await component.getByPlaceholder('bytes32').last().fill('aa');
await component.getByRole('button', { name: 'add' }).last().click();
await component.getByRole('button', { name: 'add' }).last().click();
await component.getByLabel('add').last().click();
await component.getByLabel('add').last().click();
await component.getByPlaceholder('int8', { exact: true }).first().fill('1');
await component.getByPlaceholder('int8', { exact: true }).last().fill('3');
......@@ -123,15 +123,15 @@ test('base view +@mobile +@dark-mode', async({ render }) => {
await component.getByText('parameters').click();
await component.getByText('additionalRecipients').click();
await component.getByText('#1 AdditionalRecipient').click();
await component.getByRole('button', { name: 'add' }).first().click();
await component.getByLabel('add').first().click();
await component.getByPlaceholder('uint256').nth(1).fill('42');
await component.getByPlaceholder('address').nth(1).fill('0xd789a607CEac2f0E14867de4EB15b15C9FFB5859');
await component.getByText('struct FulfillmentComponent[][]').click();
await component.getByRole('button', { name: 'add' }).nth(1).click();
await component.getByLabel('add').nth(1).click();
await component.getByText('#1 FulfillmentComponent[]').click();
await component.getByLabel('#1 FulfillmentComponent[] (tuple[])').getByText('#1 FulfillmentComponent (tuple)').click();
await component.getByRole('button', { name: 'add' }).nth(1).click();
await component.getByLabel('add').nth(1).click();
await component.getByText('ParentArray (int256[2][][3])').click();
await component.getByText('#1 int256[2][] (int256[2][])').click();
......
......@@ -44,5 +44,5 @@ test('INVALID_SIGNER_ERROR view +@mobile', async({ render, page }) => {
await signatureInput.fill(mocks.SIGNATURE);
await page.getByRole('button', { name: /verify/i }).click();
await expect(page).toHaveScreenshot();
await expect(page).toHaveScreenshot({ fullPage: true });
});
......@@ -219,7 +219,7 @@ const AddressVerificationStepSignature = ({ address, signingMessage, contractCre
) }
<Flex rowGap={ 5 } flexDir="column">
<div>
<CopyToClipboard text={ signingMessage } ml="auto" display="block"/>
<CopyToClipboard text={ signingMessage } ml="auto" mb={ 2 }/>
<FormFieldText<Fields>
name="message"
placeholder="Message to sign"
......@@ -227,7 +227,7 @@ const AddressVerificationStepSignature = ({ address, signingMessage, contractCre
asComponent="Textarea"
readOnly
inputProps={{
h: { base: '180px', lg: '130px' },
h: { base: '175px', lg: '100px' },
minH: 'auto',
}}
/>
......
......@@ -43,7 +43,7 @@ const BlockEpochElectionRewardDetailsDesktop = ({ type, token }: Props) => {
maxH="360px"
overflowY="scroll"
fontWeight={ 400 }
lineHeight={ 5 }
textStyle="sm"
>
{ query.data && (
<Grid
......
......@@ -12,13 +12,24 @@ const hooksConfig = {
},
};
test('base view +@mobile', async({ render, mockApiResponse }) => {
test('base view', async({ render, mockApiResponse }) => {
await mockApiResponse(
'block_election_rewards',
blockEpochMock.electionRewardDetails1,
{ pathParams: { height_or_hash: heightOrHash, reward_type: 'voter' } },
);
const component = await render(<BlockEpochElectionRewards data={ blockEpochMock.blockEpoch1 }/>, { hooksConfig });
await component.getByText('Voting rewards').click();
await component.getByRole('cell', { name: 'Voting rewards' }).click();
await expect(component).toHaveScreenshot();
});
test('base view +@mobile -@default', async({ render, mockApiResponse }) => {
await mockApiResponse(
'block_election_rewards',
blockEpochMock.electionRewardDetails1,
{ pathParams: { height_or_hash: heightOrHash, reward_type: 'voter' } },
);
const component = await render(<BlockEpochElectionRewards data={ blockEpochMock.blockEpoch1 }/>, { hooksConfig });
await component.locator('div').filter({ hasText: 'Voting rewards' }).nth(3).click();
await expect(component).toHaveScreenshot();
});
......@@ -22,7 +22,7 @@ const MyProfileFieldsEmail = ({ isReadOnly, defaultValue }: Props) => {
group={{
endElement: ({ field }) => {
const isVerified = defaultValue && field.value === defaultValue;
return isVerified ? <IconSvg name="certified" boxSize={ 5 } color="green.500"/> : null;
return isVerified ? <IconSvg name="certified" boxSize={ 5 } color="green.500" mx={ 5 }/> : null;
},
}}
/>
......
import { Box, chakra } from '@chakra-ui/react';
import { Flex, chakra } from '@chakra-ui/react';
import React from 'react';
import { Tooltip } from 'toolkit/chakra/tooltip';
......@@ -13,9 +13,9 @@ type Props = {
const ContractCertifiedLabel = ({ iconSize, className }: Props) => {
return (
<Tooltip content="This contract has been certified by the chain developers">
<Box className={ className }>
<Flex className={ className }>
<IconSvg name="certified" color="green.500" boxSize={ iconSize } cursor="pointer"/>
</Box>
</Flex>
</Tooltip>
);
};
......
......@@ -41,6 +41,7 @@ test.describe('contract', () => {
);
await component.getByText(/eternal/i).hover();
await page.locator('div').filter({ hasText: 'EternalStorageProxy' }).first().waitFor({ state: 'visible' });
await expect(page).toHaveScreenshot();
});
......@@ -66,7 +67,7 @@ test.describe('proxy contract', () => {
);
await component.getByText(/home/i).hover();
await expect(page.getByText('Proxy contract')).toBeVisible();
await page.getByText(/implementation/i).waitFor({ state: 'visible' });
await expect(page).toHaveScreenshot();
});
......@@ -78,7 +79,7 @@ test.describe('proxy contract', () => {
);
await component.getByText(/eternal/i).hover();
await expect(page.getByText('Proxy contract')).toBeVisible();
await page.getByText(/implementation/i).waitFor({ state: 'visible' });
await expect(page).toHaveScreenshot();
});
......@@ -90,7 +91,7 @@ test.describe('proxy contract', () => {
);
await component.getByText(addressMock.contract.hash.slice(0, 4)).hover();
await expect(page.getByText('Proxy contract')).toBeVisible();
await page.getByText(/implementation/i).waitFor({ state: 'visible' });
await expect(page).toHaveScreenshot();
});
......@@ -102,7 +103,7 @@ test.describe('proxy contract', () => {
);
await component.getByText(/eternal/i).hover();
await expect(page.getByText('Proxy contract')).toBeVisible();
await page.getByText(/implementation/i).waitFor({ state: 'visible' });
await expect(page).toHaveScreenshot();
});
......@@ -114,7 +115,7 @@ test.describe('proxy contract', () => {
);
await component.getByText(/quack/i).hover();
await expect(page.getByText('Proxy contract')).toBeVisible();
await page.getByText(/implementation/i).waitFor({ state: 'visible' });
await expect(page).toHaveScreenshot();
});
});
......@@ -222,6 +223,7 @@ test('hover', async({ page, render }) => {
);
await component.getByText(addressMock.hash.slice(0, 4)).hover();
await page.getByText(addressMock.hash).waitFor({ state: 'visible' });
await expect(page).toHaveScreenshot();
});
......
......@@ -49,7 +49,7 @@ const AddressEntityContentProxy = (props: ContentProps) => {
);
return (
<Tooltip content={ content } interactive contentProps={{ maxW: { base: '100vw', lg: '410px' } }}>
<Tooltip content={ content } interactive contentProps={{ maxW: { base: 'calc(100vw - 8px)', lg: '410px' } }}>
<Box display="inline-flex" w="100%">
<EntityBase.Content
{ ...props }
......
......@@ -15,48 +15,48 @@ test.use({ viewport: { width: 300, height: 300 } });
test('all data', async({ render, page }) => {
await render(
<GasInfoTooltip data={ statsMock.base } dataUpdatedAt={ dataUpdatedAt } isOpen>
<GasInfoTooltip data={ statsMock.base } dataUpdatedAt={ dataUpdatedAt }>
<span>Gas <GasPrice data={ statsMock.base.gas_prices?.average as GasPriceInfo }/></span>
</GasInfoTooltip>,
);
// await page.getByText(/gas/i).hover();
await page.getByText(/gas/i).hover();
await page.getByText(/last update/i).isVisible();
await expect(page).toHaveScreenshot();
});
test('without primary unit price', async({ render, page }) => {
await render(
<GasInfoTooltip data={ statsMock.withoutFiatPrices } dataUpdatedAt={ dataUpdatedAt } isOpen>
<GasInfoTooltip data={ statsMock.withoutFiatPrices } dataUpdatedAt={ dataUpdatedAt }>
<span>Gas: <GasPrice data={ statsMock.withoutFiatPrices.gas_prices?.average as GasPriceInfo }/></span>
</GasInfoTooltip>,
);
// await page.getByText(/gas/i).hover();
await page.getByText(/gas/i).hover();
await page.getByText(/last update/i).isVisible();
await expect(page).toHaveScreenshot();
});
test('without secondary unit price', async({ render, page }) => {
await render(
<GasInfoTooltip data={ statsMock.withoutGweiPrices } dataUpdatedAt={ dataUpdatedAt } isOpen>
<GasInfoTooltip data={ statsMock.withoutGweiPrices } dataUpdatedAt={ dataUpdatedAt }>
<span>Gas: <GasPrice data={ statsMock.withoutGweiPrices.gas_prices?.average as GasPriceInfo }/></span>
</GasInfoTooltip>,
);
// await page.getByText(/gas/i).hover();
await page.getByText(/gas/i).hover();
await page.getByText(/last update/i).isVisible();
await expect(page).toHaveScreenshot();
});
test('no data', async({ render, page }) => {
await render(
<GasInfoTooltip data={ statsMock.withoutBothPrices } dataUpdatedAt={ dataUpdatedAt } isOpen>
<GasInfoTooltip data={ statsMock.withoutBothPrices } dataUpdatedAt={ dataUpdatedAt }>
<span>Gas: <GasPrice data={ statsMock.withoutBothPrices.gas_prices?.average as GasPriceInfo }/></span>
</GasInfoTooltip>,
);
// await page.getByText(/gas/i).hover();
await page.getByText(/gas/i).hover();
await page.getByText(/last update/i).isVisible();
await expect(page).toHaveScreenshot();
});
......@@ -70,24 +70,24 @@ test.describe('one unit', () => {
test('with data', async({ render, page }) => {
await render(
<GasInfoTooltip data={ statsMock.withoutFiatPrices } dataUpdatedAt={ dataUpdatedAt } isOpen>
<GasInfoTooltip data={ statsMock.withoutFiatPrices } dataUpdatedAt={ dataUpdatedAt }>
<span>Gas: <GasPrice data={ statsMock.withoutFiatPrices.gas_prices?.average as GasPriceInfo }/></span>
</GasInfoTooltip>,
);
// await page.getByText(/gas/i).hover();
await page.getByText(/gas/i).hover();
await page.getByText(/last update/i).isVisible();
await expect(page).toHaveScreenshot();
});
test('without data', async({ render, page }) => {
await render(
<GasInfoTooltip data={ statsMock.withoutGweiPrices } dataUpdatedAt={ dataUpdatedAt } isOpen>
<GasInfoTooltip data={ statsMock.withoutGweiPrices } dataUpdatedAt={ dataUpdatedAt }>
<span>Gas: <GasPrice data={ statsMock.withoutGweiPrices.gas_prices?.average as GasPriceInfo }/></span>
</GasInfoTooltip>,
);
// await page.getByText(/gas/i).hover();
await page.getByText(/gas/i).hover();
await page.getByText(/last update/i).isVisible();
await expect(page).toHaveScreenshot();
});
......
......@@ -23,13 +23,12 @@ interface Props {
children: React.ReactNode;
data: HomeStats;
dataUpdatedAt: number;
isOpen?: boolean; // for testing purposes only; the tests were flaky, i couldn't find a better way
placement?: ExcludeUndefined<TooltipProps['positioning']>['placement'];
}
const feature = config.features.gasTracker;
const GasInfoTooltip = ({ children, data, dataUpdatedAt, isOpen, placement }: Props) => {
const GasInfoTooltip = ({ children, data, dataUpdatedAt, placement }: Props) => {
if (!data.gas_prices) {
return null;
}
......@@ -67,7 +66,6 @@ const GasInfoTooltip = ({ children, data, dataUpdatedAt, isOpen, placement }: Pr
<Tooltip
content={ content }
positioning={{ placement }}
{ ...(isOpen ? { open: true } : { }) }
lazyMount
interactive
showArrow={ false }
......
import { Box, chakra } from '@chakra-ui/react';
import React from 'react';
import { useColorModeValue } from 'toolkit/chakra/color-mode';
interface Props {
children: React.ReactNode;
className?: string;
}
const Container = ({ children, className }: Props) => {
const bgColor = useColorModeValue('white', 'black');
return (
<Box
className={ className }
minWidth={{ base: '100vw', lg: 'fit-content' }}
m="0 auto"
bgColor={ bgColor }
bgColor={{ _light: 'white', _dark: 'black' }}
>
{ children }
</Box>
......
......@@ -96,7 +96,7 @@ test.describe('image', () => {
image_url: null,
} as TokenInstance;
const component = await render(<NftMedia data={ data } w="250px"/>);
await component.getByAltText('Token instance image').hover();
await component.getByRole('img', { name: 'Token instance image' }).hover();
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 250, height: 250 } });
});
......@@ -106,7 +106,7 @@ test.describe('image', () => {
image_url: null,
} as TokenInstance;
const component = await render(<NftMedia data={ data } withFullscreen w="250px"/>);
await component.getByAltText('Token instance image').click();
await component.getByRole('img', { name: 'Token instance image' }).click();
await expect(page).toHaveScreenshot();
});
});
......
......@@ -56,7 +56,7 @@ const AuthModalScreenSuccessWallet = ({ address, onAddEmail, onClose, isAuth, pr
Add your email to receive exclusive updates about Blockscout { config.features.rewards.isEnabled ? 'Merits ' : ' ' }
and notifications about addresses in your watch list.
</Text>
<Flex mt={ 6 } gap={ 2 }>
<Flex mt={ 6 } gap={ 6 }>
<Button onClick={ handleAddEmailClick }>Add email</Button>
<Button variant="link" onClick={ onClose }>I{ apos }ll do it later</Button>
</Flex>
......
......@@ -31,10 +31,10 @@ test.beforeEach(async({ mockEnvs, mockConfigResponse, mockAssetResponse }) => {
test('base view', async({ render, page }) => {
const component = await render(<Burger/>, { hooksConfig });
await component.locator('div[aria-label="Menu button"]').click();
await expect(page.locator('.chakra-modal__content-container')).toHaveScreenshot();
await component.getByRole('button', { name: 'Menu button' }).click();
await expect(page).toHaveScreenshot();
await page.locator('button[aria-label="Network menu"]').click();
await page.getByRole('button', { name: 'Network menu' }).click();
await expect(page).toHaveScreenshot();
});
......@@ -44,10 +44,10 @@ test.describe('dark mode', () => {
test('base view', async({ render, page }) => {
const component = await render(<Burger/>, { hooksConfig });
await component.locator('div[aria-label="Menu button"]').click();
await component.getByRole('button', { name: 'Menu button' }).click();
await expect(page).toHaveScreenshot();
await page.locator('button[aria-label="Network menu"]').click();
await page.getByRole('button', { name: 'Network menu' }).click();
await expect(page).toHaveScreenshot();
});
});
......@@ -55,7 +55,7 @@ test.describe('dark mode', () => {
test('submenu', async({ render, page }) => {
const component = await render(<Burger/>, { hooksConfig });
await component.locator('div[aria-label="Menu button"]').click();
await component.getByRole('button', { name: 'Menu button' }).click();
await page.locator('div[aria-label="Blockchain link group"]').click();
await expect(page).toHaveScreenshot();
});
......@@ -70,7 +70,7 @@ authTest.describe('auth', () => {
authTest('base view', async({ render, page }) => {
const component = await render(<Burger/>, { hooksConfig });
await component.locator('div[aria-label="Menu button"]').click();
await component.getByRole('button', { name: 'Menu button' }).click();
await expect(page).toHaveScreenshot();
});
});
......@@ -38,13 +38,12 @@ const Burger = ({ isMarketplaceAppPage }: Props) => {
>
<DrawerBackdrop/>
<DrawerTrigger>
<IconButton onClick={ onOpen } p={ 2 }>
<IconButton onClick={ onOpen } p={ 2 } aria-label="Menu button">
<IconSvg
name="burger"
boxSize={ 6 }
display="block"
color={{ _light: 'gray.600', _dark: 'white' }}
aria-label="Menu button"
/>
</IconButton>
</DrawerTrigger>
......
......@@ -72,7 +72,7 @@ const IndexingBlocksAlert = () => {
}
return (
<Alert status="info" py={ 3 } borderRadius="md">
<Alert status="info" py={ 3 } borderRadius="md" showIcon>
{ `${ data.indexed_blocks_ratio && `${ Math.floor(Number(data.indexed_blocks_ratio) * 100) }% Blocks Indexed${ nbsp }${ ndash } ` }
We're indexing this chain right now. Some of the counts may be inaccurate.` }
</Alert>
......
......@@ -99,7 +99,7 @@ test.describe('with tooltips', () => {
);
await component.locator('header').hover();
await page.locator('div[aria-label="Expand/Collapse menu"]').click();
await page.locator('svg[aria-label="Expand/Collapse menu"]').click();
await page.locator('a[aria-label="DApps link"]').hover();
await expect(component).toHaveScreenshot();
......@@ -133,7 +133,7 @@ test.describe('with submenu', () => {
});
});
const noSideBarCookieTest = test.extend({
const noSideBarCookieTest = test.extend<{ context: BrowserContext }>({
context: ({ context }, use) => {
context.addCookies([ { name: cookies.NAMES.NAV_BAR_COLLAPSED, value: 'false', domain: config.app.host, path: '/' } ]);
use(context);
......@@ -168,7 +168,7 @@ noSideBarCookieTest.describe('cookie set to false', () => {
});
});
const sideBarCookieTest = test.extend({
const sideBarCookieTest = test.extend<{ context: BrowserContext }>({
context: ({ context }, use) => {
context.addCookies([ { name: cookies.NAMES.NAV_BAR_COLLAPSED, value: 'true', domain: config.app.host, path: '/' } ]);
use(context);
......
......@@ -28,7 +28,7 @@ const LogoFallback = ({ isCollapsed, isSmall }: { isCollapsed?: boolean; isSmall
return (
<IconSvg
name={ isSmall ? 'networks/icon-placeholder' : 'networks/logo-placeholder' }
width="auto"
width={ isSmall ? '30px' : '120px' }
height="100%"
color={{ base: 'blue.600', _dark: 'white' }}
display={ display }
......@@ -63,7 +63,7 @@ const NetworkLogo = ({ isCollapsed, onClick, className }: Props) => {
alt={ `${ config.chain.name } network logo` }
fallback={ <LogoFallback isCollapsed={ isCollapsed }/> }
display={{ base: 'block', lg: isCollapsed === false ? 'block' : 'none', xl: isCollapsed ? 'none' : 'block' }}
filter={{ _dark: INVERT_FILTER }}
filter={{ _dark: !config.UI.navigation.logo.dark ? INVERT_FILTER : undefined }}
objectFit="contain"
objectPosition="left"
/>
......@@ -75,7 +75,7 @@ const NetworkLogo = ({ isCollapsed, onClick, className }: Props) => {
alt={ `${ config.chain.name } network logo` }
fallback={ <LogoFallback isCollapsed={ isCollapsed } isSmall/> }
display={{ base: 'none', lg: isCollapsed === false ? 'none' : 'block', xl: isCollapsed ? 'block' : 'none' }}
filter={{ _dark: INVERT_FILTER }}
filter={{ _dark: !config.UI.navigation.icon.dark ? INVERT_FILTER : undefined }}
objectFit="contain"
objectPosition="left"
/>
......
......@@ -16,6 +16,6 @@ test('base view', async({ page, render, mockEnvs, mockAssetResponse }) => {
const popover = page.getByText('Solana transactions');
await expect(popover).toBeVisible();
await expect(page.getByText('1uwpB95K9ae8yrpxxVXJ27ivvHXqrmy82jsamgNtd...3LW8')).toBeVisible();
await expect(page.getByText('2uwpB95K9ae8yrpxxVXJ27ivvHXqrmy82jsamgNt...3LW8')).toBeVisible();
await expect(page.getByText('2uwpB95K9ae8yrpxxVXJ27ivvHXqrmy82jsamgNtd...3LW8')).toBeVisible();
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 500, height: 300 } });
});
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