Skip to content

Commit

Permalink
refactor: add swap tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fbwoolf committed Dec 8, 2023
1 parent 886309b commit bd6dc1a
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 22 deletions.
7 changes: 6 additions & 1 deletion src/app/pages/home/components/account-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ export function AccountActions(props: FlexProps) {
/>
)}

<ActionButton icon={<SwapIcon />} label="Swap" onClick={() => navigate(RouteUrls.Swap)} />
<ActionButton
data-testid={HomePageSelectors.SwapBtn}
icon={<SwapIcon />}
label="Swap"
onClick={() => navigate(RouteUrls.Swap)}
/>
</Flex>
);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SwapSelectors } from '@tests/selectors/swap.selectors';
import { useField } from 'formik';
import { HStack, styled } from 'leather-styles/jsx';

Expand All @@ -19,7 +20,13 @@ export function SelectAssetTriggerButton({
const [field] = useField(name);

return (
<LeatherButton onClick={onChooseAsset} p="space.02" variant="ghost" {...field}>
<LeatherButton
data-testid={SwapSelectors.SelectAssetTriggerBtn}
onClick={onChooseAsset}
p="space.02"
variant="ghost"
{...field}
>
<HStack>
{icon && <styled.img src={icon} width="32px" height="32px" alt="Swap asset" />}
<styled.span textStyle="label.01">{symbol}</styled.span>
Expand Down
2 changes: 2 additions & 0 deletions src/app/pages/swap/components/swap-amount-field.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ChangeEvent } from 'react';

import { SwapSelectors } from '@tests/selectors/swap.selectors';
import BigNumber from 'bignumber.js';
import { useField, useFormikContext } from 'formik';
import { Stack, styled } from 'leather-styles/jsx';
Expand Down Expand Up @@ -60,6 +61,7 @@ export function SwapAmountField({ amountAsFiat, isDisabled, name }: SwapAmountFi
bg="accent.background-primary"
border="none"
color={showError ? 'error.label' : 'accent.text-primary'}
data-testid={SwapSelectors.SwapAmountInput}
display="block"
disabled={isDisabled || isFetchingExchangeRate}
id={name}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SwapSelectors } from '@tests/selectors/swap.selectors';
import { HStack, styled } from 'leather-styles/jsx';

import { Flag } from '@app/components/layout/flag';
Expand All @@ -20,8 +21,12 @@ export function SwapAssetItemLayout({ caption, icon, symbol, value }: SwapAssetI
{caption}
</styled.span>
<HStack alignItems="center" justifyContent="space-between">
<styled.span textStyle="heading.05">{symbol}</styled.span>
<styled.span textStyle="heading.05">{value}</styled.span>
<styled.span data-testid={SwapSelectors.SwapDetailsSymbol} textStyle="heading.05">
{symbol}
</styled.span>
<styled.span data-testid={SwapSelectors.SwapDetailsAmount} textStyle="heading.05">
{value}
</styled.span>
</HStack>
</Flag>
);
Expand Down
4 changes: 2 additions & 2 deletions src/app/pages/swap/components/swap-content.layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SwapCryptoAssetSelectors } from '@tests/selectors/swap.selectors';
import { SwapSelectors } from '@tests/selectors/swap.selectors';
import { Flex } from 'leather-styles/jsx';

import { HasChildren } from '@app/common/has-children';
Expand All @@ -7,7 +7,7 @@ export function SwapContentLayout({ children }: HasChildren) {
return (
<Flex
alignItems="center"
data-testid={SwapCryptoAssetSelectors.SwapPageReady}
data-testid={SwapSelectors.SwapPageReady}
flexDirection="column"
maxHeight={['calc(100vh - 116px)', 'calc(85vh - 116px)']}
overflowY="auto"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@ import { Tooltip } from '@app/components/tooltip';
import { InfoIcon } from '@app/ui/components/icons/info-icon';

interface SwapDetailLayoutProps {
dataTestId?: string;
title: string;
tooltipLabel?: string;
value: ReactNode;
}
export function SwapDetailLayout({ title, tooltipLabel, value }: SwapDetailLayoutProps) {
export function SwapDetailLayout({
dataTestId,
title,
tooltipLabel,
value,
}: SwapDetailLayoutProps) {
return (
<HStack alignItems="center" justifyContent="space-between" width="100%">
<HStack alignItems="center" gap="space.01">
Expand All @@ -25,7 +31,7 @@ export function SwapDetailLayout({ title, tooltipLabel, value }: SwapDetailLayou
</Tooltip>
) : null}
</HStack>
<styled.span fontWeight={500} textStyle="label.02">
<styled.span data-testid={dataTestId} fontWeight={500} textStyle="label.02">
{value}
</styled.span>
</HStack>
Expand Down
9 changes: 7 additions & 2 deletions src/app/pages/swap/components/swap-details/swap-details.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SwapSelectors } from '@tests/selectors/swap.selectors';
import BigNumber from 'bignumber.js';
import { HStack, styled } from 'leather-styles/jsx';

Expand All @@ -21,7 +22,7 @@ function RouteNames(props: { swapSubmissionData: SwapSubmissionData }) {
return (
<HStack gap="space.01" key={route.name}>
<styled.span>{route.name}</styled.span>
{insertIcon && <ChevronUpIcon transform="rotate(90)" />}
{insertIcon && <ChevronUpIcon transform="rotate(90deg)" />}
</HStack>
);
});
Expand Down Expand Up @@ -49,7 +50,11 @@ export function SwapDetails() {

return (
<SwapDetailsLayout>
<SwapDetailLayout title="Powered by" value={swapSubmissionData.protocol} />
<SwapDetailLayout
dataTestId={SwapSelectors.SwapDetailsProtocol}
title="Powered by"
value={swapSubmissionData.protocol}
/>
<SwapDetailLayout
title="Route"
value={
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useNavigate } from 'react-router-dom';

import { SwapSelectors } from '@tests/selectors/swap.selectors';
import BigNumber from 'bignumber.js';
import { useFormikContext } from 'formik';
import { styled } from 'leather-styles/jsx';
Expand Down Expand Up @@ -68,6 +69,7 @@ export function SwapAssetList({ assets }: SwapAssetList) {
<SwapAssetListLayout>
{selectableAssets.map(asset => (
<styled.button
data-testid={SwapSelectors.ChooseAssetListItem}
key={asset.balance.symbol}
onClick={() => onChooseAsset(asset)}
textAlign="left"
Expand Down
3 changes: 2 additions & 1 deletion src/app/pages/swap/swap-choose-asset/swap-choose-asset.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useLocation, useNavigate } from 'react-router-dom';

import { SwapSelectors } from '@tests/selectors/swap.selectors';
import { Box, styled } from 'leather-styles/jsx';
import get from 'lodash.get';

Expand Down Expand Up @@ -37,7 +38,7 @@ export function SwapChooseAsset() {

return (
<BaseDrawer title="" isShowing onClose={() => navigate(-1)}>
<Box mx="space.06">
<Box data-testid={SwapSelectors.ChooseAssetList} mx="space.06">
<styled.h1 mb="space.05" textStyle="heading.03">
{title}
</styled.h1>
Expand Down
10 changes: 9 additions & 1 deletion src/app/pages/swap/swap-review/swap-review.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Outlet } from 'react-router-dom';

import { SwapSelectors } from '@tests/selectors/swap.selectors';

import { LoadingKeys, useLoading } from '@app/common/hooks/use-loading';
import { useRouteHeader } from '@app/common/hooks/use-route-header';
import { ModalHeader } from '@app/components/modal-header';
Expand All @@ -26,7 +28,13 @@ export function SwapReview() {
<SwapDetails />
</SwapContentLayout>
<SwapFooterLayout>
<LeatherButton aria-busy={isLoading} type="button" onClick={onSubmitSwap} fullWidth>
<LeatherButton
aria-busy={isLoading}
data-testid={SwapSelectors.SwapBtn}
type="button"
onClick={onSubmitSwap}
fullWidth
>
Swap
</LeatherButton>
</SwapFooterLayout>
Expand Down
2 changes: 2 additions & 0 deletions src/app/pages/swap/swap.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useAsync } from 'react-async-hook';
import { Outlet } from 'react-router-dom';

import { SwapSelectors } from '@tests/selectors/swap.selectors';
import { useFormikContext } from 'formik';

import { isUndefined } from '@shared/utils';
Expand Down Expand Up @@ -37,6 +38,7 @@ export function Swap() {
</SwapContentLayout>
<SwapFooterLayout>
<LeatherButton
data-testid={SwapSelectors.SwapReviewBtn}
disabled={!(dirty && isValid) || isFetchingExchangeRate}
type="submit"
width="100%"
Expand Down
35 changes: 31 additions & 4 deletions tests/page-object-models/swap.page.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,44 @@
import { Page } from '@playwright/test';
import { SwapCryptoAssetSelectors } from '@tests/selectors/swap.selectors';
import { Locator, Page } from '@playwright/test';
import { SwapSelectors } from '@tests/selectors/swap.selectors';
import { createTestSelector } from '@tests/utils';

export class SwapPage {
readonly page: Page;
readonly chooseAssetList: Locator;
readonly chooseAssetListItem: Locator;
readonly selectAssetBtn: Locator;
readonly swapAmountInput: Locator;
readonly swapBtn: Locator;
readonly swapDetailsAmount: Locator;
readonly swapDetailsProtocol: Locator;
readonly swapDetailsSymbol: Locator;
readonly swapReviewBtn: Locator;

constructor(page: Page) {
this.page = page;
this.chooseAssetList = page.getByTestId(SwapSelectors.ChooseAssetList);
this.chooseAssetListItem = page.getByTestId(SwapSelectors.ChooseAssetListItem);
this.selectAssetBtn = page.getByTestId(SwapSelectors.SelectAssetTriggerBtn);
this.swapAmountInput = page.getByTestId(SwapSelectors.SwapAmountInput);
this.swapBtn = page.getByTestId(SwapSelectors.SwapBtn);
this.swapDetailsAmount = page.getByTestId(SwapSelectors.SwapDetailsAmount);
this.swapDetailsProtocol = page.getByTestId(SwapSelectors.SwapDetailsProtocol);
this.swapDetailsSymbol = page.getByTestId(SwapSelectors.SwapDetailsSymbol);
this.swapReviewBtn = page.getByTestId(SwapSelectors.SwapReviewBtn);
}

async waitForSendPageReady() {
await this.page.waitForSelector(createTestSelector(SwapCryptoAssetSelectors.SwapPageReady), {
async waitForSwapPageReady() {
await this.page.waitForSelector(createTestSelector(SwapSelectors.SwapPageReady), {
state: 'attached',
});
}

async selectAssetToReceive() {
const swapAssetSelectors = await this.selectAssetBtn.all();
await swapAssetSelectors[1].click();
await this.chooseAssetList.waitFor();
const swapAssets = await this.chooseAssetListItem.all();
await swapAssets[0].click();
await this.swapReviewBtn.click();
}
}
11 changes: 10 additions & 1 deletion tests/selectors/swap.selectors.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
export enum SwapCryptoAssetSelectors {
export enum SwapSelectors {
ChooseAssetList = 'choose-asset-list',
ChooseAssetListItem = 'choose-asset-list-item',
SelectAssetTriggerBtn = 'select-asset-trigger-btn',
SwapAmountInput = 'swap-amount-input',
SwapBtn = 'swap-btn',
SwapDetailsAmount = 'swap-details-amount',
SwapDetailsProtocol = 'swap-details-protocol',
SwapDetailsSymbol = 'swap-details-symbol',
SwapPageReady = 'swap-page-ready',
SwapReviewBtn = 'swap-review-btn',
}
50 changes: 45 additions & 5 deletions tests/specs/swap/swap.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,56 @@
import { test } from '../../fixtures/fixtures';

test.describe('swap', () => {
const alexSdkPostRoute = 'https://gql.alexlab.co/v1/graphql';

test.describe('Swaps', () => {
test.beforeEach(async ({ extensionId, globalPage, homePage, onboardingPage, swapPage }) => {
await globalPage.setupAndUseApiCalls(extensionId);
await onboardingPage.signInWithTestAccount(extensionId);
await homePage.enableTestMode();
await homePage.swapButton.click();
await swapPage.waitForSendPageReady();
await swapPage.waitForSwapPageReady();
});

test('that it defaults to swapping STX', async ({ swapPage }) => {
test.expect(swapPage.page.getByText('STX')).toBeTruthy();
});

// Skip tests until feature is live
test.skip('that it shows swap page', async ({ swapPage }) => {
await test.expect(swapPage.page.getByText('Swap')).toBeVisible();
test('that it shows correct swap review details', async ({ swapPage }) => {
const swapAmountInputs = await swapPage.swapAmountInput.all();
await swapAmountInputs[0].fill('1');
await swapPage.selectAssetToReceive();

const swapProtocol = await swapPage.swapDetailsProtocol.innerText();
test.expect(swapProtocol).toEqual('ALEX');

const swapAssets = await swapPage.swapDetailsSymbol.all();
const swapAssetFrom = await swapAssets[0].innerText();
const swapAssetTo = await swapAssets[1].innerText();
test.expect(swapAssetFrom).toEqual('STX');
test.expect(swapAssetTo).toEqual('ALEX');

const swapAmounts = await swapPage.swapDetailsAmount.all();
const swapAmountFrom = await swapAmounts[0].innerText();
test.expect(swapAmountFrom).toEqual('1');

test.expect(swapPage.page.getByText('Sponsored')).toBeTruthy();
});

test('that the swap is broadcast', async ({ swapPage }) => {
const requestPromise = swapPage.page.waitForRequest(alexSdkPostRoute);

await swapPage.page.route(alexSdkPostRoute, async route => {
await route.abort();
});

const swapAmountInputs = await swapPage.swapAmountInput.all();
await swapAmountInputs[0].fill('1');
await swapPage.selectAssetToReceive();

await swapPage.swapBtn.click();

const request = await requestPromise;
const requestBody = request.postDataBuffer();
test.expect(requestBody).toBeDefined();
});
});

0 comments on commit bd6dc1a

Please sign in to comment.