Skip to content

Commit

Permalink
accounts/refactor: ♻️ container section in accounts package (deriv-co…
Browse files Browse the repository at this point in the history
…m#9832)

* refactor: ♻️ initial commit

* refactor: 🎨 fixed import file paths

* fix: 🧑‍💻 incorporate sonarcloud review

* refactor: ♻️ migrated reset-trading-password component to TSX

* refactor: 🎨 resolved build failure

* fix: ♻️ incorporated lint errors

* fix: 🎨 incorporated review comments

* fix: 🐛 resize issue

* refactor: 🎨 migrated account component to TSX (#47)

* refactor: 🎨 migrated account component to TSX

* fix: 🎨 refactored code

* refactor: 🎨 migrated account to tsx

* fix: 🎨 incorporated review comments

* chore: 💚 trigger empty commit

* fix: 🧪 failing testcase

* fix: 🐛 resolve password modal API failure

* fix: 🐛 bug regd disabled Financial Assessment

* fix: 🚚 updated paths

* Merge branch 'master' into sprint-9/account-package-refactor
  • Loading branch information
likhith-deriv authored Sep 22, 2023
1 parent f1822ae commit c39e179
Show file tree
Hide file tree
Showing 30 changed files with 522 additions and 288 deletions.
6 changes: 2 additions & 4 deletions packages/account/src/Components/Routes/binary-link.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import { NavLink } from 'react-router-dom';
import { PlatformContext } from '@deriv/shared';
import getRoutesConfig from 'Constants/routes-config';
import getRoutesConfig from '../../Constants/routes-config';
import { findRouteByPath, normalizePath } from './helpers';

type TBinaryLink = {
Expand All @@ -10,9 +9,8 @@ type TBinaryLink = {
};

const BinaryLink = ({ active_class, to, children, ...props }: React.PropsWithChildren<Partial<TBinaryLink>>) => {
const { is_appstore } = React.useContext(PlatformContext);
const path = normalizePath(to as string);
const route = findRouteByPath(path, getRoutesConfig({ is_appstore }));
const route = findRouteByPath(path, getRoutesConfig());

if (!route) {
throw new Error(`Route not found: ${to}`);
Expand Down
9 changes: 3 additions & 6 deletions packages/account/src/Components/Routes/binary-routes.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import React from 'react';
import { Switch } from 'react-router-dom';
import { PlatformContext } from '@deriv/shared';
import { Localize } from '@deriv/translations';
import getRoutesConfig from 'Constants/routes-config';
import { TBinaryRoutes, TRoute } from 'Types';
import getRoutesConfig from '../../Constants/routes-config';
import { TBinaryRoutes, TRoute } from '../../Types';
import RouteWithSubRoutes from './route-with-sub-routes';

const BinaryRoutes = (props: TBinaryRoutes) => {
const { is_appstore } = React.useContext(PlatformContext);

return (
<React.Suspense
fallback={
Expand All @@ -18,7 +15,7 @@ const BinaryRoutes = (props: TBinaryRoutes) => {
}
>
<Switch>
{getRoutesConfig({ is_appstore }).map((route: TRoute, idx: number) => (
{getRoutesConfig().map((route: TRoute, idx: number) => (
<RouteWithSubRoutes key={idx} {...route} {...props} />
))}
</Switch>
Expand Down
2 changes: 1 addition & 1 deletion packages/account/src/Components/Routes/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { match, matchPath, RouteProps } from 'react-router';
import { routes } from '@deriv/shared';
import { TRouteConfig } from 'Types';
import { TRouteConfig } from '../../Types';

export const normalizePath = (path: string) => (path.startsWith('/') ? path : `/${path || ''}`); // Default to '/'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
default_title,
} from '@deriv/shared';
import { getLanguage } from '@deriv/translations';
import { TBinaryRoutes, TRoute, TRouteConfig } from 'Types';
import { TBinaryRoutes, TRoute, TRouteConfig } from '../../Types';

type TRouteWithSubRoutesProps = TRouteConfig & TBinaryRoutes;

Expand All @@ -32,9 +32,9 @@ const RouteWithSubRoutes = (route: TRouteWithSubRoutesProps) => {
redirectToLogin(route.is_logged_in, getLanguage());
} else {
const default_subroute: TRoute = (route.routes ?? []).reduce(
(acc, cur) => ({
(acc: TRoute, cur: TRoute) => ({
...acc,
...cur.subroutes?.find(subroute => subroute.default),
...cur.subroutes?.find((subroute: TRoute) => subroute.default),
}),
{}
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from 'react';
import { PageError } from '@deriv/components';
import { localize } from '@deriv/translations';
import { Localize } from '@deriv/translations';
import { routes } from '@deriv/shared';

type TErrorComponent = {
header: React.ReactElement;
message: React.ReactNode;
redirect_label: React.ReactElement;
redirectOnClick: () => void;
header: JSX.Element | string;
message: JSX.Element | string;
redirect_label: string;
redirectOnClick: (() => void) | null;
should_show_refresh: boolean;
};

Expand All @@ -18,18 +18,28 @@ const ErrorComponent = ({
redirectOnClick,
should_show_refresh = true,
}: Partial<TErrorComponent>) => {
const refresh_message: string = should_show_refresh ? localize('Please refresh this page to continue.') : '';
const refresh_message: JSX.Element | string = should_show_refresh ? (
<Localize i18n_default_text='Please refresh this page to continue.' />
) : (
''
);

return (
<PageError
header={header || localize('Oops, something went wrong.')}
header={header || <Localize i18n_default_text='Oops, something went wrong.' />}
messages={
message
? [message, refresh_message]
: [localize('Sorry, an error occured while processing your request.'), refresh_message]
: [
<Localize
i18n_default_text='Sorry, an error occurred while processing your request.'
key={0}
/>,
refresh_message,
]
}
redirect_urls={[routes.trade]}
redirect_labels={[redirect_label || localize('Refresh')]}
redirect_labels={[redirect_label ?? <Localize i18n_default_text='Refresh' />]}
buttonOnClick={redirectOnClick ?? (() => location.reload())}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import {
} from '@deriv/components';
import { getLegalEntityName, isDesktop, isMobile, routes, validPhone } from '@deriv/shared';
import { Localize, localize } from '@deriv/translations';
import FormSubHeader from '../form-sub-header';
import PoiNameDobExample from '../../Assets/ic-poi-name-dob-example.svg';
import InlineNoteWithIcon from '../inline-note-with-icon';
import FormBodySection from '../form-body-section';
import { DateOfBirthField, FormInputField } from './form-fields.jsx';
import FormBodySection from '../form-body-section';
import FormSubHeader from '../form-sub-header';
import PoiNameDobExample from '../../Assets/ic-poi-name-dob-example.svg';
import { getEmploymentStatusList } from '../../Sections/Assessment/FinancialAssessment/financial-information-list';
import { isFieldImmutable } from '../../Helpers/utils';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React, { ChangeEvent } from 'react';
import PropTypes from 'prop-types';
import { Formik, Form, FormikValues, FormikErrors } from 'formik';
import { useHistory } from 'react-router-dom';
import { Button, Dialog, Icon, PasswordInput, PasswordMeter, Text, FormSubmitButton } from '@deriv/components';
import { getErrorMessages, validPassword, validLength, WS, getCFDPlatformLabel } from '@deriv/shared';
import { localize, Localize } from '@deriv/translations';
import { TPlatforms } from '../../Types';
import './reset-trading-password-modal.scss';

type TResetTradingPassword = {
setDialogTitleFunc?: (value: boolean) => void;
toggleResetTradingPasswordModal: (value: boolean) => void;
verification_code: string;
platform: 'dxtrade' | 'mt5' | 'derivez';
platform: TPlatforms;
};

const ResetTradingPassword = ({
Expand Down Expand Up @@ -249,13 +249,3 @@ export const ResetTradingPasswordModal = ({
</Dialog>
);
};

ResetTradingPasswordModal.propTypes = {
disableApp: PropTypes.func,
enableApp: PropTypes.func,
is_loading: PropTypes.bool,
is_visible: PropTypes.bool,
toggleResetTradingPasswordModal: PropTypes.func,
verification_code: PropTypes.string,
platform: PropTypes.string,
};
38 changes: 12 additions & 26 deletions packages/account/src/Constants/routes-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
const Page404 = React.lazy(() => moduleLoader(() => import(/* webpackChunkName: "404" */ 'Modules/Page404')));

// Order matters
const initRoutesConfig = ({ is_appstore }) => [
const initRoutesConfig = () => [
{
path: routes.account_closed,
component: AccountClosed,
Expand Down Expand Up @@ -112,27 +112,25 @@ const initRoutesConfig = ({ is_appstore }) => [
{
path: routes.self_exclusion,
component: SelfExclusion,
getTitle: () => (is_appstore ? localize('Self-exclusion') : localize('Self exclusion')),
getTitle: () => localize('Self exclusion'),
},
{
path: routes.account_limits,
component: AccountLimits,
getTitle: () => (is_appstore ? localize('Withdrawal limits') : localize('Account limits')),
getTitle: () => localize('Account limits'),
},
{
path: routes.login_history,
component: LoginHistory,
getTitle: () => localize('Login history'),
},
...(is_appstore
? []
: [
{
path: routes.api_token,
component: ApiToken,
getTitle: () => localize('API token'),
},
]),
...[
{
path: routes.api_token,
component: ApiToken,
getTitle: () => localize('API token'),
},
],
{
path: routes.connected_apps,
component: ConnectedApps,
Expand All @@ -150,18 +148,6 @@ const initRoutesConfig = ({ is_appstore }) => [
},
],
},
// TO DO -- Please remove these comments after changing for dashboard routes
// It is possible to add a Deriv Dashboard only path.
// ...(is_appstore
// ? [
// {
// component: Home,
// getTitle: () => localize('Dashboard-only path'),
// is_authenticated: false,
// path: routes.resources,
// },
// ]
// : []),
],
},
];
Expand All @@ -171,9 +157,9 @@ let routesConfig;
// 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 getRoutesConfig = ({ is_appstore }) => {
const getRoutesConfig = () => {
if (!routesConfig) {
routesConfig = initRoutesConfig({ is_appstore });
routesConfig = initRoutesConfig();
routesConfig.push(route_default);
}
return routesConfig;
Expand Down
75 changes: 75 additions & 0 deletions packages/account/src/Containers/Account/__tests__/account.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from 'react';
import { MemoryRouter, BrowserRouter } from 'react-router-dom';
import { render, screen } from '@testing-library/react';
import { StoreProvider, mockStore } from '@deriv/stores';
import { routes } from '@deriv/shared';
import { TRoute } from 'Types';
import Account from '../account';

jest.mock('../../Account/page-overlay-wrapper', () => jest.fn(() => <div>MockPageOverlayWrapper</div>));

jest.mock('@deriv/components', () => ({
...jest.requireActual('@deriv/components'),
Loading: () => <div>MockLoading</div>,
}));

describe('Account', () => {
const store = mockStore({
ui: {
is_account_settings_visible: true,
},
});

const route_list: Array<TRoute> = [
{
getTitle: () => 'Profile',
icon: 'mockIcon',
subroutes: [
{
path: routes.personal_details,
component: () => <div>MockPersonalDetails</div>,
getTitle: () => 'Personal details',
default: true,
},
{
path: routes.trading_assessment,
component: () => <div>MockTradeAssessment</div>,
getTitle: () => 'Trade assessment',
},
],
},
];

const mock_props: React.ComponentProps<typeof Account> = {
routes: route_list,
};

const mock_route = routes.personal_details;

const renderComponent = ({ store_config = store, route = mock_route, props = mock_props }) =>
render(
<MemoryRouter initialEntries={[route]}>
<StoreProvider store={store_config}>
<BrowserRouter>
<Account {...props} />
</BrowserRouter>
</StoreProvider>
</MemoryRouter>
);

it('should render account page', () => {
renderComponent({});
expect(screen.getByText('MockPageOverlayWrapper')).toBeInTheDocument();
});

it('should render loader while the client is still logging in', () => {
const new_store_config = mockStore({
client: {
is_logging_in: true,
},
});

renderComponent({ store_config: new_store_config });
expect(screen.getByText('MockLoading')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import TradingHubLogout from '../tradinghub-logout';

describe('TradingHubLogout', () => {
const mock_props: React.ComponentProps<typeof TradingHubLogout> = {
handleOnLogout: jest.fn(),
};

it('should render logout tab', () => {
render(<TradingHubLogout {...mock_props} />);
expect(screen.getByText('Log out')).toBeInTheDocument();
});

it('should invoke handleOnLogout when logout tab is clicked', () => {
render(<TradingHubLogout {...mock_props} />);
const el_tab = screen.getByTestId('dt_logout_tab');
userEvent.click(el_tab);
expect(mock_props.handleOnLogout).toBeCalledTimes(1);
});
});
Loading

0 comments on commit c39e179

Please sign in to comment.