Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ const TestComponent = () => (
);

describe('SalaryCalculatorPage', () => {
it('renders the Salary Calculator header', () => {
const { getByRole } = render(<TestComponent />);
it('renders the Salary Calculator header', async () => {
const { findByRole } = render(<TestComponent />);
expect(
getByRole('heading', { name: /Salary Calculator/i }),
await findByRole('heading', { name: /Salary Calculator/i }),
).toBeInTheDocument();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { AdditionalSalaryRequestSection } from '../SharedComponents/AdditionalSa
import { SpouseComponent } from '../SharedComponents/SpouseComponent';

export const AboutForm: React.FC = () => {
const { currentStep } = useAdditionalSalaryRequest();
const { currentIndex } = useAdditionalSalaryRequest();
const { t } = useTranslation();
const theme = useTheme();

Expand All @@ -20,7 +20,7 @@ export const AboutForm: React.FC = () => {
const remainingAllowableSalary = 17500.0;

return (
<AdditionalSalaryRequestSection title={getHeader(t, currentStep)}>
<AdditionalSalaryRequestSection title={getHeader(t, currentIndex)}>
<Trans t={t}>
<Typography variant="body1" paragraph>
You can use this form to electronically submit additional salary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Deduction } from './Deduction/Deduction';

export const CompleteForm: React.FC = () => {
const { t } = useTranslation();
const { currentStep } = useAdditionalSalaryRequest();
const { currentIndex } = useAdditionalSalaryRequest();

const theme = useTheme();
const name = 'Doc, John';
Expand All @@ -20,7 +20,7 @@ export const CompleteForm: React.FC = () => {
const remainingAllowableSalary = 17500.0;

return (
<AdditionalSalaryRequestSection title={getHeader(t, currentStep)}>
<AdditionalSalaryRequestSection title={getHeader(t, currentIndex)}>
<Box
sx={{
display: 'flex',
Expand Down
34 changes: 15 additions & 19 deletions src/components/Reports/AdditionalSalaryRequest/CurrentStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,29 @@ import { useTranslation } from 'react-i18next';
import { useAccountListId } from 'src/hooks/useAccountListId';
import { Receipt } from '../Shared/CalculationReports/ReceiptStep/Receipt';
import { AboutForm } from './AboutForm/AboutForm';
import { AdditionalSalaryRequestSectionEnum } from './AdditionalSalaryRequestHelper';
import { CompleteForm } from './CompleteForm/CompleteForm';
import { useAdditionalSalaryRequest } from './Shared/AdditionalSalaryRequestContext';
import { AdditionalSalaryRequestSection } from './SharedComponents/AdditionalSalaryRequestSection';

export const CurrentStep: React.FC = () => {
const { currentStep } = useAdditionalSalaryRequest();
const { currentIndex } = useAdditionalSalaryRequest();
const { t } = useTranslation();
const accountListId = useAccountListId();

const pageLink = `/accountLists/${accountListId}/reports/additionalSalaryRequest`;

switch (currentStep) {
case AdditionalSalaryRequestSectionEnum.AboutForm:
return <AboutForm />;
case AdditionalSalaryRequestSectionEnum.CompleteForm:
return <CompleteForm />;
case AdditionalSalaryRequestSectionEnum.Receipt:
return (
<AdditionalSalaryRequestSection>
<Receipt
formTitle={t('Additional Salary Request')}
buttonText={t('View Your Additional Salary Request')}
viewLink={pageLink}
isEdit={false}
/>
</AdditionalSalaryRequestSection>
);
}
const steps = [
<AboutForm key="about-form" />,
<CompleteForm key="complete-form" />,
<AdditionalSalaryRequestSection key="receipt-section">
<Receipt
formTitle={t('Additional Salary Request')}
buttonText={t('View Your Additional Salary Request')}
viewLink={pageLink}
isEdit={false}
/>
</AdditionalSalaryRequestSection>,
];

return steps[currentIndex] ?? null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import { useAdditionalSalaryRequest } from './AdditionalSalaryRequestContext';
import { getHeader } from './Helper/getHeader';

const TestComponent: React.FC = () => {
const { currentStep, handleNextStep, isDrawerOpen, toggleDrawer } =
const { currentIndex, handleNextStep, isDrawerOpen, toggleDrawer } =
useAdditionalSalaryRequest();
const { t } = useTranslation();

return (
<div>
<h2>{getHeader(t, currentStep)}</h2>
<h2>{getHeader(t, currentIndex)}</h2>
<div aria-label="drawer state" data-open={isDrawerOpen}>
Drawer: {isDrawerOpen ? 'open' : 'closed'}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@
import { FormEnum } from '../../Shared/CalculationReports/Shared/sharedTypes';
import { Steps } from '../../Shared/CalculationReports/StepsList/StepsList';
import { CompleteFormValues } from '../AdditionalSalaryRequest';
import { AdditionalSalaryRequestSectionEnum } from '../AdditionalSalaryRequestHelper';
import { calculateCompletionPercentage } from './calculateCompletionPercentage';

export type AdditionalSalaryRequestType = {
steps: Steps[];
currentIndex: number;
percentComplete: number;
currentStep: AdditionalSalaryRequestSectionEnum;
handleNextStep: () => void;
handlePreviousStep: () => void;
isDrawerOpen: boolean;
Expand All @@ -43,8 +41,6 @@
initialValues?: CompleteFormValues;
}

const objects = Object.values(AdditionalSalaryRequestSectionEnum);

export const AdditionalSalaryRequestProvider: React.FC<Props> = ({
children,
initialValues: providedInitialValues,
Expand Down Expand Up @@ -119,77 +115,58 @@
}),
[createCurrencyValidation],
);

// Step Handlers
const [currentStep, setCurrentStep] = useState(
AdditionalSalaryRequestSectionEnum.AboutForm,
);

const handleNextStep = useCallback(() => {
const next = objects[currentIndex + 1];
nextStep();

setCurrentStep(next);
}, [currentIndex, objects, nextStep]);

const handlePreviousStep = useCallback(() => {
const next = objects[currentIndex - 1];
previousStep();

setCurrentStep(next);
}, [currentIndex, objects, previousStep]);

const [isDrawerOpen, setIsDrawerOpen] = useState(true);
const toggleDrawer = useCallback(() => {
setIsDrawerOpen((prev) => !prev);
}, []);

const handleCancel = () => {
// Implement cancel logic here
};

const handleSubmit = useCallback(
(_values: CompleteFormValues) => {
//TODO: Submit form values
handleNextStep();
nextStep();
},
[handleNextStep],
[nextStep],
);

const formik = useFormik<CompleteFormValues>({
initialValues: providedInitialValues || initialValues,
validationSchema,
onSubmit: handleSubmit,
enableReinitialize: true,
});

const percentComplete = useMemo(
() => calculateCompletionPercentage(formik.values),
[formik.values],
);

const contextValue = useMemo<AdditionalSalaryRequestType>(
() => ({
steps,
currentIndex,
percentComplete,
currentStep,
handleNextStep,
handlePreviousStep,
handleNextStep: nextStep,
handlePreviousStep: previousStep,
isDrawerOpen,
toggleDrawer,
setIsDrawerOpen,
handleCancel,
}),
[
steps,
currentIndex,
percentComplete,
currentStep,
handleNextStep,
handlePreviousStep,
nextStep,
previousStep,
isDrawerOpen,
toggleDrawer,
setIsDrawerOpen,
handleCancel,

Check notice on line 169 in src/components/Reports/AdditionalSalaryRequest/Shared/AdditionalSalaryRequestContext.tsx

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

✅ Getting better: Large Method

AdditionalSalaryRequestProvider:React.FC<Props> decreases from 138 to 125 lines of code, threshold = 120. Large functions with many lines of code are generally harder to understand and lower the code health. Avoid adding more lines to this function.
],
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { TFunction } from 'i18next';
import { AdditionalSalaryRequestSectionEnum } from '../../AdditionalSalaryRequestHelper';

export const getHeader = (
t: TFunction,
step: AdditionalSalaryRequestSectionEnum,
): string => {
export const getHeader = (t: TFunction, step: number): string => {
switch (step) {
case AdditionalSalaryRequestSectionEnum.AboutForm:
case 0:
return 'About this Form';
case AdditionalSalaryRequestSectionEnum.CompleteForm:
case 1:
return 'Complete the Form';
case AdditionalSalaryRequestSectionEnum.Receipt:
case 2:
return 'Receipt';
default:
return '';
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { ThemeProvider } from '@mui/material/styles';
import { render, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { SnackbarProvider } from 'notistack';
import TestRouter from '__tests__/util/TestRouter';
import { GqlMockedProvider } from '__tests__/util/graphqlMocking';
import { MhaRentOrOwnEnum } from 'src/graphql/types.generated';
Expand All @@ -13,7 +14,6 @@ import {
MinisterHousingAllowanceContext,
MinisterHousingAllowanceProvider,
} from '../Shared/Context/MinisterHousingAllowanceContext';
import { StepsEnum } from '../Shared/sharedTypes';
import { EditRequestPage } from './EditRequestPage';

const mutationSpy = jest.fn();
Expand Down Expand Up @@ -54,51 +54,56 @@ const TestComponentContext: React.FC<TestComponentProps> = ({
}) => (
<ThemeProvider theme={theme}>
<TestRouter>
<GqlMockedProvider<{
UpdateMinistryHousingAllowanceRequest: UpdateMinistryHousingAllowanceRequestMutation;
}>
onCall={mutationSpy}
>
<MinisterHousingAllowanceContext.Provider
value={contextValue as ContextType}
<SnackbarProvider>
<GqlMockedProvider<{
UpdateMinistryHousingAllowanceRequest: UpdateMinistryHousingAllowanceRequestMutation;
}>
onCall={mutationSpy}
>
<EditRequestPage />
</MinisterHousingAllowanceContext.Provider>
</GqlMockedProvider>
<MinisterHousingAllowanceContext.Provider
value={contextValue as ContextType}
>
<EditRequestPage />
</MinisterHousingAllowanceContext.Provider>
</GqlMockedProvider>
</SnackbarProvider>
</TestRouter>
</ThemeProvider>
);

const TestComponent: React.FC = () => (
<ThemeProvider theme={theme}>
<TestRouter>
<GqlMockedProvider<{
UpdateMinistryHousingAllowanceRequest: UpdateMinistryHousingAllowanceRequestMutation;
}>
onCall={mutationSpy}
>
<MinisterHousingAllowanceProvider type={PageEnum.Edit}>
<EditRequestPage />
</MinisterHousingAllowanceProvider>
</GqlMockedProvider>
<SnackbarProvider>
<GqlMockedProvider<{
UpdateMinistryHousingAllowanceRequest: UpdateMinistryHousingAllowanceRequestMutation;
}>
onCall={mutationSpy}
>
<MinisterHousingAllowanceProvider type={PageEnum.Edit}>
<EditRequestPage />
</MinisterHousingAllowanceProvider>
</GqlMockedProvider>
</SnackbarProvider>
</TestRouter>
</ThemeProvider>
);

describe('EditRequestPage', () => {
it('renders steps list', () => {
const { getByText } = render(<TestComponent />);
it('renders steps list', async () => {
const { getByText, findByText } = render(<TestComponent />);

expect(getByText(/1. about this form/i)).toBeInTheDocument();
expect(await findByText(/1. about this form/i)).toBeInTheDocument();
expect(getByText(/2. rent or own?/i)).toBeInTheDocument();
expect(getByText(/3. edit your mha/i)).toBeInTheDocument();
expect(getByText(/4. receipt/i)).toBeInTheDocument();
});

it('updates steps when Continue clicked', async () => {
const { getByRole, getAllByRole, getByText, queryByTestId } = render(
<TestComponent />,
);
const { getByRole, getAllByRole, getByText, queryByTestId, findByText } =
render(<TestComponent />);

await findByText(/1. about this form/i);

expect(getByRole('progressbar')).toHaveAttribute('aria-valuenow', '25');
expect(queryByTestId('ArrowBackIcon')).toBeInTheDocument();
Expand Down Expand Up @@ -149,12 +154,12 @@ describe('EditRequestPage', () => {
});

it('should show an option is preselected', async () => {
const { findAllByRole, getByRole, findByRole } = render(
const { findAllByRole, findByRole } = render(
<TestComponentContext
contextValue={
{
pageType: PageEnum.Edit,
currentStep: StepsEnum.RentOrOwn,
currentIndex: 1,
steps,
handleNextStep,
handlePreviousStep,
Expand All @@ -169,21 +174,21 @@ describe('EditRequestPage', () => {
/>,
);

const continueButton = getByRole('button', { name: 'Continue' });
const continueButton = await findByRole('button', { name: 'Continue' });
await userEvent.click(continueButton);

expect(await findByRole('radio', { name: 'Rent' })).toBeChecked();
expect(await findAllByRole('radio', { checked: true })).toHaveLength(1);
});

it('opens confirmation modal when changing selection', async () => {
const { getByRole, getByText, queryByText } = render(
const { getByRole, getByText, queryByText, findByRole } = render(
<TestComponentContext
contextValue={
{
pageType: PageEnum.Edit,
steps,
currentStep: StepsEnum.RentOrOwn,
currentIndex: 1,
handleNextStep,
handlePreviousStep,
hasCalcValues: true,
Expand All @@ -201,7 +206,7 @@ describe('EditRequestPage', () => {
/>,
);

const ownRadio = getByRole('radio', { name: 'Own' });
const ownRadio = await findByRole('radio', { name: 'Own' });
await userEvent.click(ownRadio);
expect(ownRadio).not.toBeChecked();

Expand Down
Loading
Loading