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
3 changes: 3 additions & 0 deletions src/components/RenderConnectStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { Microdeposits } from 'src/views/microdeposits/Microdeposits'
import VerifyExistingMember from 'src/views/verification/VerifyExistingMember'
import { VerifyError } from 'src/views/verification/VerifyError'
import { ManualAccountConnect } from 'src/views/manualAccount/ManualAccountConnect'
import { DemoConnectGuard } from 'src/views/demoConnectGuard/DemoConnectGuard'
import AdditionalProductStep, {
ADDITIONAL_PRODUCT_OPTIONS,
} from 'src/views/additionalProduct/AdditionalProductStep'
Expand Down Expand Up @@ -110,6 +111,8 @@ const RenderConnectStep = (props) => {
throw new Error('invalid product offer')

connectStepView = <AdditionalProductStep ref={props.navigationRef} />
} else if (step === STEPS.DEMO_CONNECT_GUARD) {
connectStepView = <DemoConnectGuard />
} else if (step === STEPS.ADD_MANUAL_ACCOUNT) {
connectStepView = (
<ManualAccountConnect
Expand Down
79 changes: 79 additions & 0 deletions src/components/__tests__/RenderConnectStep-test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from 'react'
import { render, screen } from 'src/utilities/testingLibrary'
import RenderConnectStep from 'src/components/RenderConnectStep'
import { STEPS } from 'src/const/Connect'

describe('RenderConnectStep', () => {
const defaultProps = {
availableAccountTypes: [],
handleConsentGoBack: vi.fn(),
handleCredentialsGoBack: vi.fn(),
navigationRef: React.createRef(),
onManualAccountAdded: vi.fn(),
onUpsertMember: vi.fn(),
setConnectLocalState: vi.fn(),
}

const mockInstitution = {
guid: 'INS-123',
name: 'Test Bank',
logo_url: 'https://example.com/logo.png',
code: 'TEST',
url: 'https://testbank.com',
}

const createInitialState = (step) => ({
browser: {
height: 768,
width: 1024,
size: 'large',
},
connect: {
location: [{ step }],
selectedInstitution: mockInstitution,
updateCredentials: false,
error: null,
},
config: {
mode: 'aggregation',
initialConfig: {},
},
profiles: {
client: { has_atrium_api: false },
clientProfile: {
uses_oauth: false,
account_verification_is_enabled: true,
is_microdeposits_enabled: true,
},
widgetProfile: {
enable_support_requests: true,
show_microdeposits_in_connect: false,
display_delete_option_in_connect: true,
},
},
})

it('should render DemoConnectGuard when step is DEMO_CONNECT_GUARD', () => {
const initialState = createInitialState(STEPS.DEMO_CONNECT_GUARD)

const { container } = render(<RenderConnectStep {...defaultProps} />, {
preloadedState: initialState,
})

expect(screen.getByText('Demo mode active')).toBeInTheDocument()
expect(
screen.getByText(/Live institutions are not available in the demo environment/i),
).toBeInTheDocument()
expect(screen.getByText('MX Bank')).toBeInTheDocument()

const logo = screen.getByAltText('Logo for Test Bank')
expect(logo).toBeInTheDocument()
expect(logo).toHaveAttribute('src', mockInstitution.logo_url)

const errorIcon = container.querySelector('svg.MuiSvgIcon-colorError')
expect(errorIcon).toBeInTheDocument()

const button = screen.getByRole('button', { name: /return to institution selection/i })
expect(button).toBeInTheDocument()
})
})
1 change: 1 addition & 0 deletions src/const/Connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const STEPS = {
CONNECTING: 'connecting',
CONSENT: 'consent',
DELETE_MEMBER_SUCCESS: 'deleteMemberSuccess',
DEMO_CONNECT_GUARD: 'demoConnectGuard',
DISCLOSURE: 'disclosure',
ENTER_CREDENTIALS: 'enterCreds',
EXISTING_MEMBER: 'existingMember',
Expand Down
2 changes: 2 additions & 0 deletions src/const/language/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@
"Profile information": "Información del perfil",
"Account numbers": "Números de cuenta",
"To complete your connection, please %1share%2 the following after signing in:": "Para completar su conexión, por favor, %1comparta%2 lo siguiente después de iniciar sesión:",
"Demo mode active": "Modo de demostración activo",
"Live institutions are not available in the demo environment. Please select *MX Bank* to test the connection process.": "Las instituciones en vivo no están disponibles en el entorno de demostración. Seleccione *MX Bank* para probar el proceso de conexión.",
"connect/disclosure/button\u0004Continue": "Continuar",
"connect/disclosure/policy/text\u0004By clicking Continue, you agree to the ": "Al hacer clic en Continuar, tu aceptas la ",
"connect/disclosure/policy/link\u0004MX Privacy Policy.": "Política de privacidad de Money Experience.",
Expand Down
12 changes: 12 additions & 0 deletions src/const/language/es.po
Original file line number Diff line number Diff line change
Expand Up @@ -1986,6 +1986,7 @@ msgstr "No, solo añadir gestión financiera"
msgid "DISABLED"
msgstr "DESACTIVADO"

#: src/views/demoConnectGuard/DemoConnectGuard.tsx
#: src/views/institutionStatusDetails/InstitutionStatusDetails.tsx
msgid "Logo for %1"
msgstr "Logotipo de %1"
Expand All @@ -2010,6 +2011,7 @@ msgstr "¡Éxito!"
msgid "No accounts found"
msgstr "No se encontraron cuentas"

#: src/views/demoConnectGuard/DemoConnectGuard.tsx
#: src/views/actionableError/useActionableErrorMap.tsx
msgid "Return to institution selection"
msgstr "Volver a la selección de instituciones"
Expand Down Expand Up @@ -2104,3 +2106,13 @@ msgid ""
msgstr ""
"Para completar su conexión, por favor, %1comparta%2 lo siguiente después de "
"iniciar sesión:"

#: src/views/demoConnectGuard/DemoConnectGuard.tsx
msgid "Demo mode active"
msgstr "Modo de demostración activo"

#: src/views/demoConnectGuard/DemoConnectGuard.tsx
msgid ""
"Live institutions are not available in the demo environment. Please select "
"*MX Bank* to test the connection process."
msgstr "Las instituciones en vivo no están disponibles en el entorno de demostración. Seleccione *MX Bank* para probar el proceso de conexión."
2 changes: 2 additions & 0 deletions src/const/language/frCa.json
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,8 @@
"Profile information": "Informations de profil",
"Account numbers": "Numéros de compte",
"To complete your connection, please %1share%2 the following after signing in:": "Pour finaliser votre connexion, veuillez %1partager%2 les informations suivantes après vous être connecté :",
"Demo mode active": "Mode démo actif",
"Live institutions are not available in the demo environment. Please select *MX Bank* to test the connection process.": "Les établissements réels ne sont pas disponibles dans l'environnement de démonstration. Veuillez sélectionner *MX Bank* pour tester la procédure de connexion.",
"connect/disclosure/policy/text\u0004By clicking Continue, you agree to the ": "En cliquant sur Continuer, vous acceptez la ",
"connect/disclosure/policy/link\u0004MX Privacy Policy.": "Politique de confidentialité de MX.",
"connect/disclosure/policy/link\u0004MX Privacy Policy": "Politique de confidentialité de MX.",
Expand Down
12 changes: 12 additions & 0 deletions src/const/language/frCa.po
Original file line number Diff line number Diff line change
Expand Up @@ -2063,6 +2063,7 @@ msgstr "Non, ajoutez uniquement la gestion financière"
msgid "DISABLED"
msgstr "DÉSACTIVÉ"

#: src/views/demoConnectGuard/DemoConnectGuard.tsx
#: src/views/institutionStatusDetails/InstitutionStatusDetails.tsx
msgid "Logo for %1"
msgstr "Logo pour %1"
Expand All @@ -2088,6 +2089,7 @@ msgstr "Succès!"
msgid "No accounts found"
msgstr "Aucun compte trouvé"

#: src/views/demoConnectGuard/DemoConnectGuard.tsx
#: src/views/actionableError/useActionableErrorMap.tsx
msgid "Return to institution selection"
msgstr "Retour à la sélection des établissements"
Expand Down Expand Up @@ -2182,3 +2184,13 @@ msgid ""
msgstr ""
"Pour finaliser votre connexion, veuillez %1partager%2 les informations "
"suivantes après vous être connecté :"

#: src/views/demoConnectGuard/DemoConnectGuard.tsx
msgid "Demo mode active"
msgstr "Mode démo actif"

#: src/views/demoConnectGuard/DemoConnectGuard.tsx
msgid ""
"Live institutions are not available in the demo environment. Please select "
"*MX Bank* to test the connection process."
msgstr "Les établissements réels ne sont pas disponibles dans l'environnement de démonstration. Veuillez sélectionner *MX Bank* pour tester la procédure de connexion."
2 changes: 2 additions & 0 deletions src/hooks/useSelectInstitution.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const useSelectInstitution = () => {
const dispatch = useDispatch()
const consentIsEnabled = useSelector((state: RootState) => isConsentEnabled(state))
const connectConfig = useSelector(selectConnectConfig)
const user = useSelector((state: RootState) => state.profiles.user)

const handleSelectInstitution = useCallback(
(institution: InstitutionResponseType) => {
Expand All @@ -42,6 +43,7 @@ const useSelectInstitution = () => {
institutionStatus,
consentIsEnabled: consentIsEnabled || false,
additionalProductOption: connectConfig?.additional_product_option || null,
user,
},
})
}),
Expand Down
1 change: 1 addition & 0 deletions src/redux/actions/Connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const ActionTypes = {
LOGIN_ERROR_START_OVER: 'connect/login_error_start_over',
CONNECT_GO_BACK: 'connect/go_back',
REJECT_ADDITIONAL_PRODUCT: 'connect/reject_additional_product',
DEMO_CONNECT_GUARD_RETURN_TO_SEARCH: 'connect/demo_connect_guard_return_to_search',
}

export const loadConnect = (config = {}) => ({ type: ActionTypes.LOAD_CONNECT, payload: config })
Expand Down
4 changes: 4 additions & 0 deletions src/redux/reducers/Connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ const selectInstitutionSuccess = (state, action) => {
// 2. Additional product - if the client is offering a product AND the institution has support for the product
// 3. Consent - if the Client has enabled consent
// 4. Institution disabled - if the institution is disabled by the client
// 5. Demo connect guard - if the user is a demo user but the institution is not a demo institution
let nextStep = STEPS.ENTER_CREDENTIALS

const canOfferVerification =
Expand All @@ -292,6 +293,8 @@ const selectInstitutionSuccess = (state, action) => {
action.payload.institutionStatus === InstitutionStatus.UNAVAILABLE)
) {
nextStep = STEPS.INSTITUTION_STATUS_DETAILS
} else if (action.payload.user?.is_demo && !action.payload.institution?.is_demo) {
nextStep = STEPS.DEMO_CONNECT_GUARD
} else if (canOfferVerification || canOfferAggregation) {
nextStep = STEPS.ADDITIONAL_PRODUCT
} else if (action.payload.consentIsEnabled) {
Expand Down Expand Up @@ -733,6 +736,7 @@ export const connect = createReducer(defaultState, {
[ActionTypes.ADD_MANUAL_ACCOUNT_SUCCESS]: addManualAccount,
[ActionTypes.LOGIN_ERROR_START_OVER]: loginErrorStartOver,
[ActionTypes.CONNECT_GO_BACK]: connectGoBack,
[ActionTypes.DEMO_CONNECT_GUARD_RETURN_TO_SEARCH]: goBackSearchOrVerify,

// Addtional product offer / step up reducers
// These are here to manage changing the location/step of the widget
Expand Down
13 changes: 13 additions & 0 deletions src/redux/reducers/__tests__/Connect-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,19 @@ describe('Connect redux store', () => {
STEPS.INSTITUTION_STATUS_DETAILS,
)
})

it('should set the step to DEMO_CONNECT_GUARD when the user is a demo user but the institution is not a demo institution', () => {
const institution = { guid: 'INST-1', is_demo: false, credentials }
const user = { guid: 'USR-1', is_demo: true }
const afterState = reducer(defaultState, {
type: ActionTypes.SELECT_INSTITUTION_SUCCESS,
payload: { institution, user },
})

expect(afterState.location[afterState.location.length - 1].step).toEqual(
STEPS.DEMO_CONNECT_GUARD,
)
})
})

describe('LOAD_CONNECT', () => {
Expand Down
68 changes: 68 additions & 0 deletions src/views/demoConnectGuard/DemoConnectGuard-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react'
import { useDispatch } from 'react-redux'
import { render, screen } from 'src/utilities/testingLibrary'
import { DemoConnectGuard } from './DemoConnectGuard'
import { initialState } from 'src/services/mockedData'
import * as connectActions from 'src/redux/actions/Connect'

// Mock useDispatch
vitest.mock('react-redux', async () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests feel very mocky, so they don't give me much confidence that things will work when they're actually put together. How can you mock as little as possible while ensuring the functionality is tested?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless you have better ideas, I couldn’t think of another way to test the action dispatch without mocking useDispatch.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we can pair on this

const actual = await vitest.importActual('react-redux')
return { ...actual, useDispatch: vitest.fn() }
})
const mockDispatch = vitest.fn()
const mockedUseDispatch = vitest.mocked(useDispatch)

describe('DemoConnectGuard', () => {
const mockInstitution = {
guid: 'INS-test-123',
name: 'Test Bank',
logo_url: 'https://example.com/logo.png',
code: 'TEST',
url: 'https://testbank.com',
}

const mockInitialState = {
...initialState,
connect: {
...initialState.connect,
selectedInstitution: mockInstitution,
},
}

beforeEach(() => {
mockDispatch.mockClear()
mockedUseDispatch.mockReturnValue(mockDispatch)
})

it('renders all component elements correctly', () => {
const { container } = render(<DemoConnectGuard />, { preloadedState: mockInitialState })

expect(screen.getByText('Demo mode active')).toBeInTheDocument()
expect(
screen.getByText(/Live institutions are not available in the demo environment/i),
).toBeInTheDocument()
expect(screen.getByText('MX Bank')).toBeInTheDocument()

const logo = screen.getByAltText('Logo for Test Bank')
expect(logo).toBeInTheDocument()

const errorIcon = container.querySelector('svg.MuiSvgIcon-colorError')
expect(errorIcon).toBeInTheDocument()

const button = screen.getByRole('button', { name: /return to institution selection/i })
expect(button).toBeInTheDocument()
})

it('dispatches the correct action when return button is clicked', async () => {
const { user } = render(<DemoConnectGuard />, { preloadedState: mockInitialState })

const returnButton = screen.getByRole('button', { name: /return to institution selection/i })
await user.click(returnButton)

expect(mockDispatch).toHaveBeenCalledWith({
type: connectActions.ActionTypes.DEMO_CONNECT_GUARD_RETURN_TO_SEARCH,
payload: {},
})
})
})
Loading
Loading