Commit 6bfc4955 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Playwright tests refactoring, pt.2 (#1787)

* create storageState fixture

* remove auth fixture

* renaming

* migrate bridge tokens and shibarium rollup tests

* migrate to common app config

* update screenshots

* re-implement fixtures for mocking envs, features and auth state

* update screenshot
parent d1f7e165
......@@ -6,6 +6,7 @@ import { WagmiProvider } from 'wagmi';
import type { Props as PageProps } from 'nextjs/getServerSideProps';
import config from 'configs/app';
import { AppContextProvider } from 'lib/contexts/app';
import { SocketProvider } from 'lib/socket/context';
import wagmiConfig from 'lib/web3/wagmiConfig';
......@@ -43,7 +44,7 @@ const TestApp = ({ children, withSocket, appContext = defaultAppContext }: Props
return (
<ChakraProvider theme={ theme }>
<QueryClientProvider client={ queryClient }>
<SocketProvider url={ withSocket ? `ws://${ app.domain }:${ app.socketPort }` : undefined }>
<SocketProvider url={ withSocket ? `ws://${ config.app.host }:${ app.socketPort }` : undefined }>
<AppContextProvider { ...appContext }>
<GrowthBookProvider>
<WagmiProvider config={ wagmiConfig! }>
......
import type { BrowserContext } from '@playwright/test';
import type { BrowserContext, TestFixture } from '@playwright/test';
import config from 'configs/app';
import * as cookies from 'lib/cookies';
import { domain } from 'playwright/utils/app';
export default function authFixture(context: BrowserContext) {
context.addCookies([ { name: cookies.NAMES.API_TOKEN, value: 'foo', domain, path: '/' } ]);
export function authenticateUser(context: BrowserContext) {
context.addCookies([ { name: cookies.NAMES.API_TOKEN, value: 'foo', domain: config.app.host, path: '/' } ]);
}
export const contextWithAuth: TestFixture<BrowserContext, { context: BrowserContext }> = async({ context }, use) => {
authenticateUser(context);
use(context);
};
......@@ -7,7 +7,13 @@ interface Env {
value: string;
}
// keep in mind that all passed variables here should be present in env config files (.env.pw or .env.poa)
/**
* @deprecated please use mockEnvs fixture
*
* @export
* @param {Array<Env>} envs
* @return {*} {Parameters<typeof test.extend>[0]['context']}
*/
export default function contextWithEnvsFixture(envs: Array<Env>): Parameters<typeof test.extend>[0]['context'] {
return async({ browser }, use) => {
const context = await createContextWithStorage(browser, envs);
......
......@@ -7,6 +7,13 @@ interface Feature {
value: unknown;
}
/**
* @deprecated please use mockFeatures fixture
*
* @export
* @param {Array<Feature>} envs
* @return {*} {Parameters<typeof test.extend>[0]['context']}
*/
export default function contextWithFeaturesFixture(envs: Array<Feature>): Parameters<typeof test.extend>[0]['context'] {
return async({ browser }, use) => {
const storageItems = envs.map(({ id, value }) => ({ name: `pw_feature:${ id }`, value: JSON.stringify(value) }));
......
import type { Browser } from '@playwright/test';
import * as app from 'playwright/utils/app';
import config from 'configs/app';
/**
* @deprecated please use mockEnvs or mockFeatures fixture
*
* @export
* @param {Browser} browser
* @param {Array<{ name: string; value: string }>} localStorage
* @return {*}
*/
export default async function createContextWithEnvs(browser: Browser, localStorage: Array<{ name: string; value: string }>) {
return browser.newContext({
storageState: {
origins: [
{ origin: app.url, localStorage },
{ origin: config.app.baseUrl, localStorage },
],
cookies: [],
},
......
import type { TestFixture, Page } from '@playwright/test';
import type { WalletProvider } from 'types/web3';
export type InjectMetaMaskProvider = () => Promise<void>;
const fixture: TestFixture<InjectMetaMaskProvider, { page: Page }> = async({ page }, use) => {
await use(async() => {
await page.evaluate(() => {
window.ethereum = {
isMetaMask: true,
_events: {},
} as WalletProvider;
});
});
};
export default fixture;
import type { TestFixture, Page } from '@playwright/test';
import config from 'configs/app';
import { buildExternalAssetFilePath } from 'configs/app/utils';
export type MockConfigResponseFixture = (envName: string, envValue: string, content: string, isImage?: boolean) => Promise<void>;
const fixture: TestFixture<MockConfigResponseFixture, { page: Page }> = async({ page }, use) => {
await use(async(envName, envValue, content, isImage) => {
const url = config.app.baseUrl + buildExternalAssetFilePath(envName, envValue);
if (isImage) {
await page.route(url, (route) => route.fulfill({
status: 200,
path: content,
}));
} else {
await page.route(url, (route) => route.fulfill({
status: 200,
body: content,
}));
}
});
};
export default fixture;
/* eslint-disable max-len */
import type { TestFixture, Page } from '@playwright/test';
export type MockEnvsFixture = (envs: Array<[string, string]>) => Promise<void>;
const fixture: TestFixture<MockEnvsFixture, { page: Page }> = async({ page }, use) => {
await use(async(envs) => {
for (const [ name, value ] of envs) {
await page.evaluate(({ name, value }) => {
window.localStorage.setItem(name, value);
}, { name, value });
}
});
};
export default fixture;
export const ENVS_MAP: Record<string, Array<[string, string]>> = {
shibariumRollup: [
[ 'NEXT_PUBLIC_ROLLUP_TYPE', 'shibarium' ],
[ 'NEXT_PUBLIC_ROLLUP_L1_BASE_URL', 'https://localhost:3101' ],
],
bridgedTokens: [
[ 'NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS', '[{"id":"1","title":"Ethereum","short_title":"ETH","base_url":"https://eth.blockscout.com/token/"},{"id":"56","title":"Binance Smart Chain","short_title":"BSC","base_url":"https://bscscan.com/token/"},{"id":"99","title":"POA","short_title":"POA","base_url":"https://blockscout.com/poa/core/token/"}]' ],
[ 'NEXT_PUBLIC_BRIDGED_TOKENS_BRIDGES', '[{"type":"omni","title":"OmniBridge","short_title":"OMNI"},{"type":"amb","title":"Arbitrary Message Bridge","short_title":"AMB"}]' ],
],
userOps: [
[ 'NEXT_PUBLIC_HAS_USER_OPS', 'true' ],
],
};
/* eslint-disable max-len */
import type { TestFixture, Page } from '@playwright/test';
export type MockFeaturesFixture = (features: Array<[string, unknown]>) => Promise<void>;
const fixture: TestFixture<MockFeaturesFixture, { page: Page }> = async({ page }, use) => {
await use(async(features) => {
for (const [ name, value ] of features) {
await page.evaluate(({ name, value }) => {
window.localStorage.setItem(`pw_feature:${ name }`, JSON.stringify(value));
}, { name, value });
}
});
};
export default fixture;
......@@ -3,27 +3,35 @@ import { test as base } from '@playwright/experimental-ct-react';
import * as textAdMock from 'mocks/ad/textAd';
import type { MockApiResponseFixture } from './fixtures/mockApiResponse';
import mockApiResponseFixture from './fixtures/mockApiResponse';
import type { MockAssetResponseFixture } from './fixtures/mockAssetResponse';
import mockAssetResponseFixture from './fixtures/mockAssetResponse';
import type { RenderFixture } from './fixtures/render';
import renderFixture from './fixtures/render';
import type { CreateSocketFixture } from './fixtures/socketServer';
import { createSocket as createSocketFixture } from './fixtures/socketServer';
import * as injectMetaMaskProvider from './fixtures/injectMetaMaskProvider';
import * as mockApiResponse from './fixtures/mockApiResponse';
import * as mockAssetResponse from './fixtures/mockAssetResponse';
import * as mockConfigResponse from './fixtures/mockConfigResponse';
import * as mockEnvs from './fixtures/mockEnvs';
import * as mockFeatures from './fixtures/mockFeatures';
import * as render from './fixtures/render';
import * as socketServer from './fixtures/socketServer';
interface Fixtures {
render: RenderFixture;
mockApiResponse: MockApiResponseFixture;
mockAssetResponse: MockAssetResponseFixture;
createSocket: CreateSocketFixture;
render: render.RenderFixture;
mockApiResponse: mockApiResponse.MockApiResponseFixture;
mockAssetResponse: mockAssetResponse.MockAssetResponseFixture;
mockConfigResponse: mockConfigResponse.MockConfigResponseFixture;
mockEnvs: mockEnvs.MockEnvsFixture;
mockFeatures: mockFeatures.MockFeaturesFixture;
createSocket: socketServer.CreateSocketFixture;
injectMetaMaskProvider: injectMetaMaskProvider.InjectMetaMaskProvider;
}
const test = base.extend<Fixtures>({
render: renderFixture,
mockApiResponse: mockApiResponseFixture,
mockAssetResponse: mockAssetResponseFixture,
createSocket: createSocketFixture,
render: render.default,
mockApiResponse: mockApiResponse.default,
mockAssetResponse: mockAssetResponse.default,
mockConfigResponse: mockConfigResponse.default,
mockEnvs: mockEnvs.default,
mockFeatures: mockFeatures.default,
createSocket: socketServer.createSocket,
injectMetaMaskProvider: injectMetaMaskProvider.default,
});
test.beforeEach(async({ page }) => {
......
This diff is collapsed.
export const url = `${ process.env.NEXT_PUBLIC_APP_PROTOCOL }://${ process.env.NEXT_PUBLIC_APP_HOST }:${ process.env.NEXT_PUBLIC_APP_PORT }`;
export const domain = process.env.NEXT_PUBLIC_APP_HOST;
export const socketPort = 3200;
......@@ -4,8 +4,6 @@ import config from 'configs/app';
import type { ResourceName, ResourcePathParams } from 'lib/api/resources';
import { RESOURCES } from 'lib/api/resources';
// DEPRECATED
/**
* @deprecated please use fixture mockApiResponse from playwright/lib.tsx for rendering test suite
*
......
......@@ -20,20 +20,6 @@ export const featureEnvs = {
{ name: 'NEXT_PUBLIC_ROLLUP_L1_BASE_URL', value: 'https://localhost:3101' },
{ name: 'NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL', value: 'https://localhost:3102' },
],
shibariumRollup: [
{ name: 'NEXT_PUBLIC_ROLLUP_TYPE', value: 'shibarium' },
{ name: 'NEXT_PUBLIC_ROLLUP_L1_BASE_URL', value: 'https://localhost:3101' },
],
bridgedTokens: [
{
name: 'NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS',
value: '[{"id":"1","title":"Ethereum","short_title":"ETH","base_url":"https://eth.blockscout.com/token/"},{"id":"56","title":"Binance Smart Chain","short_title":"BSC","base_url":"https://bscscan.com/token/"},{"id":"99","title":"POA","short_title":"POA","base_url":"https://blockscout.com/poa/core/token/"}]',
},
{
name: 'NEXT_PUBLIC_BRIDGED_TOKENS_BRIDGES',
value: '[{"type":"omni","title":"OmniBridge","short_title":"OMNI"},{"type":"amb","title":"Arbitrary Message Bridge","short_title":"AMB"}]',
},
],
txInterpretation: [
{ name: 'NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER', value: 'blockscout' },
],
......
......@@ -8,7 +8,7 @@ export type TokensResponse = {
items_count: number;
name: string;
market_cap: string | null;
};
} | null;
}
export type TokensFilters = { q: string; type: Array<TokenType> | undefined };
......
import { test as base, devices, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import { apps as appsMock } from 'mocks/apps/apps';
import { securityReports as securityReportsMock } from 'mocks/apps/securityReports';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp';
import * as app from 'playwright/utils/app';
import { test, expect, devices } from 'playwright/lib';
import Marketplace from './Marketplace';
const MARKETPLACE_CONFIG_URL = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', 'https://marketplace-config.json') || '';
const MARKETPLACE_SECURITY_REPORTS_URL =
app.url + buildExternalAssetFilePath('NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL', 'https://marketplace-security-reports.json') || '';
const MARKETPLACE_BANNER_CONTENT_URL =
app.url + buildExternalAssetFilePath('NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL', 'https://marketplace-banner.html') || '';
const MARKETPLACE_BANNER_LINK_URL = 'https://example.com';
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', value: MARKETPLACE_CONFIG_URL },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
const MARKETPLACE_CONFIG_URL = 'http://localhost/marketplace-config.json';
test.beforeEach(async({ mockConfigResponse, mockEnvs, mockAssetResponse }) => {
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 Promise.all(appsMock.map(app => mockAssetResponse(app.logo, './playwright/mocks/image_s.jpg')));
});
const testFn: Parameters<typeof test>[1] = async({ mount, page }) => {
await page.route(MARKETPLACE_CONFIG_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(appsMock),
}));
await Promise.all(appsMock.map(app =>
page.route(app.logo, (route) =>
route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
}),
),
));
await page.route(MARKETPLACE_BANNER_CONTENT_URL, (route) => route.fulfill({
status: 200,
path: './playwright/mocks/banner.html',
}));
const component = await mount(
<TestApp>
<Marketplace/>
</TestApp>,
);
test('base view +@dark-mode', async({ render }) => {
const component = await render(<Marketplace/>);
await expect(component).toHaveScreenshot();
};
test('base view +@dark-mode', testFn);
const testWithFeaturedApp = test.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', value: MARKETPLACE_CONFIG_URL },
{ name: 'NEXT_PUBLIC_MARKETPLACE_FEATURED_APP', value: 'hop-exchange' },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
});
testWithFeaturedApp('with featured app +@dark-mode', testFn);
test('with featured app +@dark-mode', async({ render, mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_MARKETPLACE_FEATURED_APP', 'hop-exchange' ],
]);
const component = await render(<Marketplace/>);
const testWithBanner = test.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', value: MARKETPLACE_CONFIG_URL },
{ name: 'NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL', value: MARKETPLACE_BANNER_CONTENT_URL },
{ name: 'NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL', value: MARKETPLACE_BANNER_LINK_URL },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
await expect(component).toHaveScreenshot();
});
testWithBanner('with banner +@dark-mode', testFn);
test('with banner +@dark-mode', async({ render, mockEnvs, mockConfigResponse }) => {
const MARKETPLACE_BANNER_CONTENT_URL = 'https://localhost/marketplace-banner.html';
const MARKETPLACE_BANNER_LINK_URL = 'https://example.com';
const testWithScoreFeature = test.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', value: MARKETPLACE_CONFIG_URL },
{ name: 'NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL', value: MARKETPLACE_SECURITY_REPORTS_URL },
{ name: 'pw_feature:security_score_exp', value: 'true' },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
});
await mockEnvs([
[ 'NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL', MARKETPLACE_BANNER_CONTENT_URL ],
[ 'NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL', MARKETPLACE_BANNER_LINK_URL ],
]);
await mockConfigResponse('MARKETPLACE_BANNER_CONTENT_URL', MARKETPLACE_BANNER_CONTENT_URL, './playwright/mocks/page.html', true);
const component = await render(<Marketplace/>);
testWithScoreFeature('with scores +@dark-mode', async({ mount, page }) => {
await page.route(MARKETPLACE_CONFIG_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(appsMock),
}));
await page.route(MARKETPLACE_SECURITY_REPORTS_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(securityReportsMock),
}));
await Promise.all(appsMock.map(app =>
page.route(app.logo, (route) =>
route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
}),
),
));
const component = await mount(
<TestApp>
<Marketplace/>
</TestApp>,
);
await expect(component).toHaveScreenshot();
});
test('with scores +@dark-mode', async({ render, mockConfigResponse, mockEnvs, mockFeatures }) => {
const MARKETPLACE_SECURITY_REPORTS_URL = 'https://marketplace-security-reports.json';
await mockEnvs([
[ 'NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL', MARKETPLACE_SECURITY_REPORTS_URL ],
]);
await mockFeatures([
[ 'security_score_exp', true ],
]);
await mockConfigResponse('NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL', MARKETPLACE_SECURITY_REPORTS_URL, JSON.stringify(securityReportsMock));
const component = await render(<Marketplace/>);
await component.getByText('Apps scores').click();
await expect(component).toHaveScreenshot();
......@@ -121,36 +66,45 @@ testWithScoreFeature('with scores +@dark-mode', async({ mount, page }) => {
test.describe('mobile', () => {
test.use({ viewport: devices['iPhone 13 Pro'].viewport });
test('base view', testFn);
testWithFeaturedApp('with featured app', testFn);
testWithBanner('with banner', testFn);
testWithScoreFeature('with scores', async({ mount, page }) => {
await page.route(MARKETPLACE_CONFIG_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(appsMock),
}));
await page.route(MARKETPLACE_SECURITY_REPORTS_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(securityReportsMock),
}));
await Promise.all(appsMock.map(app =>
page.route(app.logo, (route) =>
route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
}),
),
));
const component = await mount(
<TestApp>
<Marketplace/>
</TestApp>,
);
test('base view', async({ render }) => {
const component = await render(<Marketplace/>);
await expect(component).toHaveScreenshot();
});
test('with featured app', async({ render, mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_MARKETPLACE_FEATURED_APP', 'hop-exchange' ],
]);
const component = await render(<Marketplace/>);
await expect(component).toHaveScreenshot();
});
test('with banner', async({ render, mockEnvs, mockConfigResponse }) => {
const MARKETPLACE_BANNER_CONTENT_URL = 'https://localhost/marketplace-banner.html';
const MARKETPLACE_BANNER_LINK_URL = 'https://example.com';
await mockEnvs([
[ 'NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL', MARKETPLACE_BANNER_CONTENT_URL ],
[ 'NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL', MARKETPLACE_BANNER_LINK_URL ],
]);
await mockConfigResponse('MARKETPLACE_BANNER_CONTENT_URL', MARKETPLACE_BANNER_CONTENT_URL, './playwright/mocks/page.html', true);
const component = await render(<Marketplace/>);
await expect(component).toHaveScreenshot();
});
test('with scores', async({ render, mockConfigResponse, mockEnvs, mockFeatures }) => {
const MARKETPLACE_SECURITY_REPORTS_URL = 'https://marketplace-security-reports.json';
await mockEnvs([
[ 'NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL', MARKETPLACE_SECURITY_REPORTS_URL ],
]);
await mockFeatures([
[ 'security_score_exp', true ],
]);
await mockConfigResponse('NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL', MARKETPLACE_SECURITY_REPORTS_URL, JSON.stringify(securityReportsMock));
const component = await render(<Marketplace/>);
await component.getByText('Apps scores').click();
await expect(component).toHaveScreenshot();
......
import { Flex } from '@chakra-ui/react';
import { test as base, expect, devices } from '@playwright/experimental-ct-react';
import React from 'react';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import { apps as appsMock } from 'mocks/apps/apps';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp';
import * as app from 'playwright/utils/app';
import { test, expect, devices } from 'playwright/lib';
import MarketplaceApp from './MarketplaceApp';
const MARKETPLACE_CONFIG_URL = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', 'https://marketplace-config.json') || '';
const hooksConfig = {
router: {
query: { id: appsMock[0].id },
......@@ -19,39 +13,26 @@ const hooksConfig = {
},
};
const testFn: Parameters<typeof test>[1] = async({ mount, page }) => {
await page.route(MARKETPLACE_CONFIG_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(appsMock),
}));
await page.route(appsMock[0].url, (route) =>
route.fulfill({
status: 200,
path: './mocks/apps/app.html',
}),
);
const MARKETPLACE_CONFIG_URL = 'https://marketplace-config.json';
const testFn: Parameters<typeof test>[1] = async({ render, mockConfigResponse, mockAssetResponse, mockEnvs }) => {
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');
const component = await mount(
<TestApp>
{ /* added Flex as a Layout because the iframe has negative margins */ }
const component = await render(
<Flex flexDirection="column" mx={{ base: 4, lg: 6 }} h="100vh">
<MarketplaceApp/>
</Flex>
</TestApp>,
</Flex>,
{ hooksConfig },
);
await expect(component).toHaveScreenshot();
};
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', value: MARKETPLACE_CONFIG_URL },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
});
test('base view +@dark-mode', testFn);
test.describe('mobile', () => {
......
This diff is collapsed.
import { test as base, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import { data as depositsData } from 'mocks/shibarium/deposits';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp';
import buildApiUrl from 'playwright/utils/buildApiUrl';
import * as configs from 'playwright/utils/configs';
import { ENVS_MAP } from 'playwright/fixtures/mockEnvs';
import { test, expect } from 'playwright/lib';
import ShibariumDeposits from './ShibariumDeposits';
const DEPOSITS_API_URL = buildApiUrl('shibarium_deposits');
const DEPOSITS_COUNT_API_URL = buildApiUrl('shibarium_deposits_count');
test('base view +@mobile', async({ render, mockApiResponse, mockEnvs }) => {
await mockEnvs(ENVS_MAP.shibariumRollup);
await mockApiResponse('shibarium_deposits', depositsData);
await mockApiResponse('shibarium_deposits_count', 3971111);
const test = base.extend({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context: contextWithEnvs(configs.featureEnvs.shibariumRollup) as any,
});
test('base view +@mobile', async({ mount, page }) => {
await page.route('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242', (route) => route.fulfill({
status: 200,
body: '',
}));
await page.route(DEPOSITS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(depositsData),
}));
await page.route(DEPOSITS_COUNT_API_URL, (route) => route.fulfill({
status: 200,
body: '3971111',
}));
const component = await mount(
<TestApp>
<ShibariumDeposits/>
</TestApp>,
);
const component = await render(<ShibariumDeposits/>);
await expect(component).toHaveScreenshot();
});
import { test as base, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import { data as withdrawalsData } from 'mocks/shibarium/withdrawals';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp';
import buildApiUrl from 'playwright/utils/buildApiUrl';
import * as configs from 'playwright/utils/configs';
import { ENVS_MAP } from 'playwright/fixtures/mockEnvs';
import { test, expect } from 'playwright/lib';
import ShibariuWithdrawals from './ShibariumWithdrawals';
import ShibariumWithdrawals from './ShibariumWithdrawals';
const test = base.extend({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context: contextWithEnvs(configs.featureEnvs.shibariumRollup) as any,
});
const WITHDRAWALS_API_URL = buildApiUrl('shibarium_withdrawals');
const WITHDRAWALS_COUNT_API_URL = buildApiUrl('shibarium_withdrawals_count');
test('base view +@mobile', async({ mount, page }) => {
test('base view +@mobile', async({ render, mockApiResponse, mockEnvs }) => {
// test on mobile is flaky
// my assumption is there is not enough time to calculate hashes truncation so component is unstable
// so I raised the test timeout to check if it helps
test.slow();
await page.route('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242', (route) => route.fulfill({
status: 200,
body: '',
}));
await page.route(WITHDRAWALS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(withdrawalsData),
}));
await page.route(WITHDRAWALS_COUNT_API_URL, (route) => route.fulfill({
status: 200,
body: '397',
}));
await mockEnvs(ENVS_MAP.shibariumRollup);
await mockApiResponse('shibarium_withdrawals', withdrawalsData);
await mockApiResponse('shibarium_withdrawals_count', 397);
const component = await mount(
<TestApp>
<ShibariuWithdrawals/>
</TestApp>,
);
const component = await render(<ShibariumWithdrawals/>);
await expect(component).toHaveScreenshot({ timeout: 10_000 });
});
import { test as base, expect, devices } from '@playwright/experimental-ct-react';
import React from 'react';
import * as verifiedAddressesMocks from 'mocks/account/verifiedAddresses';
import { token as contract } from 'mocks/address/address';
import { tokenInfo, tokenCounters, bridgedTokenA } from 'mocks/tokens/tokenInfo';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import { ENVS_MAP } from 'playwright/fixtures/mockEnvs';
import * as socketServer from 'playwright/fixtures/socketServer';
import TestApp from 'playwright/TestApp';
import buildApiUrl from 'playwright/utils/buildApiUrl';
import { test, expect, devices } from 'playwright/lib';
import * as configs from 'playwright/utils/configs';
import Token from './Token';
const TOKEN_API_URL = buildApiUrl('token', { hash: '1' });
const TOKEN_COUNTERS_API_URL = buildApiUrl('token_counters', { hash: '1' });
const TOKEN_TRANSFERS_API_URL = buildApiUrl('token_transfers', { hash: '1' });
const ADDRESS_API_URL = buildApiUrl('address', { hash: '1' });
const hooksConfig = {
router: {
query: { hash: '1', tab: 'token_transfers' },
......@@ -23,45 +17,19 @@ const hooksConfig = {
},
};
const test = base.extend<socketServer.SocketServerFixture>({
createSocket: socketServer.createSocket,
});
// FIXME
// test cases which use socket cannot run in parallel since the socket server always run on the same port
test.describe.configure({ mode: 'serial' });
test.beforeEach(async({ page }) => {
await page.route('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242', (route) => route.fulfill({
status: 200,
body: '',
}));
await page.route(TOKEN_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(tokenInfo),
}));
await page.route(ADDRESS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(contract),
}));
await page.route(TOKEN_COUNTERS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(tokenCounters),
}));
await page.route(TOKEN_TRANSFERS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify({}),
}));
test.beforeEach(async({ mockApiResponse }) => {
await mockApiResponse('token', tokenInfo, { pathParams: { hash: '1' } });
await mockApiResponse('address', contract, { pathParams: { hash: '1' } });
await mockApiResponse('token_counters', tokenCounters, { pathParams: { hash: '1' } });
await mockApiResponse('token_transfers', { items: [], next_page_params: null }, { pathParams: { hash: '1' } });
});
test('base view', async({ mount, page, createSocket }) => {
const component = await mount(
<TestApp withSocket>
<Token/>
</TestApp>,
{ hooksConfig },
);
test('base view', async({ render, page, createSocket }) => {
const component = await render(<Token/>, { hooksConfig }, { withSocket: true });
const socket = await createSocket();
const channel = await socketServer.joinChannel(socket, 'tokens:1');
......@@ -73,24 +41,11 @@ test('base view', async({ mount, page, createSocket }) => {
});
});
test('with verified info', async({ mount, page, createSocket }) => {
const VERIFIED_INFO_URL = buildApiUrl('token_verified_info', { chainId: '1', hash: '1' });
await page.route(VERIFIED_INFO_URL, (route) => route.fulfill({
body: JSON.stringify(verifiedAddressesMocks.TOKEN_INFO_APPLICATION.APPROVED),
}));
await page.route(tokenInfo.icon_url as string, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
});
});
test('with verified info', async({ render, page, createSocket, mockApiResponse, mockAssetResponse }) => {
await mockApiResponse('token_verified_info', verifiedAddressesMocks.TOKEN_INFO_APPLICATION.APPROVED, { pathParams: { chainId: '1', hash: '1' } });
await mockAssetResponse(tokenInfo.icon_url as string, './playwright/mocks/image_s.jpg');
const component = await mount(
<TestApp withSocket>
<Token/>
</TestApp>,
{ hooksConfig },
);
const component = await render(<Token/>, { hooksConfig }, { withSocket: true });
const socket = await createSocket();
const channel = await socketServer.joinChannel(socket, 'tokens:1');
......@@ -104,55 +59,16 @@ test('with verified info', async({ mount, page, createSocket }) => {
});
});
const bridgedTokenTest = base.extend<socketServer.SocketServerFixture>({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context: contextWithEnvs(configs.featureEnvs.bridgedTokens) as any,
createSocket: socketServer.createSocket,
});
bridgedTokenTest('bridged token', async({ mount, page, createSocket }) => {
const VERIFIED_INFO_URL = buildApiUrl('token_verified_info', { chainId: '1', hash: '1' });
await page.route('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242', (route) => route.fulfill({
status: 200,
body: '',
}));
await page.route(TOKEN_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(bridgedTokenA),
}));
await page.route(ADDRESS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(contract),
}));
await page.route(TOKEN_COUNTERS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(tokenCounters),
}));
await page.route(TOKEN_TRANSFERS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify({}),
}));
await page.route(VERIFIED_INFO_URL, (route) => route.fulfill({
body: JSON.stringify(verifiedAddressesMocks.TOKEN_INFO_APPLICATION.APPROVED),
}));
await page.route(tokenInfo.icon_url as string, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
});
});
const component = await mount(
<TestApp withSocket>
<Token/>
</TestApp>,
{ hooksConfig },
);
test('bridged token', async({ render, page, createSocket, mockApiResponse, mockAssetResponse, mockEnvs }) => {
await mockEnvs(ENVS_MAP.bridgedTokens);
await mockApiResponse('token', bridgedTokenA, { pathParams: { hash: '1' } });
await mockApiResponse('address', contract, { pathParams: { hash: '1' } });
await mockApiResponse('token_counters', tokenCounters, { pathParams: { hash: '1' } });
await mockApiResponse('token_transfers', { items: [], next_page_params: null }, { pathParams: { hash: '1' } });
await mockApiResponse('token_verified_info', verifiedAddressesMocks.TOKEN_INFO_APPLICATION.APPROVED, { pathParams: { chainId: '1', hash: '1' } });
await mockAssetResponse(tokenInfo.icon_url as string, './playwright/mocks/image_s.jpg');
const component = await render(<Token/>, { hooksConfig }, { withSocket: true });
const socket = await createSocket();
const channel = await socketServer.joinChannel(socket, 'tokens:1');
socketServer.sendMessage(socket, channel, 'total_supply', { total_supply: 10 ** 20 });
......@@ -165,14 +81,9 @@ bridgedTokenTest('bridged token', async({ mount, page, createSocket }) => {
test.describe('mobile', () => {
test.use({ viewport: devices['iPhone 13 Pro'].viewport });
test('base view', async({ mount, page, createSocket }) => {
const component = await mount(
<TestApp withSocket>
<Token/>
</TestApp>,
{ hooksConfig },
);
test('base view', async({ render, page, createSocket }) => {
const component = await render(<Token/>, { hooksConfig }, { withSocket: true });
const socket = await createSocket();
const channel = await socketServer.joinChannel(socket, 'tokens:1');
socketServer.sendMessage(socket, channel, 'total_supply', { total_supply: 10 ** 20 });
......@@ -183,25 +94,11 @@ test.describe('mobile', () => {
});
});
test('with verified info', async({ mount, page, createSocket }) => {
const VERIFIED_INFO_URL = buildApiUrl('token_verified_info', { chainId: '1', hash: '1' });
await page.route(VERIFIED_INFO_URL, (route) => route.fulfill({
body: JSON.stringify(verifiedAddressesMocks.TOKEN_INFO_APPLICATION.APPROVED),
}));
await page.route(tokenInfo.icon_url as string, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
});
});
const component = await mount(
<TestApp withSocket>
<Token/>
</TestApp>,
{ hooksConfig },
);
test('with verified info', async({ render, page, createSocket, mockApiResponse, mockAssetResponse }) => {
await mockApiResponse('token_verified_info', verifiedAddressesMocks.TOKEN_INFO_APPLICATION.APPROVED, { pathParams: { chainId: '1', hash: '1' } });
await mockAssetResponse(tokenInfo.icon_url as string, './playwright/mocks/image_s.jpg');
const component = await render(<Token/>, { hooksConfig }, { withSocket: true });
const socket = await createSocket();
const channel = await socketServer.joinChannel(socket, 'tokens:1');
socketServer.sendMessage(socket, channel, 'total_supply', { total_supply: 10 ** 20 });
......
import { Box } from '@chakra-ui/react';
import { test as base, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import * as textAdMock from 'mocks/ad/textAd';
import * as tokens from 'mocks/tokens/tokenInfo';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp';
import buildApiUrl from 'playwright/utils/buildApiUrl';
import * as configs from 'playwright/utils/configs';
import { ENVS_MAP } from 'playwright/fixtures/mockEnvs';
import { test, expect } from 'playwright/lib';
import Tokens from './Tokens';
base.beforeEach(async({ page }) => {
await page.route('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242', (route) => route.fulfill({
status: 200,
body: JSON.stringify(textAdMock.duck),
}));
await page.route(textAdMock.duck.ad.thumbnail, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
});
});
});
base('base view +@mobile +@dark-mode', async({ mount, page }) => {
test('base view +@mobile +@dark-mode', async({ render, mockApiResponse }) => {
const allTokens = {
items: [
tokens.tokenInfoERC20a, tokens.tokenInfoERC20b, tokens.tokenInfoERC20c, tokens.tokenInfoERC20d,
......@@ -35,6 +18,7 @@ base('base view +@mobile +@dark-mode', async({ mount, page }) => {
holder_count: 1,
items_count: 1,
name: 'a',
market_cap: '0',
},
};
const filteredTokens = {
......@@ -44,40 +28,25 @@ base('base view +@mobile +@dark-mode', async({ mount, page }) => {
next_page_params: null,
};
const ALL_TOKENS_API_URL = buildApiUrl('tokens');
const FILTERED_TOKENS_API_URL = buildApiUrl('tokens') + '?q=foo';
await page.route(ALL_TOKENS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(allTokens),
}));
await mockApiResponse('tokens', allTokens);
await mockApiResponse('tokens', filteredTokens, { queryParams: { q: 'foo' } });
await page.route(FILTERED_TOKENS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(filteredTokens),
}));
const component = await mount(
<TestApp>
const component = await render(
<div>
<Box h={{ base: '134px', lg: 6 }}/>
<Tokens/>
</TestApp>,
</div>,
);
await expect(component).toHaveScreenshot();
await component.getByRole('textbox', { name: 'Token name or symbol' }).focus();
await component.getByRole('textbox', { name: 'Token name or symbol' }).type('foo');
await component.getByRole('textbox', { name: 'Token name or symbol' }).fill('foo');
await expect(component).toHaveScreenshot();
});
base.describe('bridged tokens', async() => {
const test = base.extend({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context: contextWithEnvs(configs.featureEnvs.bridgedTokens) as any,
});
test.describe('bridged tokens', async() => {
const bridgedTokens = {
items: [
tokens.bridgedTokenA,
......@@ -88,6 +57,7 @@ base.describe('bridged tokens', async() => {
holder_count: 1,
items_count: 1,
name: 'a',
market_cap: null,
},
};
const bridgedFilteredTokens = {
......@@ -101,26 +71,17 @@ base.describe('bridged tokens', async() => {
query: { tab: 'bridged' },
},
};
const BRIDGED_TOKENS_API_URL = buildApiUrl('tokens_bridged');
test.beforeEach(async({ page }) => {
await page.route(BRIDGED_TOKENS_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(bridgedTokens),
}));
});
test('base view', async({ mount, page }) => {
await page.route(BRIDGED_TOKENS_API_URL + '?chain_ids=99', (route) => route.fulfill({
status: 200,
body: JSON.stringify(bridgedFilteredTokens),
}));
test('base view', async({ render, page, mockApiResponse, mockEnvs }) => {
await mockEnvs(ENVS_MAP.bridgedTokens);
await mockApiResponse('tokens_bridged', bridgedTokens);
await mockApiResponse('tokens_bridged', bridgedFilteredTokens, { queryParams: { chain_ids: '99' } });
const component = await mount(
<TestApp>
const component = await render(
<div>
<Box h={{ base: '134px', lg: 6 }}/>
<Tokens/>
</TestApp>,
</div>,
{ hooksConfig },
);
......
import type { BrowserContext } from '@playwright/test';
import React from 'react';
import * as validatorsMock from 'mocks/validators/index';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import { test as base, expect } from 'playwright/lib';
import * as configs from 'playwright/utils/configs';
import { test, expect } from 'playwright/lib';
import Validators from './Validators';
const test = base.extend<{ context: BrowserContext }>({
context: contextWithEnvs(configs.featureEnvs.validators),
});
const chainType = 'stability';
test('base view +@mobile', async({ render, mockApiResponse }) => {
await mockApiResponse('validators', validatorsMock.validatorsResponse, { pathParams: { chainType: 'stability' } });
await mockApiResponse('validators_counters', validatorsMock.validatorsCountersResponse, { pathParams: { chainType: 'stability' } });
test('base view +@mobile', async({ render, mockApiResponse, mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE', chainType ],
]);
await mockApiResponse('validators', validatorsMock.validatorsResponse, { pathParams: { chainType } });
await mockApiResponse('validators_counters', validatorsMock.validatorsCountersResponse, { pathParams: { chainType } });
const component = await render(<Validators/>);
......
import type { BrowserContext } from '@playwright/test';
import React from 'react';
import * as mocks from 'mocks/account/verifiedAddresses';
import * as profileMock from 'mocks/user/profile';
import authFixture from 'playwright/fixtures/auth';
import { contextWithAuth } from 'playwright/fixtures/auth';
import { test as base, expect } from 'playwright/lib';
import VerifiedAddresses from './VerifiedAddresses';
const test = base.extend({
context: ({ context }, use) => {
authFixture(context);
use(context);
},
const test = base.extend<{ context: BrowserContext }>({
context: contextWithAuth,
});
test.beforeEach(async({ mockAssetResponse }) => {
......
import { test as base, expect } from '@playwright/experimental-ct-react';
import type { BrowserContext } from '@playwright/test';
import React from 'react';
import * as profileMock from 'mocks/user/profile';
import authFixture from 'playwright/fixtures/auth';
import TestApp from 'playwright/TestApp';
import buildApiUrl from 'playwright/utils/buildApiUrl';
import { contextWithAuth } from 'playwright/fixtures/auth';
import { test as base, expect } from 'playwright/lib';
import AccountActionsMenu from './AccountActionsMenu';
const USER_INFO_URL = buildApiUrl('user_info');
const test = base.extend({
context: ({ context }, use) => {
authFixture(context);
use(context);
},
const test = base.extend<{ context: BrowserContext }>({
context: contextWithAuth,
});
test.use({ viewport: { width: 200, height: 200 } });
......@@ -28,56 +22,32 @@ test.describe('with multiple items', async() => {
},
};
test.beforeEach(async({ page }) => {
await page.route(USER_INFO_URL, (route) => route.fulfill({
body: JSON.stringify(profileMock.base),
}));
test.beforeEach(async({ mockApiResponse }) => {
mockApiResponse('user_info', profileMock.base);
});
test('base view', async({ mount, page }) => {
const component = await mount(
<TestApp>
<AccountActionsMenu/>
</TestApp>,
{ hooksConfig },
);
test('base view', async({ render, page }) => {
const component = await render(<AccountActionsMenu/>, { hooksConfig });
await component.getByRole('button').click();
await expect(page).toHaveScreenshot();
});
test('base view with styles', async({ mount, page }) => {
const component = await mount(
<TestApp>
<AccountActionsMenu m={ 2 } outline="1px solid lightpink"/>
</TestApp>,
{ hooksConfig },
);
test('base view with styles', async({ render, page }) => {
const component = await render(<AccountActionsMenu m={ 2 } outline="1px solid lightpink"/>, { hooksConfig });
await component.getByRole('button').click();
await expect(page).toHaveScreenshot();
});
test('loading', async({ mount }) => {
const component = await mount(
<TestApp>
<AccountActionsMenu isLoading/>
</TestApp>,
{ hooksConfig },
);
test('loading', async({ render }) => {
const component = await render(<AccountActionsMenu isLoading/>, { hooksConfig });
await expect(component).toHaveScreenshot();
});
test('loading with styles', async({ mount }) => {
const component = await mount(
<TestApp>
<AccountActionsMenu isLoading m={ 2 } outline="1px solid lightpink"/>
</TestApp>,
{ hooksConfig },
);
test('loading with styles', async({ render }) => {
const component = await render(<AccountActionsMenu isLoading m={ 2 } outline="1px solid lightpink"/>, { hooksConfig });
await expect(component).toHaveScreenshot();
});
......@@ -92,39 +62,22 @@ test.describe('with one item', async() => {
},
};
test('base view', async({ mount, page }) => {
const component = await mount(
<TestApp>
<AccountActionsMenu/>
</TestApp>,
{ hooksConfig },
);
test('base view', async({ render, page }) => {
const component = await render(<AccountActionsMenu/>, { hooksConfig });
await component.getByRole('button').hover();
await expect(page).toHaveScreenshot();
});
test('base view with styles', async({ mount, page }) => {
const component = await mount(
<TestApp>
<AccountActionsMenu m={ 2 } outline="1px solid lightpink"/>
</TestApp>,
{ hooksConfig },
);
test('base view with styles', async({ render, page }) => {
const component = await render(<AccountActionsMenu m={ 2 } outline="1px solid lightpink"/>, { hooksConfig });
await component.getByRole('button').hover();
await expect(page).toHaveScreenshot();
});
test('loading', async({ mount }) => {
const component = await mount(
<TestApp>
<AccountActionsMenu isLoading/>
</TestApp>,
{ hooksConfig },
);
test('loading', async({ render }) => {
const component = await render(<AccountActionsMenu isLoading/>, { hooksConfig });
await expect(component).toHaveScreenshot();
});
......
import { test as base, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import type { WalletProvider } from 'types/web3';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import { FOOTER_LINKS } from 'mocks/config/footerLinks';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp';
import * as app from 'playwright/utils/app';
import buildApiUrl from 'playwright/utils/buildApiUrl';
import { test, expect } from 'playwright/lib';
import * as configs from 'playwright/utils/configs';
import Footer from './Footer';
const FOOTER_LINKS_URL = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_FOOTER_LINKS', 'https://localhost:3000/footer-links.json') || '';
const BACKEND_VERSION_API_URL = buildApiUrl('config_backend_version');
const INDEXING_ALERT_API_URL = buildApiUrl('homepage_indexing_status');
base.describe('with custom links, max cols', () => {
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_FOOTER_LINKS', value: FOOTER_LINKS_URL },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
});
const FOOTER_LINKS_URL = 'https://localhost:3000/footer-links.json';
test.beforeEach(async({ page, mount }) => {
await page.route(FOOTER_LINKS_URL, (route) => {
return route.fulfill({
body: JSON.stringify(FOOTER_LINKS),
});
test.describe('with custom links, max cols', () => {
test.beforeEach(async({ render, mockApiResponse, mockConfigResponse, injectMetaMaskProvider, mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_FOOTER_LINKS', FOOTER_LINKS_URL ],
]);
await mockConfigResponse('NEXT_PUBLIC_FOOTER_LINKS', FOOTER_LINKS_URL, JSON.stringify(FOOTER_LINKS));
await injectMetaMaskProvider();
await mockApiResponse('homepage_indexing_status', {
finished_indexing: false,
finished_indexing_blocks: false,
indexed_internal_transactions_ratio: '0.1',
indexed_blocks_ratio: '0.1',
});
await page.evaluate(() => {
window.ethereum = {
isMetaMask: true,
_events: {},
} as WalletProvider;
});
await page.route(INDEXING_ALERT_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify({ finished_indexing: false, indexed_internal_transactions_ratio: 0.1 }),
}));
await mount(
<TestApp>
<Footer/>
</TestApp>,
);
await render(<Footer/>);
});
test('+@mobile +@dark-mode', async({ page }) => {
......@@ -65,74 +38,35 @@ base.describe('with custom links, max cols', () => {
});
});
base.describe('with custom links, min cols', () => {
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_FOOTER_LINKS', value: FOOTER_LINKS_URL },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
});
test('base view +@dark-mode +@mobile', async({ mount, page }) => {
await page.route(FOOTER_LINKS_URL, (route) => {
return route.fulfill({
body: JSON.stringify([ FOOTER_LINKS[0] ]),
});
});
await mount(
<TestApp>
<Footer/>
</TestApp>,
);
test.describe('with custom links, min cols', () => {
test('base view +@dark-mode +@mobile', async({ render, page, mockConfigResponse, mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_FOOTER_LINKS', FOOTER_LINKS_URL ],
]);
await mockConfigResponse('NEXT_PUBLIC_FOOTER_LINKS', FOOTER_LINKS_URL, JSON.stringify([ FOOTER_LINKS[0] ]));
await render(<Footer/>);
await expect(page).toHaveScreenshot();
});
});
base.describe('without custom links', () => {
base('base view +@dark-mode +@mobile', async({ mount, page }) => {
await page.evaluate(() => {
window.ethereum = {
isMetaMask: true,
_events: {},
} as WalletProvider;
});
await page.route(BACKEND_VERSION_API_URL, (route) => {
return route.fulfill({
body: JSON.stringify({
backend_version: 'v5.2.0-beta.+commit.1ce1a355',
}),
});
});
await mount(
<TestApp>
<Footer/>
</TestApp>,
);
test.describe('without custom links', () => {
test('base view +@dark-mode +@mobile', async({ render, page, injectMetaMaskProvider, mockApiResponse }) => {
await injectMetaMaskProvider();
await mockApiResponse('config_backend_version', { backend_version: 'v5.2.0-beta.+commit.1ce1a355' });
await render(<Footer/>);
await expect(page).toHaveScreenshot();
});
base('with indexing alert +@dark-mode +@mobile', async({ mount, page }) => {
await page.evaluate(() => {
window.ethereum = {
providers: [ { isMetaMask: true, _events: {} } ],
} as WalletProvider;
test('with indexing alert +@dark-mode +@mobile', async({ render, injectMetaMaskProvider, mockApiResponse }) => {
await injectMetaMaskProvider();
await mockApiResponse('homepage_indexing_status', {
finished_indexing: false,
finished_indexing_blocks: false,
indexed_internal_transactions_ratio: '0.1',
indexed_blocks_ratio: '0.1',
});
await page.route(INDEXING_ALERT_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify({ finished_indexing: false, indexed_internal_transactions_ratio: 0.1 }),
}));
const component = await mount(
<TestApp>
<Footer/>
</TestApp>,
);
const component = await render(<Footer/>);
await expect(component).toHaveScreenshot();
});
});
import { test as base, expect, devices } from '@playwright/experimental-ct-react';
import type { BrowserContext } from '@playwright/test';
import React from 'react';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import { FEATURED_NETWORKS_MOCK } from 'mocks/config/network';
import authFixture from 'playwright/fixtures/auth';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import createContextWithStorage from 'playwright/fixtures/createContextWithStorage';
import TestApp from 'playwright/TestApp';
import * as app from 'playwright/utils/app';
import { contextWithAuth } from 'playwright/fixtures/auth';
import { test, expect, devices } from 'playwright/lib';
import Burger from './Burger';
const FEATURED_NETWORKS_URL = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_FEATURED_NETWORKS', 'https://localhost:3000/featured-networks.json') || '';
const FEATURED_NETWORKS_URL = 'https://localhost:3000/featured-networks.json';
const LOGO_URL = 'https://localhost:3000/my-logo.png';
base.use({ viewport: devices['iPhone 13 Pro'].viewport });
test.use({ viewport: devices['iPhone 13 Pro'].viewport });
const hooksConfig = {
router: {
......@@ -24,32 +20,16 @@ const hooksConfig = {
},
};
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_FEATURED_NETWORKS', value: FEATURED_NETWORKS_URL },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
test.beforeEach(async({ mockEnvs, mockConfigResponse, mockAssetResponse }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_FEATURED_NETWORKS', FEATURED_NETWORKS_URL ],
]);
await mockConfigResponse('NEXT_PUBLIC_FEATURED_NETWORKS', FEATURED_NETWORKS_URL, FEATURED_NETWORKS_MOCK);
await mockAssetResponse(LOGO_URL, './playwright/mocks/image_s.jpg');
});
test('base view', async({ mount, page }) => {
await page.route(FEATURED_NETWORKS_URL, (route) => {
return route.fulfill({
body: FEATURED_NETWORKS_MOCK,
});
});
await page.route(LOGO_URL, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
});
});
const component = await mount(
<TestApp>
<Burger/>
</TestApp>,
{ hooksConfig },
);
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();
......@@ -61,25 +41,8 @@ test('base view', async({ mount, page }) => {
test.describe('dark mode', () => {
test.use({ colorScheme: 'dark' });
test('base view', async({ mount, page }) => {
await page.route(FEATURED_NETWORKS_URL, (route) => {
return route.fulfill({
body: FEATURED_NETWORKS_MOCK,
});
});
await page.route(LOGO_URL, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
});
});
const component = await mount(
<TestApp>
<Burger/>
</TestApp>,
{ hooksConfig },
);
test('base view', async({ render, page }) => {
const component = await render(<Burger/>, { hooksConfig });
await component.locator('div[aria-label="Menu button"]').click();
await expect(page).toHaveScreenshot();
......@@ -89,39 +52,23 @@ test.describe('dark mode', () => {
});
});
test('submenu', async({ mount, page }) => {
const component = await mount(
<TestApp>
<Burger/>
</TestApp>,
{ hooksConfig },
);
test('submenu', async({ render, page }) => {
const component = await render(<Burger/>, { hooksConfig });
await component.locator('div[aria-label="Menu button"]').click();
await page.locator('div[aria-label="Blockchain link group"]').click();
await expect(page).toHaveScreenshot();
});
test.describe('auth', () => {
const extendedTest = base.extend({
context: async({ browser }, use) => {
const context = await createContextWithStorage(browser, [
{ name: 'NEXT_PUBLIC_FEATURED_NETWORKS', value: FEATURED_NETWORKS_URL },
]);
authFixture(context);
use(context);
},
});
const authTest = test.extend<{ context: BrowserContext }>({
context: contextWithAuth,
});
extendedTest.use({ viewport: { width: devices['iPhone 13 Pro'].viewport.width, height: 800 } });
authTest.describe('auth', () => {
authTest.use({ viewport: { width: devices['iPhone 13 Pro'].viewport.width, height: 800 } });
extendedTest('base view', async({ mount, page }) => {
const component = await mount(
<TestApp>
<Burger/>
</TestApp>,
{ hooksConfig },
);
authTest('base view', async({ render, page }) => {
const component = await render(<Burger/>, { hooksConfig });
await component.locator('div[aria-label="Menu button"]').click();
await expect(page).toHaveScreenshot();
......
import { Box, Flex } from '@chakra-ui/react';
import { test as base, expect } from '@playwright/experimental-ct-react';
import type { Locator } from '@playwright/test';
import type { BrowserContext, Locator } from '@playwright/test';
import React from 'react';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import config from 'configs/app';
import * as cookies from 'lib/cookies';
import authFixture from 'playwright/fixtures/auth';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import createContextWithStorage from 'playwright/fixtures/createContextWithStorage';
import TestApp from 'playwright/TestApp';
import * as app from 'playwright/utils/app';
import { FEATURED_NETWORKS_MOCK } from 'mocks/config/network';
import { contextWithAuth } from 'playwright/fixtures/auth';
import { test, expect } from 'playwright/lib';
import * as configs from 'playwright/utils/configs';
import NavigationDesktop from './NavigationDesktop';
......@@ -22,26 +19,24 @@ const hooksConfig = {
},
};
const FEATURED_NETWORKS_URL = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_FEATURED_NETWORKS', 'https://localhost:3000/config.json') || '';
const FEATURED_NETWORKS_URL = 'https://localhost:3000/featured-networks.json';
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_FEATURED_NETWORKS', value: FEATURED_NETWORKS_URL },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
test.beforeEach(async({ mockEnvs, mockConfigResponse }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_FEATURED_NETWORKS', FEATURED_NETWORKS_URL ],
]);
await mockConfigResponse('NEXT_PUBLIC_FEATURED_NETWORKS', FEATURED_NETWORKS_URL, FEATURED_NETWORKS_MOCK);
});
test.describe('no auth', () => {
let component: Locator;
test.beforeEach(async({ mount }) => {
component = await mount(
<TestApp>
test.beforeEach(async({ render }) => {
component = await render(
<Flex w="100%" minH="100vh" alignItems="stretch">
<NavigationDesktop/>
<Box bgColor="lightpink" w="100%"/>
</Flex>
</TestApp>,
</Flex>,
{ hooksConfig },
);
});
......@@ -59,39 +54,31 @@ test.describe('no auth', () => {
});
});
base.describe('auth', () => {
const test = base.extend({
context: async({ browser }, use) => {
const context = await createContextWithStorage(browser, [
{ name: 'NEXT_PUBLIC_FEATURED_NETWORKS', value: FEATURED_NETWORKS_URL },
]);
authFixture(context);
use(context);
},
});
const authTest = test.extend<{ context: BrowserContext }>({
context: contextWithAuth,
});
authTest.describe('auth', () => {
let component: Locator;
test.beforeEach(async({ mount }) => {
component = await mount(
<TestApp>
authTest.beforeEach(async({ render }) => {
component = await render(
<Flex w="100%" minH="100vh" alignItems="stretch">
<NavigationDesktop/>
<Box bgColor="lightpink" w="100%"/>
</Flex>
</TestApp>,
</Flex>,
{ hooksConfig },
);
});
test('+@dark-mode', async() => {
authTest('+@dark-mode', async() => {
await expect(component).toHaveScreenshot();
});
test.describe('xl screen', () => {
test.use({ viewport: configs.viewport.xl });
authTest.describe('xl screen', () => {
authTest.use({ viewport: configs.viewport.xl });
test('+@dark-mode', async() => {
authTest('+@dark-mode', async() => {
await expect(component).toHaveScreenshot();
});
});
......@@ -100,14 +87,12 @@ base.describe('auth', () => {
test.describe('with tooltips', () => {
test.use({ viewport: configs.viewport.xl });
test('', async({ mount, page }) => {
const component = await mount(
<TestApp>
test('', async({ render, page }) => {
const component = await render(
<Flex w="100%" minH="100vh" alignItems="stretch">
<NavigationDesktop/>
<Box bgColor="lightpink" w="100%"/>
</Flex>
</TestApp>,
</Flex>,
{ hooksConfig },
);
......@@ -122,14 +107,12 @@ test.describe('with tooltips', () => {
test.describe('with submenu', () => {
let component: Locator;
test.beforeEach(async({ mount, page }) => {
component = await mount(
<TestApp>
test.beforeEach(async({ render, page }) => {
component = await render(
<Flex w="100%" minH="100vh" alignItems="stretch">
<NavigationDesktop/>
<Box bgColor="lightpink" w="100%"/>
</Flex>
</TestApp>,
</Flex>,
{ hooksConfig },
);
await page.locator('a[aria-label="Blockchain link group"]').hover();
......@@ -148,65 +131,55 @@ test.describe('with submenu', () => {
});
});
base.describe('cookie set to false', () => {
const test = base.extend({
context: async({ browser }, use) => {
const context = await createContextWithStorage(browser, [
{ name: 'NEXT_PUBLIC_FEATURED_NETWORKS', value: FEATURED_NETWORKS_URL },
]);
context.addCookies([ { name: cookies.NAMES.NAV_BAR_COLLAPSED, value: 'false', domain: app.domain, path: '/' } ]);
const noSideBarCookieTest = test.extend({
context: ({ context }, use) => {
context.addCookies([ { name: cookies.NAMES.NAV_BAR_COLLAPSED, value: 'false', domain: config.app.host, path: '/' } ]);
use(context);
},
});
});
noSideBarCookieTest.describe('cookie set to false', () => {
let component: Locator;
test.beforeEach(async({ mount }) => {
component = await mount(
<TestApp>
noSideBarCookieTest.beforeEach(async({ render }) => {
component = await render(
<Flex w="100%" minH="100vh" alignItems="stretch">
<NavigationDesktop/>
<Box bgColor="lightpink" w="100%"/>
</Flex>
</TestApp>,
</Flex>,
{ hooksConfig },
);
});
test('', async() => {
noSideBarCookieTest('', async() => {
const networkMenu = component.locator('button[aria-label="Network menu"]');
await expect(networkMenu).toBeVisible();
});
test.describe('xl screen', () => {
test.use({ viewport: configs.viewport.xl });
noSideBarCookieTest.describe('xl screen', () => {
noSideBarCookieTest.use({ viewport: configs.viewport.xl });
test('', async() => {
noSideBarCookieTest('', async() => {
const networkMenu = component.locator('button[aria-label="Network menu"]');
await expect(networkMenu).toBeVisible();
});
});
});
base.describe('cookie set to true', () => {
const test = base.extend({
context: async({ browser }, use) => {
const context = await createContextWithStorage(browser, [
{ name: 'NEXT_PUBLIC_FEATURED_NETWORKS', value: FEATURED_NETWORKS_URL },
]);
context.addCookies([ { name: cookies.NAMES.NAV_BAR_COLLAPSED, value: 'true', domain: 'localhost', path: '/' } ]);
const sideBarCookieTest = test.extend({
context: ({ context }, use) => {
context.addCookies([ { name: cookies.NAMES.NAV_BAR_COLLAPSED, value: 'true', domain: config.app.host, path: '/' } ]);
use(context);
},
});
});
test('navbar is collapsed', async({ mount }) => {
const component = await mount(
<TestApp>
sideBarCookieTest.describe('cookie set to true', () => {
sideBarCookieTest('navbar is collapsed', async({ render }) => {
const component = await render(
<Flex w="100%" minH="100vh" alignItems="stretch">
<NavigationDesktop/>
<Box bgColor="lightpink" w="100%"/>
</Flex>
</TestApp>,
</Flex>,
{ hooksConfig },
);
......@@ -215,14 +188,12 @@ base.describe('cookie set to true', () => {
});
});
test('hover +@dark-mode', async({ mount }) => {
const component = await mount(
<TestApp>
test('hover +@dark-mode', async({ render }) => {
const component = await render(
<Flex w="100%" minH="100vh" alignItems="stretch">
<NavigationDesktop/>
<Box bgColor="lightpink" w="100%"/>
</Flex>
</TestApp>,
</Flex>,
{ hooksConfig },
);
......@@ -233,14 +204,12 @@ test('hover +@dark-mode', async({ mount }) => {
test.describe('hover xl screen', () => {
test.use({ viewport: configs.viewport.xl });
test('+@dark-mode', async({ mount }) => {
const component = await mount(
<TestApp>
test('+@dark-mode', async({ render }) => {
const component = await render(
<Flex w="100%" minH="100vh" alignItems="stretch">
<NavigationDesktop/>
<Box bgColor="lightpink" w="100%"/>
</Flex>
</TestApp>,
</Flex>,
{ hooksConfig },
);
......
import { test as base, expect } from '@playwright/experimental-ct-react';
import type { Locator } from '@playwright/test';
import React from 'react';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp';
import * as app from 'playwright/utils/app';
import { test, expect } from 'playwright/lib';
import * as configs from 'playwright/utils/configs';
import NetworkLogo from './NetworkLogo';
base.describe('placeholder logo', () => {
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_NETWORK_LOGO', value: '' },
{ name: 'NEXT_PUBLIC_NETWORK_ICON', value: '' },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
const LOGO_URL = 'https://localhost:3000/my-logo.png';
const ICON_URL = 'https://localhost:3000/my-icon.png';
test.describe('placeholder logo', () => {
test.beforeEach(async({ mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_NETWORK_LOGO', '' ],
[ 'NEXT_PUBLIC_NETWORK_ICON', '' ],
]);
});
test('+@dark-mode', async({ mount }) => {
const component = await mount(
<TestApp>
<NetworkLogo/>
</TestApp>,
);
test('+@dark-mode', async({ render }) => {
const component = await render(<NetworkLogo/>);
await expect(component.locator('a')).toHaveScreenshot();
});
......@@ -32,50 +26,25 @@ base.describe('placeholder logo', () => {
test.describe('screen xl', () => {
test.use({ viewport: configs.viewport.xl });
test('+@dark-mode', async({ mount }) => {
const component = await mount(
<TestApp>
<NetworkLogo/>
</TestApp>,
);
test('+@dark-mode', async({ render }) => {
const component = await render(<NetworkLogo/>);
await expect(component.locator('a')).toHaveScreenshot();
});
});
});
base.describe('custom logo', () => {
const LOGO_URL = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO', 'https://localhost:3000/my-logo.png') || '';
const ICON_URL = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON', 'https://localhost:3000/my-icon.png') || '';
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_NETWORK_LOGO', value: LOGO_URL },
{ name: 'NEXT_PUBLIC_NETWORK_ICON', value: ICON_URL },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
});
test.describe('custom logo', () => {
let component: Locator;
test.beforeEach(async({ page, mount }) => {
await page.route(LOGO_URL, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/network-logo.svg',
});
});
await page.route(ICON_URL, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_svg.svg',
});
});
component = await mount(
<TestApp>
<NetworkLogo/>
</TestApp>,
);
test.beforeEach(async({ render, mockConfigResponse, mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_NETWORK_LOGO', LOGO_URL ],
[ 'NEXT_PUBLIC_NETWORK_ICON', ICON_URL ],
]);
await mockConfigResponse('NEXT_PUBLIC_NETWORK_LOGO', LOGO_URL, './playwright/mocks/network-logo.svg', true);
await mockConfigResponse('NEXT_PUBLIC_NETWORK_ICON', ICON_URL, './playwright/mocks/image_svg.svg', true);
component = await render(<NetworkLogo/>);
});
test('+@dark-mode', async() => {
......@@ -91,54 +60,22 @@ base.describe('custom logo', () => {
});
});
base.describe('custom logo with dark option -@default +@dark-mode', () => {
const LOGO_URL = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO', 'https://localhost:3000/my-logo.png') || '';
const LOGO_URL_DARK = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO_DARK', 'https://localhost:3000/my-logo.png') || '';
const ICON_URL = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON', 'https://localhost:3000/my-icon.png') || '';
const ICON_URL_DARK = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON_DARK', 'https://localhost:3000/my-icon.png') || '';
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_NETWORK_LOGO', value: LOGO_URL },
{ name: 'NEXT_PUBLIC_NETWORK_LOGO_DARK', value: LOGO_URL_DARK },
{ name: 'NEXT_PUBLIC_NETWORK_ICON', value: ICON_URL },
{ name: 'NEXT_PUBLIC_NETWORK_ICON_DARK', value: ICON_URL_DARK },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
});
test.describe('custom logo with dark option -@default +@dark-mode', () => {
let component: Locator;
test.beforeEach(async({ page, mount }) => {
await page.route(LOGO_URL, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_long.jpg',
});
});
await page.route(LOGO_URL_DARK, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_long.jpg',
});
});
await page.route(ICON_URL, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
});
});
await page.route(ICON_URL_DARK, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
});
});
component = await mount(
<TestApp>
<NetworkLogo/>
</TestApp>,
);
test.beforeEach(async({ render, mockConfigResponse, mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_NETWORK_LOGO', LOGO_URL ],
[ 'NEXT_PUBLIC_NETWORK_LOGO_DARK', LOGO_URL ],
[ 'NEXT_PUBLIC_NETWORK_ICON', ICON_URL ],
[ 'NEXT_PUBLIC_NETWORK_ICON_DARK', ICON_URL ],
]);
await mockConfigResponse('NEXT_PUBLIC_NETWORK_LOGO', LOGO_URL, './playwright/mocks/image_long.jpg', true);
await mockConfigResponse('NEXT_PUBLIC_NETWORK_LOGO_DARK', LOGO_URL, './playwright/mocks/image_long.jpg', true);
await mockConfigResponse('NEXT_PUBLIC_NETWORK_ICON', ICON_URL, './playwright/mocks/image_s.jpg', true);
await mockConfigResponse('NEXT_PUBLIC_NETWORK_ICON_DARK', ICON_URL, './playwright/mocks/image_s.jpg', true);
component = await render(<NetworkLogo/>);
});
test('', async() => {
......
import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import { FEATURED_NETWORKS_MOCK } from 'mocks/config/network';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp';
import * as app from 'playwright/utils/app';
import { test, expect } from 'playwright/lib';
import NetworkMenu from './NetworkMenu';
const FEATURED_NETWORKS_URL = app.url + buildExternalAssetFilePath('NEXT_PUBLIC_FEATURED_NETWORKS', 'https://localhost:3000/featured-networks.json') || '';
const FEATURED_NETWORKS_URL = 'https://localhost:3000/featured-networks.json';
const LOGO_URL = 'https://localhost:3000/my-logo.png';
const extendedTest = test.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_FEATURED_NETWORKS', value: FEATURED_NETWORKS_URL },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
});
test.use({ viewport: { width: 1600, height: 1000 } });
test('base view +@dark-mode', async({ render, page, mockConfigResponse, mockAssetResponse, mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_FEATURED_NETWORKS', FEATURED_NETWORKS_URL ],
]);
await mockConfigResponse('NEXT_PUBLIC_FEATURED_NETWORKS', FEATURED_NETWORKS_URL, FEATURED_NETWORKS_MOCK);
await mockAssetResponse(LOGO_URL, './playwright/mocks/image_s.jpg');
extendedTest.use({ viewport: { width: 1600, height: 1000 } });
extendedTest('base view +@dark-mode', async({ mount, page }) => {
const LOGO_URL = 'https://localhost:3000/my-logo.png';
await page.route(LOGO_URL, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
});
});
await page.route(FEATURED_NETWORKS_URL, (route) => {
return route.fulfill({
status: 200,
body: FEATURED_NETWORKS_MOCK,
});
});
const component = await mount(
<TestApp>
<NetworkMenu/>
</TestApp>,
);
const component = await render(<NetworkMenu/>);
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 36, height: 36 } });
......
import type { BrowserContext } from '@playwright/test';
import React from 'react';
import config from 'configs/app';
import * as profileMock from 'mocks/user/profile';
import authFixture from 'playwright/fixtures/auth';
import { contextWithAuth } from 'playwright/fixtures/auth';
import { test, expect } from 'playwright/lib';
import * as app from 'playwright/utils/app';
import ProfileMenuDesktop from './ProfileMenuDesktop';
......@@ -17,14 +18,11 @@ test('no auth', async({ render, page }) => {
const component = await render(<ProfileMenuDesktop/>, { hooksConfig });
await component.locator('a').click();
expect(page.url()).toBe(`${ app.url }/auth/auth0?path=%2F`);
expect(page.url()).toBe(`${ config.app.baseUrl }/auth/auth0?path=%2F`);
});
const authTest = test.extend({
context: ({ context }, use) => {
authFixture(context);
use(context);
},
const authTest = test.extend<{ context: BrowserContext }>({
context: contextWithAuth,
});
authTest('auth +@dark-mode', async({ render, page, mockApiResponse, mockAssetResponse }) => {
await mockApiResponse('user_info', profileMock.base);
......
import { test, expect, devices } from '@playwright/experimental-ct-react';
import type { BrowserContext } from '@playwright/test';
import React from 'react';
import config from 'configs/app';
import * as profileMock from 'mocks/user/profile';
import authFixture from 'playwright/fixtures/auth';
import TestApp from 'playwright/TestApp';
import * as app from 'playwright/utils/app';
import buildApiUrl from 'playwright/utils/buildApiUrl';
import { contextWithAuth } from 'playwright/fixtures/auth';
import { test, expect, devices } from 'playwright/lib';
import ProfileMenuMobile from './ProfileMenuMobile';
test('no auth', async({ mount, page }) => {
test('no auth', async({ render, page }) => {
const hooksConfig = {
router: {
asPath: '/',
pathname: '/',
},
};
const component = await mount(
<TestApp>
<ProfileMenuMobile/>
</TestApp>,
{ hooksConfig },
);
const component = await render(<ProfileMenuMobile/>, { hooksConfig });
await component.locator('a').click();
expect(page.url()).toBe(`${ app.url }/auth/auth0?path=%2F`);
expect(page.url()).toBe(`${ config.app.baseUrl }/auth/auth0?path=%2F`);
});
test.use({ viewport: devices['iPhone 13 Pro'].viewport });
test.describe('auth', () => {
const extendedTest = test.extend({
context: ({ context }, use) => {
authFixture(context);
use(context);
},
});
extendedTest('base view', async({ mount, page }) => {
await page.route(buildApiUrl('user_info'), (route) => route.fulfill({
status: 200,
body: JSON.stringify(profileMock.base),
}));
await page.route(profileMock.base.avatar, (route) => {
return route.fulfill({
status: 200,
path: './playwright/mocks/image_s.jpg',
});
});
const authTest = test.extend<{ context: BrowserContext }>({
context: contextWithAuth,
});
const component = await mount(
<TestApp>
<ProfileMenuMobile/>
</TestApp>,
);
authTest.describe('auth', () => {
authTest('base view', async({ render, page, mockApiResponse, mockAssetResponse }) => {
await mockApiResponse('user_info', profileMock.base);
await mockAssetResponse(profileMock.base.avatar, './playwright/mocks/image_s.jpg');
const component = await render(<ProfileMenuMobile/>);
await component.getByAltText(/Profile picture/i).click();
await expect(page).toHaveScreenshot();
});
});
This diff is collapsed.
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