Skip to content

Commit

Permalink
Amina/comp 515/amend financial information dropdown (deriv-com#10360)
Browse files Browse the repository at this point in the history
* fix: set form values

* fix: common formating function

* fix: add id

* fix: aa

* fix: account signup

* fix: revert unrelated file change

* fix: test case

* fix: revert eslint fix on unrelated files

* fix: revert eslint fix on unrelated files

* fix: revert eslint fix on unrelated files

* fix: merge master

* fix: function to common

* fix: mobile

* fix: validation

* fix: add optional parameter

* fix: eslint

* chore: merge master
  • Loading branch information
amina-deriv authored Oct 26, 2023
1 parent 4f51e97 commit f6f566f
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FormikValues } from 'formik';
import React from 'react';
import { FormikValues } from 'formik';
import { isDesktop, isMobile } from '@deriv/shared';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import FinancialDetails from '../financial-details';

Expand All @@ -25,6 +25,7 @@ describe('<FinancialDetails />', () => {
validate: jest.fn(() => ({ errors: {} })),
goToPreviousStep: jest.fn(() => ({ errors: {} })),
value: {},
employment_status: '',
};

const fieldsRenderCheck = () => {
Expand Down Expand Up @@ -73,7 +74,7 @@ describe('<FinancialDetails />', () => {
const btns = screen.getAllByRole('button');
expect(btns[0]).toHaveTextContent('Previous');

fireEvent.click(btns[0]);
userEvent.click(btns[0]);
expect(mock_props.getCurrentStep).toHaveBeenCalledTimes(1);
});

Expand Down Expand Up @@ -103,21 +104,21 @@ describe('<FinancialDetails />', () => {
(option: FormikValues) => option.name === 'source_of_wealth'
);

fireEvent.change(account_turnover_select as HTMLElement, { target: { value: 'account turnover 1' } });
userEvent.type(account_turnover_select as HTMLElement, 'account turnover 1');

fireEvent.change(education_level_select as HTMLElement, { target: { value: 'education level 2' } });
fireEvent.change(employment_indystry_select as HTMLElement, { target: { value: 'employment industry 1' } });
fireEvent.change(estimated_worth_select as HTMLElement, { target: { value: 'estimated worth 2' } });
fireEvent.change(income_source_select as HTMLElement, { target: { value: 'income source 1' } });
fireEvent.change(net_income_select as HTMLElement, { target: { value: 'net income 1' } });
fireEvent.change(occuppation_select as HTMLElement, { target: { value: 'occupation 2' } });
userEvent.type(education_level_select as HTMLElement, 'education level 2');
userEvent.type(employment_indystry_select as HTMLElement, 'employment industry 1');
userEvent.type(estimated_worth_select as HTMLElement, 'estimated worth 2');
userEvent.type(income_source_select as HTMLElement, 'income source 1');
userEvent.type(net_income_select as HTMLElement, 'net income 1');
userEvent.type(occuppation_select as HTMLElement, 'Government Officers');

fireEvent.change(source_of_wealth_select as HTMLElement, { target: { value: 'source of wealth 1' } });
userEvent.type(source_of_wealth_select as HTMLElement, 'source of wealth 1');

const btns = screen.getAllByRole('button');
expect(btns[1]).toHaveTextContent('Next');

fireEvent.click(btns[1]);
userEvent.click(btns[1]);
await waitFor(() => {
expect(mock_props.onSubmit).toHaveBeenCalledTimes(1);
});
Expand All @@ -137,4 +138,56 @@ describe('<FinancialDetails />', () => {

expect(screen.getByRole('option', { name: 'Salaried Employee' }).selected).toBe(true);
});

it('should show "Unemployed" in occupation list if employment status is not "Employed"', async () => {
(isDesktop as jest.Mock).mockReturnValue(false);
(isMobile as jest.Mock).mockReturnValue(true);
const new_mock_props = {
...mock_props,
employment_status: 'Pensioner',
};
render(<FinancialDetails {...new_mock_props} />);

fieldsRenderCheck();

const select_inputs = screen.getAllByRole('combobox');

const account_turnover_select = select_inputs.find(
(option: FormikValues) => option.name === 'account_turnover'
);
const education_level_select = select_inputs.find((option: FormikValues) => option.name === 'education_level');
const employment_indystry_select = select_inputs.find(
(option: FormikValues) => option.name === 'employment_industry'
);
const estimated_worth_select = select_inputs.find((option: FormikValues) => option.name === 'estimated_worth');
const income_source_select = select_inputs.find((option: FormikValues) => option.name === 'income_source');
const net_income_select = select_inputs.find((option: FormikValues) => option.name === 'net_income');

const source_of_wealth_select = select_inputs.find(
(option: FormikValues) => option.name === 'source_of_wealth'
);
const occuppation_select = select_inputs.find((option: FormikValues) => option.name === 'occupation');

userEvent.type(account_turnover_select as HTMLElement, 'account turnover 1');

userEvent.type(education_level_select as HTMLElement, 'education level 2');
userEvent.type(employment_indystry_select as HTMLElement, 'employment industry 1');
userEvent.type(estimated_worth_select as HTMLElement, 'estimated worth 2');
userEvent.type(income_source_select as HTMLElement, 'income source 1');
userEvent.type(net_income_select as HTMLElement, 'net income 1');
userEvent.type(source_of_wealth_select as HTMLElement, 'source of wealth 1');

const occupation_text = screen.getAllByText('Unemployed')[0];
expect(occupation_text).toBeInTheDocument();

userEvent.type(occuppation_select as HTMLElement, 'Unemployed');

const next_btn = screen.getByRole('button', { name: 'Next' });
expect(next_btn).toBeEnabled();

userEvent.click(next_btn);
await waitFor(() => {
expect(mock_props.onSubmit).toHaveBeenCalled();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@ import {
getEstimatedWorthList,
getIncomeSourceList,
getNetIncomeList,
getOccupationList,
getFormattedOccupationList,
getSourceOfWealthList,
} from 'Configs/financial-details-config';
import { EMPLOYMENT_VALUES } from 'Constants/financial-details';

type TFinancialDetailsDropdownFieldProps = {
dropdown_list: Array<object>;
field_key: string;
placeholder?: string;
label: string;
employment_status?: string;
};

type TFinancialInformationProps = {
employment_status?: string;
};

/**
Expand All @@ -27,6 +33,7 @@ type TFinancialDetailsDropdownFieldProps = {
* @param {string} field_key - field reference of the field
* @param {string} placeholder - placeholder of the field
* @param {string} label - label of the field
* @param {string} employment_status - selected employment_status,
* @returns {JSX.Element}
*/
const FinancialDetailsDropdownField = ({
Expand All @@ -49,13 +56,13 @@ const FinancialDetailsDropdownField = ({
is_align_text_left
name={field.name}
list={dropdown_list}
value={values[field_key]}
value={values?.[field_key]}
onChange={handleChange}
handleBlur={handleBlur}
error={touched?.[field_key] && errors?.[field_key]}
list_portal_id='modal_root'
{...field}
required
{...field}
/>
</DesktopWrapper>
<MobileWrapper>
Expand All @@ -70,8 +77,8 @@ const FinancialDetailsDropdownField = ({
handleChange(e);
setFieldValue('field_key', e.target.value, true);
}}
{...field}
required
{...field}
/>
</MobileWrapper>
</React.Fragment>
Expand All @@ -80,12 +87,71 @@ const FinancialDetailsDropdownField = ({
);
};

const FinancialDetailsOccupationDropdownField = ({
dropdown_list,
field_key,
placeholder = localize('Please select'),
label,
employment_status,
}: TFinancialDetailsDropdownFieldProps) => {
const { values, handleChange, handleBlur, touched, errors, setFieldValue } = useFormikContext<{
[key: string]: string;
}>();

const getFormattedOccupationValues = () =>
employment_status === EMPLOYMENT_VALUES.EMPLOYED && values?.occupation === EMPLOYMENT_VALUES.UNEMPLOYED
? ''
: values?.occupation;

return (
<Field name={field_key}>
{({ field }: FormikValues) => (
<React.Fragment>
<DesktopWrapper>
<Dropdown
{...field}
placeholder={label}
is_align_text_left
name={field.name}
list={dropdown_list}
value={getFormattedOccupationValues()}
onChange={e => {
setFieldValue('field_key', getFormattedOccupationValues(), true);
handleChange(e);
}}
handleBlur={handleBlur}
error={touched?.[field_key] && errors?.[field_key]}
list_portal_id='modal_root'
required
/>
</DesktopWrapper>
<MobileWrapper>
<SelectNative
{...field}
placeholder={placeholder}
name={field.name}
label={label}
list_items={dropdown_list}
value={getFormattedOccupationValues()}
error={touched?.[field_key] && errors?.[field_key]}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
setFieldValue('field_key', getFormattedOccupationValues(), true);
handleChange(e);
}}
required
/>
</MobileWrapper>
</React.Fragment>
)}
</Field>
);
};
/**
* Wrapper for financial details form fields.
* @name FinancialInformation
* @returns {JSX.Element}
*/
const FinancialInformation = () => {
const FinancialInformation = ({ employment_status }: TFinancialInformationProps) => {
return (
<React.Fragment>
<FinancialDetailsDropdownField
Expand All @@ -98,10 +164,11 @@ const FinancialInformation = () => {
field_key='employment_industry'
label={localize('Industry of employment')}
/>
<FinancialDetailsDropdownField
dropdown_list={getOccupationList()}
<FinancialDetailsOccupationDropdownField
dropdown_list={getFormattedOccupationList(employment_status)}
field_key='occupation'
label={localize('Occupation')}
employment_status={employment_status}
/>
<FinancialDetailsDropdownField
dropdown_list={getSourceOfWealthList()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from '@deriv/components';
import { isDesktop, isMobile } from '@deriv/shared';
import { Localize, localize } from '@deriv/translations';
import { EMPLOYMENT_VALUES } from 'Constants/financial-details';
import FinancialInformation from './financial-details-partials';
import { splitValidationResultTypes } from '../real-account-signup/helpers/utils';
import ScrollToFieldWithError from '../forms/scroll-to-field-with-error';
Expand Down Expand Up @@ -40,6 +41,7 @@ type TFinancialDetails = {
onCancel: (current_step: number, props: () => void) => void;
validate: (values: TFinancialDetailsFormValues) => object;
value: TFinancialDetailsFormValues;
employment_status: string;
};

/**
Expand Down Expand Up @@ -104,13 +106,19 @@ const FinancialDetails = (props: TFinancialDetails) => {
'financial-assessment__form'
)}
>
<FinancialInformation />
<FinancialInformation employment_status={props.employment_status} />
</div>
</ThemedScrollbars>
</Div100vhContainer>
<Modal.Footer has_separator is_bypassed={isMobile()}>
<FormSubmitButton
is_disabled={isSubmitting}
is_disabled={
isSubmitting ||
!!(
props.employment_status === EMPLOYMENT_VALUES.EMPLOYED &&
values?.occupation === EMPLOYMENT_VALUES.UNEMPLOYED
)
}
is_absolute={isMobile()}
label={localize('Next')}
has_cancel
Expand Down
6 changes: 6 additions & 0 deletions packages/account/src/Configs/financial-details-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { GetFinancialAssessment } from '@deriv/api-types';
import { generateValidationFunction, getDefaultFields, TSchema } from '@deriv/shared';
import { localize } from '@deriv/translations';
import { EMPLOYMENT_VALUES } from 'Constants/financial-details';

type TFinancialDetailsConfig = {
real_account_signup_target: string;
Expand Down Expand Up @@ -314,4 +315,9 @@ export const getIncomeSourceList = () => [
},
];

export const getFormattedOccupationList = (employment_status?: string) =>
employment_status && employment_status === EMPLOYMENT_VALUES.EMPLOYED
? getOccupationList().filter(item => item.value !== EMPLOYMENT_VALUES.UNEMPLOYED)
: getOccupationList();

export default financialDetailsConfig;
4 changes: 4 additions & 0 deletions packages/account/src/Constants/financial-details.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const EMPLOYMENT_VALUES = {
EMPLOYED: 'Employed',
UNEMPLOYED: 'Unemployed',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { StoreProvider, mockStore } from '@deriv/stores';
import FinancialAssessment from '../financial-assessment';

jest.mock('@deriv/shared/src/services/ws-methods', () => ({
__esModule: true,
default: 'mockedDefaultExport',
WS: {
wait: jest.fn(() => Promise.resolve()),
setSettings: jest.fn(() => Promise.resolve({ error: '' })),
authorized: {
storage: {
getFinancialAssessment: jest.fn(() =>
Promise.resolve({
get_financial_assessment: {
account_turnover: '',
cfd_score: 0,
education_level: '',
employment_industry: '',
employment_status: 'Employed',
estimated_worth: '',
financial_information_score: '',
income_source: '',
net_income: '',
occupation: '',
source_of_wealth: '',
total_score: '',
trading_score: '',
},
})
),
},
},
},
useWS: () => undefined,
}));
jest.mock('@deriv/components', () => {
const original_module = jest.requireActual('@deriv/components');
return {
...original_module,
Loading: jest.fn(() => 'mockedLoading'),
};
});
describe('<FinancialAssessment/>', () => {
const mock = mockStore({});
const rendercomponent = () => {
const wrapper = ({ children }: { children: JSX.Element }) => (
<StoreProvider store={mock}>{children}</StoreProvider>
);
render(
<BrowserRouter>
<FinancialAssessment />
</BrowserRouter>,
{ wrapper }
);
};
it('should render FinancialAssessment component', async () => {
rendercomponent();
await waitFor(() => {
expect(screen.getByText('Financial information')).toBeInTheDocument();
expect(screen.getByText('Source of income')).toBeInTheDocument();
expect(screen.getByText('Employment status')).toBeInTheDocument();
expect(screen.getByText('Industry of employment')).toBeInTheDocument();
expect(screen.getByText('Occupation')).toBeInTheDocument();
expect(screen.getByText('Source of wealth')).toBeInTheDocument();
expect(screen.getByText('Level of education')).toBeInTheDocument();
expect(screen.getByText('Net annual income')).toBeInTheDocument();
expect(screen.getByText('Source of wealth')).toBeInTheDocument();
expect(screen.getByText('Estimated net worth')).toBeInTheDocument();
expect(screen.getByText('Anticipated account turnover')).toBeInTheDocument();
});
});
});
Loading

0 comments on commit f6f566f

Please sign in to comment.