Skip to content
Merged
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## v.0.9.3

### Added

- Adding a UCP specific variable to the connection success event

## v.0.9.2

### Added
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@mxenabled/connect-widget",
"description": "A simple ui library for React",
"version": "0.9.2",
"version": "0.9.3",
"module": "dist/index.es.js",
"types": "dist/index.d.ts",
"type": "module",
Expand Down
4 changes: 2 additions & 2 deletions src/components/RenderConnectStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useTokens } from '@kyper/tokenprovider'
import * as connectActions from 'src/redux/actions/Connect'

import { getSize } from 'src/redux/selectors/Browser'
import { getCurrentMember, getMembers } from 'src/redux/selectors/Connect'
import { getCurrentMember, getMembers, getSelectedInstitution } from 'src/redux/selectors/Connect'
import {
selectConnectConfig,
selectIsMobileWebView,
Expand Down Expand Up @@ -57,7 +57,7 @@ const RenderConnectStep = (props) => {
)
const connectedMembers = useSelector(getMembers)
const currentMember = useSelector(getCurrentMember)
const selectedInstitution = useSelector((state) => state.connect.selectedInstitution)
const selectedInstitution = useSelector(getSelectedInstitution)
const updateCredentials = useSelector((state) => state.connect.updateCredentials)
const verifyMemberError = useSelector((state) => state.connect.error)

Expand Down
4 changes: 2 additions & 2 deletions src/hooks/__tests__/useSelectInstitution-test.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from 'react'
import { useSelector } from 'react-redux'
import type { RootState } from 'src/redux/Store'
import { screen, render } from 'src/utilities/testingLibrary'
import useSelectInstitution from 'src/hooks/useSelectInstitution'
import { institutionData } from 'src/services/mockedData'
import { getSelectedInstitution } from 'src/redux/selectors/Connect'

const TestSelectInstitutionComponent = () => {
const selectedInstitution = useSelector((state: RootState) => state.connect.selectedInstitution)
const selectedInstitution = useSelector(getSelectedInstitution)
const { handleSelectInstitution } = useSelectInstitution()
return (
<div>
Expand Down
25 changes: 23 additions & 2 deletions src/redux/selectors/Connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,34 @@ const getMemberByGuid = (members, guid) => {
/**
* Selectors
*/

const getConnectSlice = createSelector(
(state) => state,
(state) => state.connect,
)

const getMembersRaw = createSelector(getConnectSlice, (slice) => slice.members)

export const getCurrentMember = createSelector(
(state) => state.connect.members,
getMembersRaw,
(state) => state.connect.currentMemberGuid,
getMemberByGuid,
)

export const getMembers = createSelector(
(state) => state.connect.members,
getMembersRaw,
(members) =>
members?.filter((member) => !(member.connection_status === ReadableStatuses.PENDING)) ?? [],
)

export const getSelectedInstitution = createSelector(
getConnectSlice,
(slice) => slice.selectedInstitution,
)

export const getSelectedInstitutionUcpInstitutionId = createSelector(
getSelectedInstitution,
(selectedInstitution) => {
return selectedInstitution?.ucpInstitutionId
},
)
63 changes: 61 additions & 2 deletions src/redux/selectors/__tests__/Connect-test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
import * as ConnectSelectors from 'src/redux/selectors/Connect'
import { genMember } from 'src/utilities/generators/Members'
import {
getCurrentMember,
getMembers,
getSelectedInstitution,
getSelectedInstitutionUcpInstitutionId,
} from '../Connect'
import { ReadableStatuses } from 'src/const/Statuses'

const ucpInstitutionId = 'testUcpInstitutionId'

const stateWithASelectedInstitution = {
connect: {
selectedInstitution: {
ucpInstitutionId,
},
},
}

describe('Connect Selectors', () => {
describe('getCurrentMember', () => {
Expand All @@ -10,9 +26,52 @@ describe('Connect Selectors', () => {
members: [genMember({ guid: 'MBR-1' }), genMember({ guid: 'MBR-2' })],
},
}
const currentMember = ConnectSelectors.getCurrentMember(state)
const currentMember = getCurrentMember(state)

expect(currentMember.guid).toEqual('MBR-1')
})
})

describe('getMembers', () => {
it("returns an empty array if members doesn't exist", () => {
const state = {
connect: {},
}

expect(getMembers(state)).toEqual([])
})

it("returns any members that aren't pending", () => {
const memberThatIsPending = genMember({
connection_status: ReadableStatuses.PENDING,
})
const memberThatIsntPending = genMember({
connection_status: ReadableStatuses.CHALLENGED,
})

const state = {
connect: {
members: [memberThatIsPending, memberThatIsntPending],
},
}

expect(getMembers(state)).toEqual([memberThatIsntPending])
})
})

describe('getSelectedInstitution', () => {
it('returns the selected institution', () => {
expect(getSelectedInstitution(stateWithASelectedInstitution)).toEqual(
stateWithASelectedInstitution.connect.selectedInstitution,
)
})
})

describe('getSelectedInstitutionUcpInstitutionId', () => {
it("returns the selected institution's ucpId", () => {
expect(getSelectedInstitutionUcpInstitutionId(stateWithASelectedInstitution)).toEqual(
ucpInstitutionId,
)
})
})
})
12 changes: 11 additions & 1 deletion src/views/connecting/Connecting.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ import * as JobSchedule from 'src/utilities/JobSchedule'
import { AriaLive } from 'src/components/AriaLive'
import useAnalyticsPath from 'src/hooks/useAnalyticsPath'
import { useApi } from 'src/context/ApiContext'
import { getCurrentMember } from 'src/redux/selectors/Connect'
import {
getCurrentMember,
getSelectedInstitutionUcpInstitutionId,
} from 'src/redux/selectors/Connect'
import { isConnectComboJobsEnabled } from 'src/redux/reducers/userFeaturesSlice'

import { ErrorStatuses, ReadableStatuses } from 'src/const/Statuses'
Expand Down Expand Up @@ -69,6 +72,9 @@ export const Connecting = (props) => {
const styles = getStyles(tokens)
const getNextDelay = getDelay()
const dispatch = useDispatch()

const ucpInstitutionId = useSelector(getSelectedInstitutionUcpInstitutionId)

const analyticFunctions = useContext(AnalyticContext)
const postMessageFunctions = useContext(PostMessageContext)
const connectingRef = useRef(null)
Expand Down Expand Up @@ -125,6 +131,10 @@ export const Connecting = (props) => {
event.aggregator = currentMember.aggregator
}

if (ucpInstitutionId) {
event.ucpInstitutionId = ucpInstitutionId
}

postMessageFunctions.onPostMessage(POST_MESSAGES.MEMBER_CONNECTED, event)
analyticFunctions.onAnalyticEvent(`connect_${POST_MESSAGES.MEMBER_CONNECTED}`, {
type: connectConfig.is_mobile_webview ? 'url' : 'message',
Expand Down
3 changes: 2 additions & 1 deletion src/views/credentials/CreateMemberForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { LoadingSpinner } from 'src/components/LoadingSpinner'
import { ReadableStatuses } from 'src/const/Statuses'

import { PostMessageContext } from 'src/ConnectWidget'
import { getSelectedInstitution } from 'src/redux/selectors/Connect'

/**
* Responsibilities:
Expand All @@ -23,7 +24,7 @@ import { PostMessageContext } from 'src/ConnectWidget'
* - Performs the CREATE
*/
export const CreateMemberForm = (props) => {
const institution = useSelector((state) => state.connect.selectedInstitution)
const institution = useSelector(getSelectedInstitution)
useAnalyticsPath(...PageviewInfo.CONNECT_CREATE_CREDENTIALS, {
institution_guid: institution.guid,
institution_name: institution.name,
Expand Down
4 changes: 2 additions & 2 deletions src/views/credentials/Credentials.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { InstitutionBlock } from 'src/components/InstitutionBlock'
import { InstructionalText } from 'src/components/InstructionalText'
import { InstructionList } from 'src/components/InstructionList'
import { Support, VIEWS as SUPPORT_VIEWS } from 'src/components/support/Support'
import { getCurrentMember } from 'src/redux/selectors/Connect'
import { getCurrentMember, getSelectedInstitution } from 'src/redux/selectors/Connect'

import { buildInitialValues, buildFormSchema } from 'src/views/credentials/utils'
import { CREDENTIAL_FIELD_TYPES } from 'src/views/credentials/consts'
Expand Down Expand Up @@ -77,7 +77,7 @@ export const Credentials = React.forwardRef(
// Redux Selectors/Dispatch
const connectConfig = useSelector(selectConnectConfig)
const isSmall = useSelector((state) => state.browser.size) === 'small'
const institution = useSelector((state) => state.connect.selectedInstitution)
const institution = useSelector(getSelectedInstitution)
const showExternalLinkPopup = useSelector(
(state) => state.profiles.clientProfile.show_external_link_popup,
)
Expand Down
4 changes: 2 additions & 2 deletions src/views/credentials/UpdateMemberForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useDispatch, useSelector } from 'react-redux'
import { useApi } from 'src/context/ApiContext'
import useAnalyticsPath from 'src/hooks/useAnalyticsPath'
import { PageviewInfo } from 'src/const/Analytics'
import { getCurrentMember } from 'src/redux/selectors/Connect'
import { getCurrentMember, getSelectedInstitution } from 'src/redux/selectors/Connect'
import { ActionTypes } from 'src/redux/actions/Connect'
import { selectConfig } from 'src/redux/reducers/configSlice'

Expand All @@ -23,7 +23,7 @@ import { PostMessageContext } from 'src/ConnectWidget'
*/
export const UpdateMemberForm = (props) => {
useAnalyticsPath(...PageviewInfo.CONNECT_UPDATE_CREDENTIALS)
const institution = useSelector((state) => state.connect.selectedInstitution)
const institution = useSelector(getSelectedInstitution)
const currentMember = useSelector(getCurrentMember)
const config = useSelector(selectConfig)
const isHuman = useSelector((state) => state.app.humanEvent)
Expand Down
3 changes: 2 additions & 1 deletion src/views/disclosure/Interstitial.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { ConnectLogoHeader } from 'src/components/ConnectLogoHeader'
import { PrivacyPolicy } from 'src/views/disclosure/PrivacyPolicy'
import { DataRequested } from 'src/views/disclosure/DataRequested'
import { DataAvailable } from 'src/views/disclosure/DataAvailable'
import { getSelectedInstitution } from 'src/redux/selectors/Connect'

export const VIEWS = {
AVAILABLE_DATA: 'available_data',
Expand All @@ -35,7 +36,7 @@ export const DisclosureInterstitial = React.forwardRef((props, interstitialNavRe
const tokens = useTokens()
const styles = getStyles(tokens)
const getNextDelay = getDelay()
const institution = useSelector((state) => state.connect.selectedInstitution)
const institution = useSelector(getSelectedInstitution)
const appName = useSelector((state) => state.profiles.client.oauth_app_name || null)

const [currentView, setCurrentView] = useState(VIEWS.INTERSTITIAL_DISCLOSURE)
Expand Down
4 changes: 2 additions & 2 deletions src/views/loginError/NoEligibleAccountsError.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Button } from '@mui/material'
import { __ } from 'src/utilities/Intl'
import { ActionTypes } from 'src/redux/actions/Connect'

import { getCurrentMember } from 'src/redux/selectors/Connect'
import { getCurrentMember, getSelectedInstitution } from 'src/redux/selectors/Connect'

import { AriaLive } from 'src/components/AriaLive'
import { SlideDown } from 'src/components/SlideDown'
Expand All @@ -27,7 +27,7 @@ export const NoEligibleAccounts = () => {
const dispatch = useDispatch()

const currentMember = useSelector(getCurrentMember)
const selectedInstitution = useSelector((state) => state.connect.selectedInstitution)
const selectedInstitution = useSelector(getSelectedInstitution)

const postHogEventMetadata = {
authentication_method: currentMember.is_oauth
Expand Down
3 changes: 2 additions & 1 deletion src/views/oauth/OAuthError.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ import { InstitutionBlock } from 'src/components/InstitutionBlock'
import { SlideDown } from 'src/components/SlideDown'
import { getDelay } from 'src/utilities/getDelay'
import { PostMessageContext } from 'src/ConnectWidget'
import { getSelectedInstitution } from 'src/redux/selectors/Connect'

export const OAuthError = React.forwardRef((props, navigationRef) => {
useAnalyticsPath(...PageviewInfo.CONNECT_OAUTH_ERROR)
const { currentMember, onRetry, onReturnToSearch } = props

const postMessageFunctions = useContext(PostMessageContext)
const errorReason = useSelector((state) => state.connect.oauthErrorReason)
const selectedInstitution = useSelector((state) => state.connect.selectedInstitution)
const selectedInstitution = useSelector(getSelectedInstitution)
const tokens = useTokens()
const styles = getStyles(tokens)
const getNextDelay = getDelay()
Expand Down