Skip to content

Commit

Permalink
Sergei / wall 147 / in progress and migrated banner (#8201)
Browse files Browse the repository at this point in the history
* feat: create a scratch of desktop upgrade banner

* feat: create upgrade wallet banner

* feat: add review suggestions and rename WalletsBannerImage component

* feat: add images and scratch of components

* feat: add some suggestions

* feat: add some images

* feat: almost complete upgrading banner

* feat: finished with ready banner

* feat: change title for ready banner

* refactor: change icon name

* feat: add size for tick

* feat: add tests

* feat: add some changes from PR review

* feat: add changes from review

* feat: add some constants

* refactor: add React.Fragment

* refactor: change images name

* feat: add suggestions after review

* feat: add switch to wallets-banner component

* feat: change short dash to long dash

* feat: add logout when click ready banner logout button

* feat: fix tests

* feat: add 1 more test for logout
  • Loading branch information
sergei-deriv committed May 2, 2023
1 parent dd27d69 commit 9fd7089
Show file tree
Hide file tree
Showing 23 changed files with 712 additions and 2 deletions.
10 changes: 10 additions & 0 deletions packages/appstore/src/assets/svgs/wallets/image-types.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { WalletsImagesList } from './index';

export type TWalletsImagesListKeys = keyof typeof WalletsImagesList;
export type TImageTestID = `dt_${TWalletsImagesListKeys}`;

export type WalletsImageProps<T> = {
image: T;
className?: string;
width?: number;
};
30 changes: 30 additions & 0 deletions packages/appstore/src/assets/svgs/wallets/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import UpgradeDesktopImage from 'Assets/svgs/wallets/wallets-upgrade-desktop.svg';
import UpgradeMobileImage from 'Assets/svgs/wallets/wallets-upgrade-mobile.svg';
import ReadyDesktopImage from 'Assets/svgs/wallets/wallets-ready-desktop.svg';
import ReadyDesktopEuImage from 'Assets/svgs/wallets/wallets-ready-desktop-eu.svg';
import ReadyMobileImage from 'Assets/svgs/wallets/wallets-ready-mobile.svg';
import ReadyMobileEuImage from 'Assets/svgs/wallets/wallets-ready-mobile-eu.svg';
import { TImageTestID, TWalletsImagesListKeys, WalletsImageProps } from './image-types';

export const WalletsImagesList = {
upgrade_desktop: UpgradeDesktopImage,
upgrade_mobile: UpgradeMobileImage,
upgrading_desktop: ReadyDesktopImage,
upgrading_desktop_eu: ReadyDesktopEuImage,
upgrading_mobile: ReadyMobileImage,
upgrading_mobile_eu: ReadyMobileEuImage,
ready_desktop: ReadyDesktopImage,
ready_desktop_eu: ReadyDesktopEuImage,
ready_mobile: ReadyMobileImage,
ready_mobile_eu: ReadyMobileEuImage,
} as const;

const WalletsImage = ({ image, className, width }: WalletsImageProps<TWalletsImagesListKeys>) => {
const Component = WalletsImagesList[image] as React.ElementType;
const data_testid: TImageTestID = `dt_${image}`;

return <Component className={className} style={{ width }} data-testid={data_testid} />;
};

export default WalletsImage;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import { isMobile } from '@deriv/shared';
import { mockStore, StoreProvider } from '@deriv/stores';
import WalletsBannerUpgrade from '../wallets-banner-upgrade';
import { TImageTestID } from 'Assets/svgs/wallets/image-types';
import WalletsBannerUpgrading from '../wallets-banner-upgrading';
import WalletsBannerReady from '../wallets-banner-ready';

jest.mock('@deriv/shared', () => ({
...jest.requireActual('@deriv/shared'),
isMobile: jest.fn(() => false),
}));

describe('<WalletsBanner />', () => {
describe('Should render properly with right banner if status is eligible: <WalletsBannerUpgrade />', () => {
const desktop: TImageTestID = 'dt_upgrade_desktop';
const mobile: TImageTestID = 'dt_upgrade_mobile';

it('Should render right button', () => {
render(<WalletsBannerUpgrade />);
const btn = screen.queryByText('Upgrade now');

expect(btn).toBeInTheDocument();
});

it('Should render image properly for desktop', () => {
isMobile.mockReturnValue(false);
render(<WalletsBannerUpgrade />);
const desktop_image = screen.queryByTestId(desktop);
const mobile_image = screen.queryByTestId(mobile);

expect(desktop_image).toBeInTheDocument();
expect(mobile_image).not.toBeInTheDocument();
});

it('Should render image properly for mobile', () => {
isMobile.mockReturnValue(true);
render(<WalletsBannerUpgrade />);
const desktop_image = screen.queryByTestId(desktop);
const mobile_image = screen.queryByTestId(mobile);

expect(mobile_image).toBeInTheDocument();
expect(desktop_image).not.toBeInTheDocument();
});
});

describe('Should render properly with right banner if status is in_progress: <WalletsBannerUpgrading />', () => {
const desktop: TImageTestID = 'dt_upgrading_desktop';
const mobile: TImageTestID = 'dt_upgrading_mobile';
const desktop_eu: TImageTestID = 'dt_upgrading_desktop_eu';
const mobile_eu: TImageTestID = 'dt_upgrading_mobile_eu';

it('Should render right title', () => {
render(<WalletsBannerUpgrading />);
const title = screen.queryByText(/We're setting up your Wallets/i);

expect(title).toBeInTheDocument();
});

it('Should render loading dots', () => {
render(<WalletsBannerUpgrading />);
const loading_dots = screen.queryByTestId('dt_wallets-loading-dots');

expect(loading_dots).toBeInTheDocument();
});

it('Should render image properly for desktop for Non-EU', () => {
isMobile.mockReturnValue(false);
render(<WalletsBannerUpgrading />);
const desktop_image = screen.queryByTestId(desktop);
const mobile_image = screen.queryByTestId(mobile);

expect(desktop_image).toBeInTheDocument();
expect(mobile_image).not.toBeInTheDocument();
});

it('Should render image properly for mobile for Non-EU', () => {
isMobile.mockReturnValue(true);
render(<WalletsBannerUpgrading />);
const desktop_image = screen.queryByTestId(desktop);
const mobile_image = screen.queryByTestId(mobile);

expect(mobile_image).toBeInTheDocument();
expect(desktop_image).not.toBeInTheDocument();
});

it('Should render image properly for desktop for EU', () => {
isMobile.mockReturnValue(false);
render(<WalletsBannerUpgrading is_eu={true} />);
const desktop_image = screen.queryByTestId(desktop_eu);
const mobile_image = screen.queryByTestId(mobile_eu);

expect(desktop_image).toBeInTheDocument();
expect(mobile_image).not.toBeInTheDocument();
});

it('Should render image properly for mobile for EU', () => {
isMobile.mockReturnValue(true);
render(<WalletsBannerUpgrading is_eu={true} />);
const desktop_image = screen.queryByTestId(desktop_eu);
const mobile_image = screen.queryByTestId(mobile_eu);

expect(mobile_image).toBeInTheDocument();
expect(desktop_image).not.toBeInTheDocument();
});
});

describe('Should render properly with right banner if status is migrated: <WalletsBannerReady />', () => {
const desktop: TImageTestID = 'dt_ready_desktop';
const mobile: TImageTestID = 'dt_ready_mobile';
const desktop_eu: TImageTestID = 'dt_ready_desktop_eu';
const mobile_eu: TImageTestID = 'dt_ready_mobile_eu';
const mocked_root_store = mockStore({});

it('Should render right title', () => {
render(
<StoreProvider store={mocked_root_store}>
<WalletsBannerReady />
</StoreProvider>
);
const title = screen.queryByText(/Your Wallets are ready/i);

expect(title).toBeInTheDocument();
});

it('Should render tick', () => {
render(
<StoreProvider store={mocked_root_store}>
<WalletsBannerReady />
</StoreProvider>
);
const tick = screen.queryByTestId('dt_wallets-ready-tick');

expect(tick).toBeInTheDocument();
});

it('Should render right button', () => {
render(
<StoreProvider store={mocked_root_store}>
<WalletsBannerReady />
</StoreProvider>
);
const btn = screen.queryByText('Log out');

expect(btn).toBeInTheDocument();
});

it('Should render image properly for desktop for Non-EU', () => {
isMobile.mockReturnValue(false);
render(
<StoreProvider store={mocked_root_store}>
<WalletsBannerReady />
</StoreProvider>
);
const desktop_image = screen.queryByTestId(desktop);
const mobile_image = screen.queryByTestId(mobile);

expect(desktop_image).toBeInTheDocument();
expect(mobile_image).not.toBeInTheDocument();
});

it('Should render image properly for mobile for Non-EU', () => {
isMobile.mockReturnValue(true);
render(
<StoreProvider store={mocked_root_store}>
<WalletsBannerReady />
</StoreProvider>
);
const desktop_image = screen.queryByTestId(desktop);
const mobile_image = screen.queryByTestId(mobile);

expect(mobile_image).toBeInTheDocument();
expect(desktop_image).not.toBeInTheDocument();
});

it('Should render image properly for desktop for EU', () => {
isMobile.mockReturnValue(false);
render(
<StoreProvider store={mocked_root_store}>
<WalletsBannerReady is_eu={true} />
</StoreProvider>
);
const desktop_image = screen.queryByTestId(desktop_eu);
const mobile_image = screen.queryByTestId(mobile_eu);

expect(desktop_image).toBeInTheDocument();
expect(mobile_image).not.toBeInTheDocument();
});

it('Should render image properly for mobile for EU', () => {
isMobile.mockReturnValue(true);
render(
<StoreProvider store={mocked_root_store}>
<WalletsBannerReady is_eu={true} />
</StoreProvider>
);
const desktop_image = screen.queryByTestId(desktop_eu);
const mobile_image = screen.queryByTestId(mobile_eu);

expect(mobile_image).toBeInTheDocument();
expect(desktop_image).not.toBeInTheDocument();
});

it('Should call logout function when click on button', async () => {
render(
<StoreProvider store={mocked_root_store}>
<WalletsBannerReady />
</StoreProvider>
);

const btn = screen.getByText('Log out');

await userEvent.click(btn);

expect(btn).toBeInTheDocument();
expect(mocked_root_store.client.logout).toBeCalledTimes(1);
});
});
});
4 changes: 4 additions & 0 deletions packages/appstore/src/components/wallets-banner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import WalletsBanner from './wallets-banner';
import './wallets-banner.scss';

export default WalletsBanner;
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import WalletsImage from 'Assets/svgs/wallets';
import { Button, Icon, Text } from '@deriv/components';
import { Localize, localize } from '@deriv/translations';
import { isMobile } from '@deriv/shared';
import { TWalletsImagesListKeys } from 'Assets/svgs/wallets/image-types';
import { useStore } from '@deriv/stores';

// just for now for testing purpose, in the future 'is_eu' value will be taken from the store
type TWalletsBannerReady = {
is_eu?: boolean;
};

const WalletsBannerReady = ({ is_eu }: TWalletsBannerReady) => {
const {
client: { logout },
} = useStore();

const image: TWalletsImagesListKeys = isMobile()
? `ready_mobile${is_eu ? '_eu' : ''}`
: `ready_desktop${is_eu ? '_eu' : ''}`;
const title_size = isMobile() ? 'xs' : 'sm';
const description_size = isMobile() ? 'xxxs' : 'xs';
const tick_size = isMobile() ? 16 : 24;

const onButtonClickHandler = async () => {
await logout();
};

return (
<div className='wallets-banner__container wallets-banner__ready-banner'>
<div className='wallets-banner__ready-banner-description'>
<div className='wallets-banner__ready-banner-tick' data-testid='dt_wallets-ready-tick'>
<Icon icon='IcAppstoreTickWhite' size={tick_size} />
</div>
<Localize
i18n_default_text='<0>Your Wallets are ready</0>'
components={[<Text key={0} weight='bold' size={title_size} />]}
/>
<Localize
i18n_default_text='<0>To complete the upgrade, please log out and log in again to add more accounts and make transactions with your Wallets.</0>'
components={[<Text key={0} size={description_size} />]}
/>
<Button
onClick={onButtonClickHandler}
className='wallets-banner__ready-banner-button'
has_effect
text={localize('Log out')}
primary
large={!isMobile()}
/>
</div>
<WalletsImage image={image} className='wallets-banner__image wallets-banner__ready-banner-image' />
</div>
);
};

export default WalletsBannerReady;
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import WalletsImage from 'Assets/svgs/wallets';
import { Button, Text } from '@deriv/components';
import { Localize, localize } from '@deriv/translations';
import { isMobile } from '@deriv/shared';
import { TWalletsImagesListKeys } from 'Assets/svgs/wallets/image-types';

const WalletsBannerUpgrade = () => {
const image: TWalletsImagesListKeys = isMobile() ? 'upgrade_mobile' : 'upgrade_desktop';
const size: string = isMobile() ? 'xs' : 'm';

return (
<div className='wallets-banner__container wallets-banner__upgrade-banner'>
<div className='wallets-banner__upgrade-banner-description'>
<div>
<Localize
i18n_default_text='<0>Wallets</0><1> — the best way to organise your funds</1>'
components={[<Text key={0} weight='bold' size={size} />, <Text key={1} size={size} />]}
/>
</div>
<Button
// Onclick props will be added here to show the upgrade wallets wizard in stitching user story
className='wallets-banner__upgrade-banner-button'
has_effect
text={localize('Upgrade now')}
primary
large={!isMobile()}
/>
</div>
<WalletsImage image={image} className='wallets-banner__image' />
</div>
);
};

export default WalletsBannerUpgrade;
Loading

0 comments on commit 9fd7089

Please sign in to comment.