Skip to content

Commit

Permalink
george / rm65047 / convert routes, cashier, error-component component…
Browse files Browse the repository at this point in the history
…s to TS (#6361)

* perf(cashier routes): convert csahier routes to TS

* perf(cashier routes): convert error-component to TS

* refactor(error-dialog, types): refactor error-dialog types, move error type to shared types

* perf(cashier): convert cashier to TS

* perf(types): refactor types

* refactor(routes with sub routes): refactor default subroute

* refactor(types): add/refactor server error type

* test: refactor pathname

* refactor(route types): refactor route types

* fix: fix ts error in React.Suspense
  • Loading branch information
heorhi-deriv authored Sep 6, 2022
1 parent fa1fad5 commit 3e5a76d
Show file tree
Hide file tree
Showing 28 changed files with 246 additions and 183 deletions.
22 changes: 9 additions & 13 deletions packages/cashier/src/components/error-dialog/error-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@ import { Dialog } from '@deriv/components';
import { localize, Localize } from '@deriv/translations';
import { routes } from '@deriv/shared';
import { connect } from 'Stores/connect';
import { RootStore, TReactElement } from 'Types';
import { RootStore, TError, TReactElement } from 'Types';

type TErrorDialogProps = {
disableApp: () => void;
enableApp: () => void;
error: {
message?: string;
code?: string;
setErrorMessage?: (message: string) => void;
};
error: TError | Record<string, never>;
};

type TSetDetails = {
Expand All @@ -36,6 +32,13 @@ const ErrorDialog = ({ disableApp, enableApp, error = {} }: TErrorDialogProps) =
message: '',
});

const dismissError = React.useCallback(() => {
if (error.setErrorMessage) {
error.setErrorMessage('', null, false);
}
setErrorVisibility(false);
}, [error]);

const mapErrorToDetails = React.useCallback(
(error_code?: string, error_message?: string) => {
if (
Expand Down Expand Up @@ -118,13 +121,6 @@ const ErrorDialog = ({ disableApp, enableApp, error = {} }: TErrorDialogProps) =
setIsVisible(is_error_visible);
};

const dismissError = React.useCallback(() => {
if (error.setErrorMessage) {
error.setErrorMessage('');
}
setErrorVisibility(false);
}, [error]);

return (
<Dialog
title={details.title}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { routes, moduleLoader } from '@deriv/shared';
import { localize } from '@deriv/translations';
import { Cashier } from '../containers';
import { AccountTransfer, Deposit, OnRamp, P2PCashier, PaymentAgent, PaymentAgentTransfer, Withdrawal } from '../pages';
import { TRouteConfig, TRoute } from 'Types';

// Error Routes
const Page404 = React.lazy(() => moduleLoader(() => import(/* webpackChunkName: "404" */ 'Components/page-404')));
export type TPage404 = typeof Page404;

// Order matters
const initRoutesConfig = () => [
const initRoutesConfig = (): TRouteConfig[] => [
{
path: routes.cashier,
component: Cashier,
Expand Down Expand Up @@ -72,14 +74,14 @@ const initRoutesConfig = () => [
},
];

let routesConfig;
let routesConfig: undefined | TRouteConfig[];

// For default page route if page/path is not found, must be kept at the end of routes_config array
const route_default = { component: Page404, getTitle: () => localize('Error 404') };
const route_default: TRoute = { component: Page404, getTitle: () => localize('Error 404') };

const getRoutesConfig = ({ is_appstore }) => {
const getRoutesConfig = (): TRouteConfig[] => {
if (!routesConfig) {
routesConfig = initRoutesConfig({ is_appstore });
routesConfig = initRoutesConfig();
routesConfig.push(route_default);
}
return routesConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { createBrowserHistory } from 'history';
import { Router } from 'react-router';
import { isMobile } from '@deriv/shared';
import getRoutesConfig from 'Constants/routes-config';
import Cashier from '../cashier.jsx';
import Cashier from '../cashier';

jest.mock('Stores/connect', () => ({
__esModule: true,
Expand Down Expand Up @@ -58,7 +58,7 @@ describe('<Cashier />', () => {
is_p2p_enabled: true,
is_onramp_tab_visible: true,
is_visible: true,
routes: getRoutesConfig({})[0].routes,
routes: getRoutesConfig()[0].routes,
routeBackInApp: jest.fn(),
onMount: jest.fn(),
setAccountSwitchListener: jest.fn(),
Expand Down Expand Up @@ -121,7 +121,7 @@ describe('<Cashier />', () => {
});

it('should show the selected route page on mobile', () => {
isMobile.mockReturnValue(true);
(isMobile as jest.Mock).mockReturnValue(true);

renderWithRouter(<Cashier {...props} />);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import { RouteComponentProps } from 'react-router';
import { withRouter } from 'react-router-dom';
import {
Button,
Expand All @@ -11,13 +11,50 @@ import {
VerticalTab,
Loading,
} from '@deriv/components';
import { localize } from '@deriv/translations';
import { getSelectedRoute, getStaticUrl, isMobile, routes, WS } from '@deriv/shared';
import { connect } from 'Stores/connect';
import { localize } from '@deriv/translations';
import AccountPromptDialog from 'Components/account-prompt-dialog';
import ErrorDialog from 'Components/error-dialog';
import { connect } from 'Stores/connect';
import { TClientStore, TCommonStore, TError, TRootStore, TRoute, TUiStore } from 'Types';
import './cashier.scss';

type TCashierProps = RouteComponentProps & {
error: TError;
is_account_transfer_visible: boolean;
is_account_setting_loaded: TClientStore['is_account_setting_loaded'];
is_cashier_onboarding: boolean;
is_crypto: boolean;
is_crypto_transactions_visible: boolean;
is_loading: boolean;
is_logged_in: TClientStore['is_logged_in'];
is_logging_in: TClientStore['is_logging_in'];
is_from_derivgo: TCommonStore['is_from_derivgo'];
is_onramp_tab_visible: boolean;
is_p2p_enabled: boolean;
is_payment_agent_transfer_visible: boolean;
is_payment_agent_visible: boolean;
is_visible: TUiStore['is_cashier_visible'];
p2p_notification_count: number;
routes: TRoute[];
tab_index: number;
onMount: (should_remount?: boolean) => void;
setAccountSwitchListener: () => void;
setTabIndex: (index: number) => void;
routeBackInApp: TCommonStore['routeBackInApp'];
toggleCashier: TUiStore['toggleCashier'];
};

type TCashierOptions = {
count?: number;
default?: boolean;
has_side_note: boolean;
icon?: string;
label: string;
path?: string;
value: TRoute['component'];
};

const Cashier = ({
error,
history,
Expand Down Expand Up @@ -45,7 +82,7 @@ const Cashier = ({
setTabIndex,
tab_index,
toggleCashier,
}) => {
}: TCashierProps) => {
React.useEffect(() => {
toggleCashier();
// we still need to populate the tabs shown on cashier
Expand All @@ -65,7 +102,7 @@ const Cashier = ({

const onClickClose = () => routeBackInApp(history);
const getMenuOptions = () => {
const options = [];
const options: TCashierOptions[] = [];
routes_config.forEach(route => {
if (
!route.is_invisible &&
Expand Down Expand Up @@ -179,36 +216,7 @@ const Cashier = ({
);
};

Cashier.propTypes = {
error: PropTypes.object,
history: PropTypes.object,
is_account_transfer_visible: PropTypes.bool,
is_account_setting_loaded: PropTypes.bool,
is_cashier_onboarding: PropTypes.bool,
is_crypto: PropTypes.bool,
is_crypto_transactions_visible: PropTypes.bool,
is_loading: PropTypes.bool,
is_logged_in: PropTypes.bool,
is_logging_in: PropTypes.bool,
is_from_derivgo: PropTypes.bool,
is_onramp_tab_visible: PropTypes.bool,
is_p2p_enabled: PropTypes.bool,
is_payment_agent_transfer_visible: PropTypes.bool,
is_payment_agent_visible: PropTypes.bool,
is_virtual: PropTypes.bool,
is_visible: PropTypes.bool,
location: PropTypes.object,
onMount: PropTypes.func,
p2p_notification_count: PropTypes.number,
routeBackInApp: PropTypes.func,
routes: PropTypes.arrayOf(PropTypes.object),
setAccountSwitchListener: PropTypes.func,
setTabIndex: PropTypes.func,
tab_index: PropTypes.number,
toggleCashier: PropTypes.func,
};

export default connect(({ client, common, modules, ui }) => ({
export default connect(({ client, common, modules, ui }: TRootStore) => ({
error: modules.cashier.withdraw.error,
is_cashier_onboarding: modules.cashier.general_store.is_cashier_onboarding,
is_account_transfer_visible: modules.cashier.account_transfer.is_account_transfer_visible,
Expand Down
3 changes: 0 additions & 3 deletions packages/cashier/src/containers/cashier/index.js

This file was deleted.

3 changes: 3 additions & 0 deletions packages/cashier/src/containers/cashier/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Cashier from './cashier';

export default Cashier;
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { expect } from 'chai';
import { configure, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { RouteWithSubRoutesRender } from '../route-with-sub-routes.jsx';
import { RouteWithSubRoutesRender } from '../route-with-sub-routes';
import { Redirect } from 'react-router-dom';

configure({ adapter: new Adapter() });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jest.mock('Stores/connect.js', () => ({
connect: () => Component => Component,
}));

jest.mock('../binary-routes', () => () => <div>BinaryRoutes</div>);
jest.mock('../binary-routes', () => jest.fn(() => 'BinaryRoutes'));

describe('<Routes />', () => {
it('should show error messages when "has_error = true"', () => {
Expand Down
29 changes: 0 additions & 29 deletions packages/cashier/src/containers/routes/binary-routes.jsx

This file was deleted.

32 changes: 32 additions & 0 deletions packages/cashier/src/containers/routes/binary-routes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import { Switch } from 'react-router-dom';
import { Localize } from '@deriv/shared';
import getRoutesConfig from 'Constants/routes-config';
import RouteWithSubRoutes from './route-with-sub-routes';

type TBinaryRoutesProps = {
is_logged_in: boolean;
is_logging_in: boolean;
};

const Loading = () => {
return (
<div>
<Localize i18n_default_text='Loading...' />
</div>
);
};

const BinaryRoutes = (props: TBinaryRoutesProps) => {
return (
<React.Suspense fallback={<Loading />}>
<Switch>
{getRoutesConfig().map((route, idx: number) => (
<RouteWithSubRoutes key={idx} {...route} {...props} />
))}
</Switch>
</React.Suspense>
);
};

export default BinaryRoutes;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { screen, render, fireEvent } from '@testing-library/react';
import ErrorComponent from '../error-component.jsx';
import ErrorComponent from '../error-component';
import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';

Expand All @@ -11,7 +11,7 @@ describe('<ErrorComponent/>', () => {
return render(<Router history={history}>{component}</Router>);
};
const reloadFn = () => {
window.location.reload(true);
window.location.reload();
};
beforeAll(() => {
Object.defineProperty(window, 'location', {
Expand Down Expand Up @@ -40,7 +40,7 @@ describe('<ErrorComponent/>', () => {
it('do not show refresh message when should_show_refresh is false', () => {
const refreshRequestText = screen.queryByText('Please refresh this page to continue.');
renderWithRouter(<ErrorComponent {...props} should_show_refresh={false} />);
expect(refreshRequestText).toBeNull();
expect(refreshRequestText).not.toBeInTheDocument();
});
it('should show default message when header message is not passed', () => {
const header = '';
Expand All @@ -66,13 +66,9 @@ describe('<ErrorComponent/>', () => {
});
it('should trigger the history.listen and call the setError function when redirect button get clicked', () => {
const redirectOnClick = jest.fn();
const history = createBrowserHistory();
const setError = jest.fn();
render(
<Router history={history}>
<ErrorComponent {...props} buttonOnClick={redirectOnClick} setError={setError} />
</Router>
);
renderWithRouter(<ErrorComponent {...props} buttonOnClick={redirectOnClick} setError={setError} />);

fireEvent.click(screen.getByText('testlabel'));
if (typeof setError === 'function') {
expect(setError).toHaveBeenCalledTimes(1);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import PropTypes from 'prop-types';
import React from 'react';
import { useHistory } from 'react-router-dom';
import { PageError } from '@deriv/components';
import { routes } from '@deriv/shared';
import { Localize } from '@deriv/translations';
import { TCommonStore } from 'Types';

const ErrorComponent = ({
header,
Expand All @@ -14,7 +14,7 @@ const ErrorComponent = ({
setError,
redirect_to = routes.trade,
should_show_refresh = true,
}) => {
}: TCommonStore['error']) => {
const history = useHistory();

React.useEffect(() => {
Expand Down Expand Up @@ -55,16 +55,4 @@ const ErrorComponent = ({
);
};

ErrorComponent.propTypes = {
header: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
message: PropTypes.oneOfType([PropTypes.node, PropTypes.string, PropTypes.object]),
redirect_label: PropTypes.string,
redirect_to: PropTypes.string,
redirectOnClick: PropTypes.func,
setError: PropTypes.func,
should_clear_error_on_click: PropTypes.bool,
should_show_refresh: PropTypes.bool,
type: PropTypes.string,
};

export default ErrorComponent;

This file was deleted.

Loading

1 comment on commit 3e5a76d

@vercel
Copy link

@vercel vercel bot commented on 3e5a76d Sep 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

deriv-app – ./

deriv-app.vercel.app
deriv-app.binary.sx
binary.sx
deriv-app-git-master.binary.sx

Please sign in to comment.