Skip to content

Commit

Permalink
accounts package ts migration and refactor - sprint 8 (deriv-com#9791)
Browse files Browse the repository at this point in the history
* fix: ⚡ refactored Address-details component

* fix: 🎨 failing testcases

* refactor: ♻️ incorporated review comments

* feat: 🔥 removed PlatformContext

* fix: testcase failure

* refactor: ♻️ incorporated review comments

* refactor: ♻️ refactor component to remove unwanted code (deriv-com#44)

* refactor: ♻️ refactor component to remove unwanted code

* feat: removed commented code

* test: ✅ added testcase

* test: 🧪 added tests

* refactor: ♻️ incorporated review comments

* refactor: ♻️ incorporated review comments

* refactor: ♻️ incorporated review comments

* refactor: ♻️ migrated code to TS (deriv-com#45)

* refactor: ♻️ migrated code to TS

* refactor: ♻️ incorporated review comments

* refactor: ♻️ incorporated review comments

* Update packages/account/src/Types/common-prop.type.ts

Co-authored-by: yauheni-deriv <103182683+yauheni-deriv@users.noreply.github.com>

---------

Co-authored-by: yauheni-deriv <103182683+yauheni-deriv@users.noreply.github.com>

* refactor: ⚡ refactored currency selector component (deriv-com#43)

* refactor: ⚡ refactored currency selector component

* fix: 🚨 lint errors

* feat: incorporated store values

* fix: 🎨 split code into small components

* fix: 🎨 removed un-necessary array

* refactor: ♻️ incorporated review comments

* refactor: ♻️ incorporated review comments

* resolved failing test cases

* chore: incorporated review comment

* fix: build issue

* fix: build issue

* ref: incorporated review comments

* refactor: Modified code to contain hooks

* refactor: Modified code to contain hooks

* replaced test component

* fix: eslint issues

* fix: failing testcases

* ref: Incorporated review somments

* Likhith/webrel 780/migrate Email and password section (#7)

* chore: migrated deriv-email and unlink component

* chore: migrate password-platform to tsx

* chore: migrate password-platform to tsx

* chore: added missing test cases

* ref: incorporated review comments

* refactor: incorporated review comments

* refactor: incorporated review comments

* refactor: incorporated review comments

* ref: Incorporated review somments

* chore: config files ts migration and refactor (#8)

* chore: config files ts migartion and refactor

* refactor: test case for config func

* fix: config typing

* refactor: remove custom accounts residence type

* refactor: review comment

* chore: added test cases

* fix: revert boolean in types

* refactor: default value fields

* refactor: files types, import react types

* refactor: react types

* fix: condition rule

* fix: failing testcase

---------

Co-authored-by: “yauheni-kryzhyk-deriv” <“yauheni@deriv.me”>

* fix: incorporated review comments

* fix: failing testcase

* refactor: migrate form-fields file (#10)

* refactor: migrate form-fields file

* refactor: migrate form-fields file

* ref: incorporated review comments

* fix: failing testcase

* fix: incorporated review comments

* fix: incorporated review comments

* fix: incorporated review comments

* fix: resolved Sonar lint errors

* fix: tslint issues

* fix: review comments

* fix: review comments

* refactor: 🎨 incorporated types for test cases

* fix: 🦺 incorporated review comments

* fix: 🎨 incorporated ui-store-fix

* fix: ⚰️ replaced deprecated hooks

* fix: 🔥 unused dependency

* Merge branch 'master' into KYC-accounts-package-TS-migration--test-coverage/sprint-8

* chore: added package-lock

* fix: added value for mock-store

---------

Co-authored-by: yauheni-deriv <103182683+yauheni-deriv@users.noreply.github.com>
Co-authored-by: “yauheni-kryzhyk-deriv” <“yauheni@deriv.me”>
Co-authored-by: Shahzaib <shahzaib@deriv.com>
  • Loading branch information
4 people authored Oct 4, 2023
1 parent 06d4f73 commit c2e6360
Show file tree
Hide file tree
Showing 92 changed files with 2,750 additions and 3,270 deletions.
1 change: 1 addition & 0 deletions packages/account/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
},
"dependencies": {
"@binary-com/binary-document-uploader": "^2.4.8",
"@deriv/api": "^1.0.0",
"@deriv/api-types": "^1.0.118",
"@deriv/components": "^1.0.0",
"@deriv/hooks": "^1.0.0",
Expand Down
17 changes: 9 additions & 8 deletions packages/account/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import Routes from './Containers/routes';
import ResetTradingPassword from './Containers/reset-trading-password';
import { setWebsocket } from '@deriv/shared';
import { APIProvider } from '@deriv/api';
import { StoreProvider } from '@deriv/stores';
import type { TCoreStores } from '@deriv/stores/types';

Expand All @@ -14,17 +14,18 @@ type TAppProps = {
};

const App = ({ passthrough }: TAppProps) => {
const { root_store, WS } = passthrough;
setWebsocket(WS);
const { root_store } = passthrough;

const { notification_messages_ui: Notifications } = root_store.ui;

return (
<StoreProvider store={root_store}>
{Notifications && <Notifications />}
<Routes />
<ResetTradingPassword />
</StoreProvider>
<APIProvider>
<StoreProvider store={root_store}>
{Notifications && <Notifications />}
<Routes />
<ResetTradingPassword />
</StoreProvider>
</APIProvider>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React from 'react';
import { FormikProps, FormikValues } from 'formik';
import { FormikProps } from 'formik';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { isDesktop, isMobile, PlatformContext } from '@deriv/shared';
import AddressDetails from '../address-details';
import { useStatesList } from '@deriv/hooks';
import { isDesktop, isMobile } from '@deriv/shared';
import { StoreProvider, mockStore } from '@deriv/stores';
import AddressDetails, { TAddressDetailFormProps } from '../address-details';
import { TStores } from '@deriv/stores/types';

jest.mock('@deriv/shared', () => ({
...jest.requireActual('@deriv/shared'),
Expand All @@ -19,6 +22,11 @@ jest.mock('../../real-account-signup/helpers/utils.ts', () => ({
})),
}));

jest.mock('@deriv/hooks', () => ({
...jest.requireActual('@deriv/hooks'),
useStatesList: jest.fn(() => ({ data: [], isFetched: true })),
}));

jest.mock('@deriv/components', () => {
const original_module = jest.requireActual('@deriv/components');

Expand All @@ -45,19 +53,16 @@ describe('<AddressDetails/>', () => {
let modal_root_el: HTMLDivElement;

const mock_props: React.ComponentProps<typeof AddressDetails> = {
fetchStatesList: jest.fn(() => Promise.resolve([])),
getCurrentStep: jest.fn(),
goToNextStep: jest.fn(),
goToPreviousStep: jest.fn(),
has_real_account: false,
is_gb_residence: '',
is_svg: true,
onCancel: jest.fn(),
onSave: jest.fn(),
onSubmit: jest.fn(),
onSubmitEnabledChange: jest.fn(),
selected_step_ref: { current: { isSubmitting: false } } as React.RefObject<FormikProps<FormikValues>>,
states_list: [],
selected_step_ref: { current: { isSubmitting: false } } as React.RefObject<
FormikProps<TAddressDetailFormProps>
>,
value: {
address_city: '',
address_line_1: '',
Expand All @@ -67,10 +72,12 @@ describe('<AddressDetails/>', () => {
},
validate: jest.fn(),
disabled_items: [],
has_real_account: false,
};

const store = mockStore({});

const svgCommonRenderCheck = () => {
expect(mock_props.onSubmitEnabledChange).toHaveBeenCalledTimes(1);
expect(screen.getByLabelText(address_line_1_marked)).toBeInTheDocument();
expect(screen.getByLabelText(address_line_2)).toBeInTheDocument();
expect(screen.getByLabelText(address_postcode)).toBeInTheDocument();
Expand All @@ -84,6 +91,14 @@ describe('<AddressDetails/>', () => {
expect(screen.queryByLabelText(address_town)).not.toBeInTheDocument();
};

const renderComponent = ({ props = mock_props, store_config = store }) => {
return render(
<StoreProvider store={store_config}>
<AddressDetails {...props} />
</StoreProvider>
);
};

beforeEach(() => {
(isDesktop as jest.Mock).mockReturnValue(true);
(isMobile as jest.Mock).mockReturnValue(false);
Expand All @@ -101,10 +116,15 @@ describe('<AddressDetails/>', () => {
});

it('should render AddressDetails component for mobile', async () => {
(isDesktop as jest.Mock).mockReturnValue(false);
(isMobile as jest.Mock).mockReturnValue(true);
const new_store_config: TStores = {
...store,
ui: {
...store.ui,
is_mobile: true,
},
};

render(<AddressDetails {...mock_props} />);
renderComponent({ store_config: new_store_config });

await waitFor(() => {
svgCommonRenderCheck();
Expand All @@ -117,33 +137,18 @@ describe('<AddressDetails/>', () => {
expect(required_fields).toHaveLength(2);
});

it('should call fetchResidenceList if states list is empty', async () => {
render(<AddressDetails {...mock_props} />);
expect(mock_props.fetchStatesList).toHaveBeenCalled();
});

it('should not call fetchResidenceList if states list is empty', async () => {
render(
<AddressDetails
{...mock_props}
states_list={[
{ text: 'State 1', value: 'State 1' },
{ text: 'State 2', value: 'State 2' },
]}
/>
);

expect(mock_props.fetchStatesList).not.toHaveBeenCalled();
expect(screen.queryByText('mockedLoading')).not.toBeInTheDocument();
});

it('should show a loader when states list is not fully fetched', async () => {
render(<AddressDetails {...mock_props} states_list={[]} />);
(useStatesList as jest.Mock).mockReturnValue({
data: [],
isFetched: false,
});

renderComponent({});
expect(screen.getByText('mockedLoading')).toBeInTheDocument();
});

it('should render AddressDetails component and trigger buttons', async () => {
render(<AddressDetails {...mock_props} />);
renderComponent({});

await waitFor(() => {
svgCommonRenderCheck();
Expand Down Expand Up @@ -202,80 +207,26 @@ describe('<AddressDetails/>', () => {
});
});

it('should render AddressDetails component not svg', async () => {
mock_props.is_svg = false;

render(<AddressDetails {...mock_props} />);

expect(mock_props.onSubmitEnabledChange).toHaveBeenCalledTimes(1);

const inputs: HTMLTextAreaElement[] = screen.getAllByRole('textbox');
expect(inputs).toHaveLength(5);
const required_fields = inputs.filter(input => input.required === true);
expect(required_fields).toHaveLength(0);

await waitFor(() => {
expect(screen.getByLabelText(address_line_1)).toBeInTheDocument();
expect(screen.getByLabelText(address_line_2)).toBeInTheDocument();
expect(screen.getByLabelText(address_postcode)).toBeInTheDocument();
expect(screen.getByLabelText(address_state)).toBeInTheDocument();
expect(screen.getByLabelText(address_town)).toBeInTheDocument();
expect(screen.getByText(use_address_info)).toBeInTheDocument();
});

expect(screen.queryByText(address_line_1_marked)).not.toBeInTheDocument();
expect(screen.queryByText(address_line_2_marked)).not.toBeInTheDocument();
expect(screen.queryByText(address_postcode_marked)).not.toBeInTheDocument();
expect(screen.queryByText(address_town_marked)).not.toBeInTheDocument();
expect(screen.queryByText(verification_info)).not.toBeInTheDocument();
});

it('should render AddressDetails component for appstore', async () => {
render(
<PlatformContext.Provider value={{ is_appstore: true, is_deriv_crypto: false, is_pre_appstore: false }}>
<AddressDetails {...mock_props} />
</PlatformContext.Provider>
);

expect(mock_props.onSubmitEnabledChange).toHaveBeenCalledTimes(1);
await waitFor(() => {
expect(screen.getByText(verification_info)).toBeInTheDocument();
});
expect(screen.queryByText(use_address_info)).not.toBeInTheDocument();

const inputs: HTMLTextAreaElement[] = screen.getAllByRole('textbox');
expect(inputs).toHaveLength(5);

const required_fields = inputs.filter(input => input.required === true);
expect(required_fields).toHaveLength(4);

expect(screen.getByLabelText(address_line_1_marked)).toBeInTheDocument();
expect(screen.getByLabelText(address_line_2_marked)).toBeInTheDocument();
expect(screen.getByLabelText(address_postcode_marked)).toBeInTheDocument();
expect(screen.getByLabelText(address_state)).toBeInTheDocument();
expect(screen.getByLabelText(address_town_marked)).toBeInTheDocument();
expect(screen.getByText(verification_info)).toBeInTheDocument();

expect(screen.queryByText(address_line_1)).not.toBeInTheDocument();
expect(screen.queryByText(address_line_2)).not.toBeInTheDocument();
expect(screen.queryByText(address_postcode)).not.toBeInTheDocument();
expect(screen.queryByText(address_town)).not.toBeInTheDocument();
expect(screen.queryByText(use_address_info)).not.toBeInTheDocument();
});

it('should render AddressDetails component with states_list for mobile', async () => {
(isDesktop as jest.Mock).mockReturnValue(false);
(isMobile as jest.Mock).mockReturnValue(true);

mock_props.states_list = [
{ text: 'State 1', value: 'State 1' },
{ text: 'State 2', value: 'State 2' },
];

render(<AddressDetails {...mock_props} />);
(useStatesList as jest.Mock).mockReturnValue({
data: [
{ text: 'State 1', value: 'State 1' },
{ text: 'State 2', value: 'State 2' },
],
isFetched: true,
});
const new_store_config: TStores = {
...store,
ui: {
...store.ui,
is_mobile: true,
},
};
renderComponent({ store_config: new_store_config });

expect(screen.getByText('Default test state')).toBeInTheDocument();

const address_state_input: HTMLInputElement = screen.getByRole('combobox');
expect(address_state_input.value).toBe('');
fireEvent.change(address_state_input, { target: { value: 'State 2' } });
Expand All @@ -285,12 +236,14 @@ describe('<AddressDetails/>', () => {
});

it('should render AddressDetails component with states_list for desktop', async () => {
mock_props.states_list = [
{ text: 'State 1', value: 'State 1' },
{ text: 'State 2', value: 'State 2' },
];

render(<AddressDetails {...mock_props} />);
(useStatesList as jest.Mock).mockReturnValue({
data: [
{ text: 'State 1', value: 'State 1' },
{ text: 'State 2', value: 'State 2' },
],
isFetched: true,
});
renderComponent({});

const address_state_input: HTMLTextAreaElement = screen.getByRole('textbox', { name: 'State/Province' });
expect(address_state_input).toHaveValue('Default test state');
Expand All @@ -300,18 +253,21 @@ describe('<AddressDetails/>', () => {
});
});

it('should disable the field if it is immuatble from BE', async () => {
mock_props.disabled_items = ['address_line_1', 'address_line_2'];
mock_props.value.address_state = '';
it('should disable the field if it is immutable from BE', async () => {
const new_props: React.ComponentProps<typeof AddressDetails> = {
...mock_props,
disabled_items: ['address_line_1', 'address_line_2'],
value: { ...mock_props.value, address_state: '' },
};

render(<AddressDetails {...mock_props} />);
renderComponent({ props: new_props });

expect(screen.getByLabelText(address_line_1)).toBeDisabled();
expect(screen.getByLabelText(address_line_1_marked)).toBeDisabled();
expect(screen.getByLabelText(address_line_2)).toBeDisabled();
await waitFor(() => {
expect(screen.getByRole('textbox', { name: 'State/Province' })).toBeEnabled();
});
expect(screen.getByLabelText(address_town)).toBeEnabled();
expect(screen.getByLabelText(address_town_marked)).toBeEnabled();
expect(screen.getByLabelText(address_postcode)).toBeEnabled();
});
});
Loading

0 comments on commit c2e6360

Please sign in to comment.