From b5c0d16251e8cfe3b9c88cc282775f17b0ec3a3a Mon Sep 17 00:00:00 2001 From: Bastien DUMONT <bdumont@grandlyon.com> Date: Wed, 9 Oct 2024 11:29:27 +0200 Subject: [PATCH] apple to GRDf & fix tests --- .../ExpiredConsentModal.spec.tsx | 2 +- .../ExpiredConsentModal.tsx | 28 +-------- .../GRDFConnect/GrdfConnectView.tsx | 59 ++++++++++++------- .../SGEConnect/SgeConnectView.spec.tsx | 31 +++++----- .../Connection/SGEConnect/SgeConnectView.tsx | 19 +----- .../SGEConnect/StepAddress.spec.tsx | 18 ++---- .../SGEConnect/StepConsent.spec.tsx | 14 +---- .../SGEConnect/StepIdentityAndPdl.spec.tsx | 19 ++---- .../__snapshots__/StepAddress.spec.tsx.snap | 8 +-- src/components/Connection/useForm.tsx | 15 +++++ tests/__mocks__/forms.mock.ts | 14 +++++ 11 files changed, 110 insertions(+), 117 deletions(-) create mode 100644 tests/__mocks__/forms.mock.ts diff --git a/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.spec.tsx b/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.spec.tsx index ced72db8d..c50602afd 100644 --- a/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.spec.tsx +++ b/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.spec.tsx @@ -68,7 +68,7 @@ describe('ExpiredConsentModal component', () => { await act(async () => { await userEvent.click(screen.getByText('consent_outdated.yes')) }) - expect(mockAppDispatch).toHaveBeenCalledTimes(2) + expect(mockAppDispatch).toHaveBeenCalledTimes(1) expect(mockedNavigate).toHaveBeenCalledTimes(1) }) it('should click on close modal', async () => { diff --git a/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.tsx b/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.tsx index 8959ba88e..b01fcb166 100644 --- a/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.tsx +++ b/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.tsx @@ -7,14 +7,10 @@ import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import StyledIconButton from 'components/CommonKit/IconButton/StyledIconButton' import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n' import { FluidType } from 'enums' -import { AccountSgeData } from 'models' import React, { useCallback } from 'react' import { useNavigate } from 'react-router-dom' -import { - setShouldRefreshConsent, - updateSgeStore, -} from 'store/global/global.slice' -import { useAppDispatch, useAppSelector } from 'store/hooks' +import { setShouldRefreshConsent } from 'store/global/global.slice' +import { useAppDispatch } from 'store/hooks' import { getFluidName } from 'utils/utils' import './expiredConsentModal.scss' @@ -34,26 +30,8 @@ const ExpiredConsentModal = ({ const { t } = useI18n() const navigate = useNavigate() const dispatch = useAppDispatch() - const { fluidStatus } = useAppSelector(state => state.ecolyo.global) const launchUpdateConsent = useCallback(() => { if (fluidType === FluidType.ELECTRICITY) { - const accountData = fluidStatus[FluidType.ELECTRICITY].connection.account - ?.auth as AccountSgeData - // store the previous account data since the onDelete will remove account from DB - dispatch( - updateSgeStore({ - currentStep: 0, - firstName: accountData.firstname, - lastName: accountData.lastname, - pdl: parseInt(accountData.pointId), - address: accountData.address, - zipCode: parseInt(accountData.postalCode), - city: accountData.city, - dataConsent: true, - pdlConfirm: true, - shouldLaunchAccount: true, - }) - ) dispatch(setShouldRefreshConsent(true)) toggleModal() navigate(`/consumption/${FluidType[fluidType].toLocaleLowerCase()}`) @@ -62,7 +40,7 @@ const ExpiredConsentModal = ({ toggleModal() navigate(`/connect/${FluidType[fluidType].toLocaleLowerCase()}`) } - }, [dispatch, fluidStatus, fluidType, navigate, toggleModal]) + }, [dispatch, fluidType, navigate, toggleModal]) return ( <Dialog diff --git a/src/components/Connection/GRDFConnect/GrdfConnectView.tsx b/src/components/Connection/GRDFConnect/GrdfConnectView.tsx index 9661de4e1..e26af2bc9 100644 --- a/src/components/Connection/GRDFConnect/GrdfConnectView.tsx +++ b/src/components/Connection/GRDFConnect/GrdfConnectView.tsx @@ -11,6 +11,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react' import { useNavigate } from 'react-router-dom' import { useAppSelector } from 'store/hooks' import '../connection.scss' +import { FormData, useFormData } from '../useForm' import StepConsent from './StepConsent' import { StepIdentity } from './StepIdentity' @@ -18,11 +19,21 @@ export enum GrdfStep { Identity, Consent, } + +const createInitialState = (formData?: FormData): AccountGRDFData => ({ + lastname: formData?.lastName ?? '', + firstname: formData?.firstName ?? '', + pce: formData?.pce ?? '', + postalCode: formData?.zipCode ?? '', + email: '', +}) + /** * http://ecolyo.cozy.tools:8080/#/connect/gas */ export const GrdfConnectView = () => { const navigate = useNavigate() + const { formData } = useFormData() const { instanceSettings } = useUserInstanceSettings() const { fluidStatus } = useAppSelector(state => state.ecolyo.global) const currentFluidStatus = fluidStatus[FluidType.GAS] @@ -30,13 +41,9 @@ export const GrdfConnectView = () => { const [launchConnection, setLaunchConnection] = useState(false) const [currentStep, setCurrentStep] = useState<GrdfStep>(GrdfStep.Identity) - const [formData, setFormData] = useState<AccountGRDFData>({ - lastname: '', - firstname: '', - email: '', - postalCode: '', - pce: '', - }) + const [grdfState, setGrdfState] = useState<AccountGRDFData>( + createInitialState() + ) const [formConsent, setFormConsent] = useState({ dataConsent: false, pceConfirm: false, @@ -48,13 +55,25 @@ export const GrdfConnectView = () => { } const [connect, update] = useKonnectorAuth(FluidType.GAS, { - grdfAuthData: formData, + grdfAuthData: grdfState, }) useEffect(() => { - setFormData(prev => ({ ...prev, email: instanceSettings.email ?? '' })) + setGrdfState(prev => ({ ...prev, email: instanceSettings.email ?? '' })) }, [instanceSettings]) + useEffect( + function applyFormData() { + if (formData) { + setGrdfState(prevState => ({ + ...prevState, + ...createInitialState(formData), + })) + } + }, + [formData] + ) + useEffect(() => { async function launchConnect() { if (launchConnection) { @@ -74,11 +93,11 @@ export const GrdfConnectView = () => { const isNextValid = useCallback(() => { if (currentStep === GrdfStep.Identity) { return ( - formData.firstname !== '' && - formData.lastname !== '' && - formData.postalCode !== '' && - formData.email.includes('@') && - formData.pce.length === 14 + grdfState.firstname !== '' && + grdfState.lastname !== '' && + grdfState.postalCode !== '' && + grdfState.email.includes('@') && + grdfState.pce.length === 14 ) } else if (currentStep === GrdfStep.Consent) { return formConsent.dataConsent && formConsent.pceConfirm @@ -88,11 +107,11 @@ export const GrdfConnectView = () => { currentStep, formConsent.dataConsent, formConsent.pceConfirm, - formData.email, - formData.firstname, - formData.lastname, - formData.pce, - formData.postalCode, + grdfState.email, + grdfState.firstname, + grdfState.lastname, + grdfState.pce, + grdfState.postalCode, ]) const handleNext = useCallback(() => { @@ -113,7 +132,7 @@ export const GrdfConnectView = () => { const renderStep = (step: GrdfStep) => { if (step === GrdfStep.Identity) { - return <StepIdentity formData={formData} setFormData={setFormData} /> + return <StepIdentity formData={grdfState} setFormData={setGrdfState} /> } else { return ( <StepConsent diff --git a/src/components/Connection/SGEConnect/SgeConnectView.spec.tsx b/src/components/Connection/SGEConnect/SgeConnectView.spec.tsx index 3941573aa..f659b47e5 100644 --- a/src/components/Connection/SGEConnect/SgeConnectView.spec.tsx +++ b/src/components/Connection/SGEConnect/SgeConnectView.spec.tsx @@ -18,6 +18,23 @@ jest.mock('components/Hooks/useKonnectorAuth', () => jest.fn(() => [mockConnect, mockUpdate]) ) +// mock sge state with shouldLaunchAccount set to true +jest.mock('components/Connection/useForm', () => ({ + useFormData: jest.fn().mockReturnValue({ formData: {} }), + createInitialSgeState: jest.fn().mockReturnValue({ + address: '', + lastName: '', + firstName: '', + pdl: 0, + zipCode: 0, + city: '', + currentStep: 0, + dataConsent: false, + shouldLaunchAccount: true, + pdlConfirm: false, + }), +})) + describe('SgeConnectView component', () => { beforeEach(() => { jest.clearAllMocks() @@ -57,16 +74,6 @@ describe('SgeConnectView component', () => { describe('should test methods from useKonnectorAuth hook', () => { it('should launch account and trigger creation process', () => { - const store = createMockEcolyoStore({ - global: { - ...mockGlobalState, - sgeConnect: { - ...mockGlobalState.sgeConnect, - shouldLaunchAccount: true, - }, - }, - }) - render( <Provider store={store}> <SgeConnectView /> @@ -79,10 +86,6 @@ describe('SgeConnectView component', () => { global: { ...mockGlobalState, fluidStatus: [SgeStatusWithAccount], - sgeConnect: { - ...mockGlobalState.sgeConnect, - shouldLaunchAccount: true, - }, }, }) render( diff --git a/src/components/Connection/SGEConnect/SgeConnectView.tsx b/src/components/Connection/SGEConnect/SgeConnectView.tsx index 795c4ced6..32dc5d065 100644 --- a/src/components/Connection/SGEConnect/SgeConnectView.tsx +++ b/src/components/Connection/SGEConnect/SgeConnectView.tsx @@ -12,7 +12,7 @@ import { useNavigate } from 'react-router-dom' import { setShouldRefreshConsent } from 'store/global/global.slice' import { useAppDispatch, useAppSelector } from 'store/hooks' import '../connection.scss' -import { useFormData, type FormData } from '../useForm' +import { createInitialSgeState, useFormData } from '../useForm' import StepAddress from './StepAddress' import StepConsent from './StepConsent' import StepIdentityAndPdl from './StepIdentityAndPdl' @@ -27,19 +27,6 @@ export type SGEKeysForm = | 'dataConsent' | 'pdlConfirm' -const createInitialState = (formData?: FormData): SgeStore => ({ - address: formData?.address ?? '', - lastName: formData?.lastName ?? '', - firstName: formData?.firstName ?? '', - pdl: formData?.pdl ? parseInt(formData.pdl) : null, - zipCode: formData?.zipCode ? parseInt(formData.zipCode) : null, - city: formData?.city ?? '', - currentStep: SgeStep.Address, - dataConsent: false, - shouldLaunchAccount: false, - pdlConfirm: false, -}) - /** * http://ecolyo.cozy.tools:8080/#/connect/electricity */ @@ -49,7 +36,7 @@ const SgeConnectView = () => { const dispatch = useAppDispatch() const { formData } = useFormData() const [isLoading, setIsLoading] = useState(false) - const [sgeState, setSgeState] = useState<SgeStore>(createInitialState()) + const [sgeState, setSgeState] = useState<SgeStore>(createInitialSgeState()) const [currentStep, setCurrentStep] = useState<SgeStep>( SgeStep.IdentityAndPDL ) @@ -71,7 +58,7 @@ const SgeConnectView = () => { if (formData) { setSgeState(prevState => ({ ...prevState, - ...createInitialState(formData), + ...createInitialSgeState(formData), })) } }, diff --git a/src/components/Connection/SGEConnect/StepAddress.spec.tsx b/src/components/Connection/SGEConnect/StepAddress.spec.tsx index e7e1326c2..8ba9d9443 100644 --- a/src/components/Connection/SGEConnect/StepAddress.spec.tsx +++ b/src/components/Connection/SGEConnect/StepAddress.spec.tsx @@ -1,7 +1,7 @@ import { act, render, screen } from '@testing-library/react' import { userEvent } from '@testing-library/user-event' import React from 'react' -import { mockGlobalState } from 'tests/__mocks__/store' +import { mockSgeState } from 'tests/__mocks__/forms.mock' import StepAddress from './StepAddress' const mockHandleChange = jest.fn() @@ -9,10 +9,7 @@ const mockHandleChange = jest.fn() describe('StepAddress component', () => { it('should be rendered correctly', () => { const { container } = render( - <StepAddress - sgeState={mockGlobalState.sgeConnect} - onChange={mockHandleChange} - /> + <StepAddress sgeState={mockSgeState} onChange={mockHandleChange} /> ) expect(container).toMatchSnapshot() }) @@ -20,10 +17,7 @@ describe('StepAddress component', () => { describe('should change inputs', () => { beforeEach(() => { render( - <StepAddress - sgeState={mockGlobalState.sgeConnect} - onChange={mockHandleChange} - /> + <StepAddress sgeState={mockSgeState} onChange={mockHandleChange} /> ) }) it('should change address value', async () => { @@ -40,9 +34,9 @@ describe('StepAddress component', () => { name: 'auth.enedissgegrandlyon.zipCode', }) await act(async () => { - await userEvent.type(input, '0') + await userEvent.type(input, '1') }) - expect(mockHandleChange).toHaveBeenCalledWith('zipCode', '0', 5) + expect(mockHandleChange).toHaveBeenCalledWith('zipCode', '1', 5) }) it('should change city value', async () => { @@ -58,7 +52,7 @@ describe('StepAddress component', () => { it('should have an existing zipCode value', () => { render( <StepAddress - sgeState={{ ...mockGlobalState.sgeConnect, zipCode: 69200 }} + sgeState={{ ...mockSgeState, zipCode: 69200 }} onChange={mockHandleChange} /> ) diff --git a/src/components/Connection/SGEConnect/StepConsent.spec.tsx b/src/components/Connection/SGEConnect/StepConsent.spec.tsx index 642ebccb3..72fb90150 100644 --- a/src/components/Connection/SGEConnect/StepConsent.spec.tsx +++ b/src/components/Connection/SGEConnect/StepConsent.spec.tsx @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react' import { userEvent } from '@testing-library/user-event' import React from 'react' -import { mockGlobalState } from 'tests/__mocks__/store' +import { mockSgeState } from 'tests/__mocks__/forms.mock' import StepConsent from './StepConsent' const mockHandleChange = jest.fn() @@ -9,21 +9,13 @@ const mockHandleChange = jest.fn() describe('StepConsent component', () => { it('should be rendered correctly', () => { const { container } = render( - <StepConsent - sgeState={mockGlobalState.sgeConnect} - onChange={mockHandleChange} - /> + <StepConsent sgeState={mockSgeState} onChange={mockHandleChange} /> ) expect(container).toMatchSnapshot() }) it('should change dataConsent and pdlConfirm value', async () => { - render( - <StepConsent - sgeState={mockGlobalState.sgeConnect} - onChange={mockHandleChange} - /> - ) + render(<StepConsent sgeState={mockSgeState} onChange={mockHandleChange} />) const consentCheckbox = screen.getByLabelText( 'auth.enedissgegrandlyon.consentCheck1' ) diff --git a/src/components/Connection/SGEConnect/StepIdentityAndPdl.spec.tsx b/src/components/Connection/SGEConnect/StepIdentityAndPdl.spec.tsx index 42846fe60..db0bb7e1d 100644 --- a/src/components/Connection/SGEConnect/StepIdentityAndPdl.spec.tsx +++ b/src/components/Connection/SGEConnect/StepIdentityAndPdl.spec.tsx @@ -1,7 +1,7 @@ import { act, render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import React from 'react' -import { mockGlobalState } from 'tests/__mocks__/store' +import { mockSgeState } from 'tests/__mocks__/forms.mock' import StepIdentityAndPdl from './StepIdentityAndPdl' const mockHandleChange = jest.fn() @@ -9,20 +9,14 @@ const mockHandleChange = jest.fn() describe('StepIdentityAndPdl component', () => { it('should be rendered correctly', () => { const { container } = render( - <StepIdentityAndPdl - sgeState={mockGlobalState.sgeConnect} - onChange={mockHandleChange} - /> + <StepIdentityAndPdl sgeState={mockSgeState} onChange={mockHandleChange} /> ) expect(container).toMatchSnapshot() }) it('should be able to change fields', async () => { render( - <StepIdentityAndPdl - sgeState={mockGlobalState.sgeConnect} - onChange={mockHandleChange} - /> + <StepIdentityAndPdl sgeState={mockSgeState} onChange={mockHandleChange} /> ) const firstNameInput = screen.getByRole('textbox', { name: 'auth.enedissgegrandlyon.firstName', @@ -51,10 +45,7 @@ describe('StepIdentityAndPdl component', () => { it('should open hint modal', async () => { render( - <StepIdentityAndPdl - sgeState={mockGlobalState.sgeConnect} - onChange={mockHandleChange} - /> + <StepIdentityAndPdl sgeState={mockSgeState} onChange={mockHandleChange} /> ) await act(async () => { await userEvent.click( @@ -68,7 +59,7 @@ describe('StepIdentityAndPdl component', () => { render( <StepIdentityAndPdl sgeState={{ - ...mockGlobalState.sgeConnect, + ...mockSgeState, pdl: 11111111111111, firstName: 'Zack', lastName: 'Ichan', diff --git a/src/components/Connection/SGEConnect/__snapshots__/StepAddress.spec.tsx.snap b/src/components/Connection/SGEConnect/__snapshots__/StepAddress.spec.tsx.snap index 1e960609d..310b53b3a 100644 --- a/src/components/Connection/SGEConnect/__snapshots__/StepAddress.spec.tsx.snap +++ b/src/components/Connection/SGEConnect/__snapshots__/StepAddress.spec.tsx.snap @@ -58,8 +58,8 @@ exports[`StepAddress component should be rendered correctly 1`] = ` class="MuiFormControl-root MuiTextField-root" > <label - class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined Mui-required Mui-required" - data-shrink="false" + class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled Mui-required Mui-required" + data-shrink="true" for="zipCode" id="zipCode-label" > @@ -81,14 +81,14 @@ exports[`StepAddress component should be rendered correctly 1`] = ` id="zipCode" required="" type="number" - value="" + value="0" /> <fieldset aria-hidden="true" class="PrivateNotchedOutline-root-1 MuiOutlinedInput-notchedOutline" > <legend - class="PrivateNotchedOutline-legendLabelled-3" + class="PrivateNotchedOutline-legendLabelled-3 PrivateNotchedOutline-legendNotched-4" > <span> auth.enedissgegrandlyon.zipCode diff --git a/src/components/Connection/useForm.tsx b/src/components/Connection/useForm.tsx index 1f7240c3f..341d07753 100644 --- a/src/components/Connection/useForm.tsx +++ b/src/components/Connection/useForm.tsx @@ -1,6 +1,8 @@ import { Q, QueryDefinition, useQuery } from 'cozy-client' import { QueryOptions } from 'cozy-client/types/types' import { FORM_DOCTYPE } from 'doctypes' +import { SgeStep } from 'enums' +import { SgeStore } from 'models' export type QueryParams = (arg?: any) => { definition: QueryDefinition @@ -40,3 +42,16 @@ export const useFormData = () => { lastError, } } + +export const createInitialSgeState = (formData?: FormData): SgeStore => ({ + address: formData?.address ?? '', + lastName: formData?.lastName ?? '', + firstName: formData?.firstName ?? '', + pdl: formData?.pdl ? parseInt(formData.pdl) : null, + zipCode: formData?.zipCode ? parseInt(formData.zipCode) : null, + city: formData?.city ?? '', + currentStep: SgeStep.Address, + dataConsent: false, + shouldLaunchAccount: false, + pdlConfirm: false, +}) diff --git a/tests/__mocks__/forms.mock.ts b/tests/__mocks__/forms.mock.ts new file mode 100644 index 000000000..9f3f43e67 --- /dev/null +++ b/tests/__mocks__/forms.mock.ts @@ -0,0 +1,14 @@ +import { SgeStore } from 'models' + +export const mockSgeState: SgeStore = { + address: '', + lastName: '', + firstName: '', + pdl: 0, + zipCode: 0, + city: '', + currentStep: 0, + dataConsent: false, + shouldLaunchAccount: false, + pdlConfirm: false, +} -- GitLab