From e109e5018e4cf9131c768c6dd2cd3b20e93a6272 Mon Sep 17 00:00:00 2001 From: michaelroytman Date: Thu, 28 Oct 2021 16:55:14 -0400 Subject: [PATCH] feat: Remove Use of Verified Name Enabled Flag The VERIFIED_NAME_FLAG was added as part https://github.com/edx/edx-name-affirmation/pull/12, [MST-801](https://openedx.atlassian.net/browse/MST-801) in order to control the release of the Verified Name project. It was used for a phased roll out by percentage of users. The release reached a percentage of 50% before it was observed that, due to the way percentage roll out works in django-waffle, the code to create or update VerifiedName records was not working properly. The code was written such that any change to a SoftwareSecurePhotoVerification model instance sent a signal, which was received and handled by the Name Affirmation application. If the VERIFIED_NAME_FLAG was on for the requesting user, a Celery task was launched from the Name Affirmation application to perform the creation of or update to the appropriate VerifiedName model instances based on the verify_student application signal. However, we observed that when SoftwareSecurePhotoVerification records were moved into the "created" or "ready" status, a Celery task in Name Affirmation was created, but when SoftwareSecurePhotoVerification records were moved into the "submitted" status, the corresponding Celery task in Name Affirmation was not created. This caused VerifiedName records to stay in the "pending" state. The django-waffle waffle flag used by the edx-toggle library implements percentage rollout by setting a cookie in a learner's browser session to assign them to the enabled or disabled group. It turns out that the code that submits a SoftwareSecurePhotoVerification record, which moves it into the "submitted" state, happens as part of a Celery task in the verify_student application in the edx-platform. Therefore, we believe that because there is no request object in a Celery task, the edx-toggle code is defaulting to the case where there is no request object. In this case, the code checks whether the flag is enabled for everyone when determining whether the flag is enabled. Because of the percentage rollout (i.e. waffle flag not enabled for everyone), the Celery task in Name Affirmation is not created. This behavior was confirmed by logging added as part of https://github.com/edx/edx-name-affirmation/pull/62. We have determined that we do not need the waffle flag, as we are comfortable that enabling the waffle flag for everyone will fix the issue and are comfortable releasing the feature to all users. For this reason, we are removing references to the flag. [MST-1130](https://openedx.atlassian.net/browse/MST-1130) --- src/account-settings/AccountSettingsPage.jsx | 18 +- .../CertificatePreference.jsx | 5 +- .../test/CertificatePreference.test.jsx | 1 - src/account-settings/data/reducers.js | 1 - src/account-settings/data/selectors.js | 7 - src/account-settings/data/service.js | 13 -- .../IdVerification.messages.js | 55 ------ .../IdVerificationContextProvider.jsx | 16 +- src/id-verification/VerifiedNameContext.jsx | 11 +- src/id-verification/panels/GetNameIdPanel.jsx | 186 +----------------- src/id-verification/panels/SummaryPanel.jsx | 48 ++--- .../IdVerificationContextProvider.test.jsx | 4 +- .../VerifiedNameContextProvider.test.jsx | 31 +-- .../tests/panels/GetNameIdPanel.test.jsx | 71 ++----- .../tests/panels/SummaryPanel.test.jsx | 26 +-- 15 files changed, 52 insertions(+), 441 deletions(-) diff --git a/src/account-settings/AccountSettingsPage.jsx b/src/account-settings/AccountSettingsPage.jsx index 0216fc4ce..5b9b5c223 100644 --- a/src/account-settings/AccountSettingsPage.jsx +++ b/src/account-settings/AccountSettingsPage.jsx @@ -262,7 +262,6 @@ class AccountSettingsPage extends React.Component { renderFullNameHelpText = (status) => { if ( !this.props.verifiedNameHistory - || !this.props.verifiedNameEnabled ) { return this.props.intl.formatMessage(messages['account.settings.field.full.name.help.text']); } @@ -471,7 +470,7 @@ class AccountSettingsPage extends React.Component { // Show State field only if the country is US (could include Canada later) const showState = this.props.formValues.country === COUNTRY_WITH_STATES; - const { verifiedName, verifiedNameEnabled } = this.props; + const { verifiedName } = this.props; const timeZoneOptions = this.getLocalizedTimeZoneOptions( this.props.timeZoneOptions, @@ -484,7 +483,7 @@ class AccountSettingsPage extends React.Component { <>
{ - verifiedNameEnabled && this.props.mostRecentVerifiedName + this.props.mostRecentVerifiedName && this.renderVerifiedNameMessage(this.props.mostRecentVerifiedName) } @@ -512,8 +511,7 @@ class AccountSettingsPage extends React.Component { name="name" type="text" value={ - verifiedNameEnabled - && verifiedName?.status === 'submitted' + verifiedName?.status === 'submitted' && this.props.formValues.pending_name_change ? this.props.formValues.pending_name_change : this.props.formValues.name @@ -525,22 +523,22 @@ class AccountSettingsPage extends React.Component { : this.renderEmptyStaticFieldMessage() } helpText={ - verifiedNameEnabled && verifiedName + verifiedName ? this.renderFullNameHelpText(verifiedName.status) : this.props.intl.formatMessage(messages['account.settings.field.full.name.help.text']) } isEditable={ - verifiedNameEnabled && verifiedName + verifiedName ? this.isEditable('verifiedName') && this.isEditable('name') : this.isEditable('name') } isGrayedOut={ - verifiedNameEnabled && verifiedName && !this.isEditable('verifiedName') + verifiedName && !this.isEditable('verifiedName') } onChange={this.handleEditableFieldChange} onSubmit={this.handleSubmitProfileName} /> - {verifiedNameEnabled && verifiedName + {verifiedName && ( { originalVerifiedName: 'edX Verified', saveState: null, useVerifiedNameForCerts: false, - verifiedNameEnabled: true, intl: {}, }; diff --git a/src/account-settings/data/reducers.js b/src/account-settings/data/reducers.js index d458240b6..6416a7c08 100644 --- a/src/account-settings/data/reducers.js +++ b/src/account-settings/data/reducers.js @@ -39,7 +39,6 @@ export const defaultState = { verifiedName: null, mostRecentVerifiedName: {}, verifiedNameHistory: {}, - verifiedNameEnabled: false, }; const reducer = (state = defaultState, action) => { diff --git a/src/account-settings/data/selectors.js b/src/account-settings/data/selectors.js index 76016cfb8..907869562 100644 --- a/src/account-settings/data/selectors.js +++ b/src/account-settings/data/selectors.js @@ -12,7 +12,6 @@ const verifiedNameSettingsSelector = createSelector( accountSettingsSelector, accountSettings => ({ history: accountSettings.verifiedNameHistory.results, - verifiedNameEnabled: accountSettings?.verifiedNameHistory.verified_name_enabled, useVerifiedNameForCerts: accountSettings?.verifiedNameHistory.use_verified_name_for_certs, }), ); @@ -229,7 +228,6 @@ export const accountSettingsPageSelector = createSelector( mostRecentApprovedVerifiedNameValueSelector, mostRecentVerifiedNameSelector, sortedVerifiedNameHistorySelector, - verifiedNameSettingsSelector, ( accountSettings, siteLanguageOptions, @@ -247,7 +245,6 @@ export const accountSettingsPageSelector = createSelector( verifiedName, mostRecentVerifiedName, verifiedNameHistory, - verifiedNameSettings, ) => ({ siteLanguageOptions, siteLanguage, @@ -268,19 +265,16 @@ export const accountSettingsPageSelector = createSelector( verifiedName, mostRecentVerifiedName, verifiedNameHistory, - verifiedNameEnabled: verifiedNameSettings?.verifiedNameEnabled, }), ); export const certPreferenceSelector = createSelector( - verifiedNameSettingsSelector, valuesSelector, formValuesSelector, mostRecentApprovedVerifiedNameValueSelector, saveStateSelector, errorSelector, ( - verifiedNameSettings, committedValues, formValues, mostRecentApprovedVerifiedNameValue, @@ -291,7 +285,6 @@ export const certPreferenceSelector = createSelector( originalVerifiedName: mostRecentApprovedVerifiedNameValue?.verified_name || '', useVerifiedNameForCerts: formValues.useVerifiedNameForCerts || false, saveState, - verifiedNameEnabled: verifiedNameSettings.verifiedNameEnabled || false, formErrors: errors, }), ); diff --git a/src/account-settings/data/service.js b/src/account-settings/data/service.js index 4e760dd4b..ab5b434a7 100644 --- a/src/account-settings/data/service.js +++ b/src/account-settings/data/service.js @@ -177,19 +177,6 @@ export async function shouldDisplayDemographicsQuestions() { return false; } -export async function getVerifiedNameEnabled() { - let data; - const client = getAuthenticatedHttpClient(); - try { - const requestUrl = `${getConfig().LMS_BASE_URL}/api/edx_name_affirmation/v1/verified_name_enabled`; - ({ data } = await client.get(requestUrl)); - } catch (error) { - return {}; - } - - return data; -} - export async function getVerifiedName() { let data; const client = getAuthenticatedHttpClient(); diff --git a/src/id-verification/IdVerification.messages.js b/src/id-verification/IdVerification.messages.js index cc3b4dfa6..da7f23443 100644 --- a/src/id-verification/IdVerification.messages.js +++ b/src/id-verification/IdVerification.messages.js @@ -521,21 +521,11 @@ const messages = defineMessages({ defaultMessage: 'The file you have selected is too large. Please try again with a file less than 10MB.', description: 'Error message for file upload that is larger than 10MB.', }, - 'id.verification.account.name.title': { - id: 'id.verification.account.name.title', - defaultMessage: 'Account Name Check', - description: 'Title for the Account Name Check page.', - }, 'id.verification.name.check.title': { id: 'id.verification.name.check.title', defaultMessage: 'Double-Check Your Name', description: 'Title for the page where a user double-checks that their name is correct.', }, - 'id.verification.account.name.instructions': { - id: 'id.verification.account.name.instructions', - defaultMessage: 'The name on your account and the name on your ID must be an exact match. If not, please click "No" to update your account name.', - description: 'Text to verify that the account name matches the name on the ID photo.', - }, 'id.verification.name.check.instructions': { id: 'id.verification.name.check.instructions', defaultMessage: 'Does the name below match the name on your government-issued ID? If not, update the name below to match your goverment-issued ID.', @@ -546,41 +536,6 @@ const messages = defineMessages({ defaultMessage: 'If the name below does not match your government-issued ID, your identity verification will be denied.', description: 'Text to inform the user that if the name displayed on the page does not match what is on their government-issued ID, identity verification will be denied.', }, - 'id.verification.account.name.radio.label': { - id: 'id.verification.account.name.radio.label', - defaultMessage: 'Does the name on your ID match the Account Name below?', - description: 'Question to ask the user whether their account name match the name on their ID card.', - }, - 'id.verification.name.check.radio.label': { - id: 'id.verification.name.check.radio.label', - defaultMessage: 'Select an option', - description: 'Label for a radio button group where the user needs to choose one of two options.', - }, - 'id.verification.account.name.radio.yes': { - id: 'id.verification.account.name.radio.yes', - defaultMessage: 'Yes', - description: 'The radio button that says the account name matches.', - }, - 'id.verification.name.check.radio.yes': { - id: 'id.verification.name.check.radio.yes', - defaultMessage: 'Yes, the name below matches my ID', - description: 'Label for a radio button that indicates that the name displayed on the page matches the name on the user\'s ID.', - }, - 'id.verification.account.name.radio.no': { - id: 'id.verification.account.name.radio.no', - defaultMessage: 'No', - description: 'The radio button that says the account name does not match.', - }, - 'id.verification.name.check.radio.no': { - id: 'id.verification.name.check.radio.no', - defaultMessage: 'No, the name below does not match my ID', - description: 'Label for a radio button that indicates that the name displayed on the page does not match the name on the user\'s ID.', - }, - 'id.verification.account.name.error': { - id: 'id.verification.account.name.error', - defaultMessage: 'Please update account name to match the name on your ID.', - description: 'Error that shows when the user needs to update their account name to match the name on their ID.', - }, 'id.verification.name.error': { id: 'id.verification.name.error', defaultMessage: 'Please enter your name as it appears on your government-issued ID.', @@ -596,11 +551,6 @@ const messages = defineMessages({ defaultMessage: 'Account Settings', description: 'Link to Account Settings.', }, - 'id.verification.account.name.label': { - id: 'id.verification.account.name.label', - defaultMessage: 'Account Name', - description: 'Label for account name input.', - }, 'id.verification.name.label': { id: 'id.verification.name.label', defaultMessage: 'Name', @@ -611,11 +561,6 @@ const messages = defineMessages({ defaultMessage: 'Photo of your ID to be submitted.', description: 'Alt text for the photo of the user\'s ID.', }, - 'id.verification.account.name.save': { - id: 'id.verification.account.name.save', - defaultMessage: 'Save and Next', - description: 'Button to save the account name.', - }, 'id.verification.review.title': { id: 'id.verification.review.title', defaultMessage: 'Review Your Photos', diff --git a/src/id-verification/IdVerificationContextProvider.jsx b/src/id-verification/IdVerificationContextProvider.jsx index bb7eb1f53..62584f0ae 100644 --- a/src/id-verification/IdVerificationContextProvider.jsx +++ b/src/id-verification/IdVerificationContextProvider.jsx @@ -15,7 +15,7 @@ import { VerifiedNameContext } from './VerifiedNameContext'; export default function IdVerificationContextProvider({ children }) { const { authenticatedUser } = useContext(AppContext); - const { verifiedNameHistoryCallStatus, verifiedName, verifiedNameEnabled } = useContext(VerifiedNameContext); + const { verifiedNameHistoryCallStatus, verifiedName } = useContext(VerifiedNameContext); const idVerificationData = useAsyncCall(getExistingIdVerification); const enrollmentsData = useAsyncCall(getEnrollments); @@ -64,20 +64,6 @@ export default function IdVerificationContextProvider({ children }) { existingIdVerification = idVerificationData.data; } - if (verifiedNameHistoryCallStatus === SUCCESS_STATUS && idVerificationData.status === SUCCESS_STATUS) { - // With verified name we can redo verification multiple times - // if not a successful request prevents re-verification - if (!verifiedNameEnabled && existingIdVerification && !existingIdVerification.canVerify) { - const { status } = existingIdVerification; - canVerify = false; - if (status === 'pending' || status === 'approved') { - error = ERROR_REASONS.EXISTING_REQUEST; - } else { - error = ERROR_REASONS.CANNOT_VERIFY; - } - } - } - if (enrollmentsData.status === SUCCESS_STATUS && enrollmentsData?.data) { const verifiedEnrollments = enrollmentsData.data.filter((enrollment) => ( VERIFIED_MODES.includes(enrollment.mode) diff --git a/src/id-verification/VerifiedNameContext.jsx b/src/id-verification/VerifiedNameContext.jsx index 223405a4c..6ff040c49 100644 --- a/src/id-verification/VerifiedNameContext.jsx +++ b/src/id-verification/VerifiedNameContext.jsx @@ -11,22 +11,15 @@ export const VerifiedNameContext = createContext(); export function VerifiedNameContextProvider({ children }) { const verifiedNameHistoryData = useAsyncCall(getVerifiedNameHistory); - let verifiedNameEnabled = false; let verifiedName = ''; const { status, data } = verifiedNameHistoryData; if (status === SUCCESS_STATUS && data) { - const { verified_name_enabled: verifiedNameFeatureEnabled, results } = data; - verifiedNameEnabled = verifiedNameFeatureEnabled; - - if (verifiedNameFeatureEnabled) { - const applicableVerifiedName = getMostRecentApprovedOrPendingVerifiedName(results); - verifiedName = applicableVerifiedName; - } + const { results } = data; + verifiedName = getMostRecentApprovedOrPendingVerifiedName(results); } const value = { verifiedNameHistoryCallStatus: status, - verifiedNameEnabled, verifiedName, }; diff --git a/src/id-verification/panels/GetNameIdPanel.jsx b/src/id-verification/panels/GetNameIdPanel.jsx index eadb27e2f..a7b7f473d 100644 --- a/src/id-verification/panels/GetNameIdPanel.jsx +++ b/src/id-verification/panels/GetNameIdPanel.jsx @@ -1,20 +1,17 @@ import React, { - useContext, useState, useEffect, useRef, + useContext, useEffect, useRef, } from 'react'; -import { getConfig } from '@edx/frontend-platform'; -import { Hyperlink, Form } from '@edx/paragon'; +import { Form } from '@edx/paragon'; import { Link, useHistory } from 'react-router-dom'; -import { sendTrackEvent } from '@edx/frontend-platform/analytics'; -import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n'; +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; import { useNextPanelSlug } from '../routing-utilities'; import BasePanel from './BasePanel'; import IdVerificationContext from '../IdVerificationContext'; -import { VerifiedNameContext } from '../VerifiedNameContext'; import messages from '../IdVerification.messages'; -function GetNameIdPanelVerified(props) { +function GetNameIdPanel(props) { const { push, location } = useHistory(); const nameInputRef = useRef(); const panelSlug = 'get-name-id'; @@ -94,180 +91,7 @@ function GetNameIdPanelVerified(props) { ); } -function GetNameIdPanelNonVerified(props) { - const { push } = useHistory(); - const panelSlug = 'get-name-id'; - const [nameMatches, setNameMatches] = useState(true); - const nameInputRef = useRef(); - const nextPanelSlug = useNextPanelSlug(panelSlug); - - const { - nameOnAccount, userId, profileDataManager, idPhotoName, setIdPhotoName, - } = useContext(IdVerificationContext); - const nameOnAccountValue = nameOnAccount || ''; - const invalidName = !nameMatches && (!idPhotoName || idPhotoName === nameOnAccount); - const blankName = !nameOnAccount && !idPhotoName; - - useEffect(() => { - setIdPhotoName(null); - }, []); - - useEffect(() => { - if (!nameMatches && nameInputRef.current) { - nameInputRef.current.focus(); - } - if (!nameMatches) { - sendTrackEvent('edx.id_verification.name_change', { - category: 'id_verification', - user_id: userId, - }); - } - if (blankName) { - setNameMatches(false); - } - }, [nameMatches, blankName]); - - function getNameValue() { - if (!nameMatches) { - // Explicitly check for null, as an empty string should still be used here - if (idPhotoName === null) { - return nameOnAccountValue; - } - return idPhotoName; - } - return nameOnAccountValue; - } - - function getErrorMessage() { - if (profileDataManager) { - return ( - {profileDataManager}, - profileDataManager, - support: ( - - {props.intl.formatMessage(messages['id.verification.support'])} - - ), - }} - /> - ); - } - return props.intl.formatMessage(messages['id.verification.account.name.error']); - } - - function handleSubmit(e) { - e.preventDefault(); - // If the input is empty, or if no changes have been made to the - // mismatching name, the user should not be able to proceed. - if (!invalidName && !blankName) { - push(nextPanelSlug); - } - } - - return ( - -

- {props.intl.formatMessage(messages['id.verification.account.name.instructions'])} -

- -
- - - {props.intl.formatMessage(messages['id.verification.account.name.radio.label'])} - - { - setNameMatches(true); - setIdPhotoName(null); - }} - /> - setNameMatches(false)} - /> - - - - {props.intl.formatMessage(messages['id.verification.account.name.label'])} - - setIdPhotoName(e.target.value)} - data-testid="name-input" - /> - {(invalidName || !!profileDataManager) && ( - - {getErrorMessage()} - - )} - -
- -
- - { - !nameMatches - ? props.intl.formatMessage(messages['id.verification.account.name.save']) - : props.intl.formatMessage(messages['id.verification.next']) - } - -
-
- ); -} - -function GetNameIdPanel(props) { - const { verifiedNameEnabled } = useContext(VerifiedNameContext); - - if (verifiedNameEnabled) { - return ; - } - - return ; -} - -GetNameIdPanelVerified.propTypes = { - intl: intlShape.isRequired, -}; - -GetNameIdPanelNonVerified.propTypes = { +GetNameIdPanel.propTypes = { intl: intlShape.isRequired, }; diff --git a/src/id-verification/panels/SummaryPanel.jsx b/src/id-verification/panels/SummaryPanel.jsx index bf54e1949..05d501da8 100644 --- a/src/id-verification/panels/SummaryPanel.jsx +++ b/src/id-verification/panels/SummaryPanel.jsx @@ -11,7 +11,6 @@ import { useNextPanelSlug } from '../routing-utilities'; import BasePanel from './BasePanel'; import IdVerificationContext from '../IdVerificationContext'; import ImagePreview from '../ImagePreview'; -import { VerifiedNameContext } from '../VerifiedNameContext'; import messages from '../IdVerification.messages'; import CameraHelpWithUpload from '../CameraHelpWithUpload'; @@ -32,7 +31,6 @@ function SummaryPanel(props) { portraitPhotoMode, idPhotoMode, } = useContext(IdVerificationContext); - const { verifiedNameEnabled } = useContext(VerifiedNameContext); const nameToBeUsed = idPhotoName || nameOnAccount || ''; const [isSubmitting, setIsSubmitting] = useState(false); const [submissionError, setSubmissionError] = useState(null); @@ -74,17 +72,10 @@ function SummaryPanel(props) { }; if (idPhotoName) { verificationData.idPhotoName = idPhotoName; - } else if (verifiedNameEnabled) { + } else { /** * If learner has not entered an idPhotoName on the GetNameIdPanel, - * and the verified name feature is enabled, use the current nameOnAccount - * when submitting IDV. The reason we only do this if the feature is enabled - * is that, when the feature is off, the server will change the learner's - * profile name to this value. If we send the idPhotoName on all requests, - * even ones where the learner does not change the idPhotoName, then the - * server will record that the full name on the learner's profile has - * a requested change, even if the name is the same. This will pollute - * the history. + * use the current nameOnAccount when submitting IDV. */ verificationData.idPhotoName = nameOnAccount; } @@ -220,9 +211,7 @@ function SummaryPanel(props) { {!optimizelyExperimentName && }
{renderManagedProfileMessage()}
@@ -242,29 +231,14 @@ function SummaryPanel(props) { state: { fromSummary: true }, }} > - { - verifiedNameEnabled - ? ( - Name, - }} - /> - ) - : ( - Account Name, - }} - /> - ) - } + Name, + }} + /> )}
diff --git a/src/id-verification/tests/IdVerificationContextProvider.test.jsx b/src/id-verification/tests/IdVerificationContextProvider.test.jsx index 26a9cf3b5..a2c0f57f3 100644 --- a/src/id-verification/tests/IdVerificationContextProvider.test.jsx +++ b/src/id-verification/tests/IdVerificationContextProvider.test.jsx @@ -32,7 +32,7 @@ describe('IdVerificationContextProvider', () => { it('renders correctly and calls getExistingIdVerification + getEnrollments', async () => { const appContext = { authenticatedUser: { userId: 3, roles: [] } }; - const verifiedNameContext = { verifiedName: '', verifiedNameEnabled: false }; + const verifiedNameContext = { verifiedName: '' }; await act(async () => render(( @@ -54,7 +54,7 @@ describe('IdVerificationContextProvider', () => { roles: ['enterprise_learner'], }, }; - const verifiedNameContext = { verifiedName: '', verifiedNameEnabled: false }; + const verifiedNameContext = { verifiedName: '' }; await act(async () => render(( diff --git a/src/id-verification/tests/VerifiedNameContextProvider.test.jsx b/src/id-verification/tests/VerifiedNameContextProvider.test.jsx index 6959ba9cd..4a73ea8a5 100644 --- a/src/id-verification/tests/VerifiedNameContextProvider.test.jsx +++ b/src/id-verification/tests/VerifiedNameContextProvider.test.jsx @@ -5,11 +5,10 @@ import { getVerifiedNameHistory } from '../../account-settings/data/service'; import { VerifiedNameContext, VerifiedNameContextProvider } from '../VerifiedNameContext'; const VerifiedNameContextTestComponent = () => { - const { verifiedName, verifiedNameEnabled } = useContext(VerifiedNameContext); + const { verifiedName } = useContext(VerifiedNameContext); return ( <> - {verifiedNameEnabled && (
{verifiedName}
)} -
{verifiedNameEnabled ? 'true' : 'false'}
+ {verifiedName && (
{verifiedName}
)} ); }; @@ -38,9 +37,8 @@ describe('VerifiedNameContextProvider', () => { await waitFor(() => expect(getVerifiedNameHistory).toHaveBeenCalledTimes(1)); }); - it('sets verifiedName and verifiedNameEnabled correctly when verified name feature enabled', async () => { + it('sets verifiedName', async () => { const mockReturnValue = { - verified_name_enabled: true, results: [{ verified_name: 'Michael', status: 'approved', @@ -57,28 +55,5 @@ describe('VerifiedNameContextProvider', () => { await waitFor(() => expect(getVerifiedNameHistory).toHaveBeenCalledTimes(1)); expect(getByTestId('verified-name')).toHaveTextContent('Michael'); - expect(getByTestId('verified-name-enabled')).toHaveTextContent('true'); - }); - - it('sets verifiedName and verifiedNameEnabled correctly when verified name feature not enabled', async () => { - const mockReturnValue = { - verified_name_enabled: false, - results: [{ - verified_name: 'Michael', - status: 'approved', - created: '2021-08-31T18:33:32.489200Z', - }], - }; - getVerifiedNameHistory.mockReturnValueOnce(mockReturnValue); - - const { queryByTestId } = render(( - - - - )); - - await waitFor(() => expect(getVerifiedNameHistory).toHaveBeenCalledTimes(1)); - expect(queryByTestId('verified-name')).toBeNull(); - expect(queryByTestId('verified-name-enabled')).toHaveTextContent('false'); }); }); diff --git a/src/id-verification/tests/panels/GetNameIdPanel.test.jsx b/src/id-verification/tests/panels/GetNameIdPanel.test.jsx index 6507f65aa..d26dd2cc1 100644 --- a/src/id-verification/tests/panels/GetNameIdPanel.test.jsx +++ b/src/id-verification/tests/panels/GetNameIdPanel.test.jsx @@ -32,16 +32,14 @@ describe('GetNameIdPanel', () => { idPhotoFile: 'test.jpg', }; - const verifiedNameContextValue = { - verifiedNameEnabled: false, - }; + const verifiedNameContextValue = {}; - const getPanel = async () => { + const getPanel = async (idVerificationContextValue = IDVerificationContextValue) => { await act(async () => render(( - + @@ -54,65 +52,28 @@ describe('GetNameIdPanel', () => { cleanup(); }); - it('edits', async () => { + it('shows feedback message when user has an empty name', async () => { await getPanel(); - - const yesButton = await screen.findByTestId('name-matches-yes'); - const noButton = await screen.findByTestId('name-matches-no'); - const input = await screen.findByTestId('name-input'); - const nextButton = await screen.findByTestId('next-button'); - const errorMessageQuery = await screen.queryByTestId('id-name-feedback-message'); - - expect(input).toHaveAttribute('readonly'); - expect(errorMessageQuery).toBeNull(); - - fireEvent.click(noButton); - expect(input).not.toHaveAttribute('readonly'); - expect(nextButton.classList.contains('disabled')).toBe(true); - expect(nextButton).toHaveAttribute('aria-disabled'); - - fireEvent.change(input, { target: { value: 'test change' } }); - expect(IDVerificationContextValue.setIdPhotoName).toHaveBeenCalled(); - // Ensure the feedback message on name shows when the user says the name does not match ID + // Ensure the feedback message on name shows when the user has an empty name expect(await screen.queryByTestId('id-name-feedback-message')).toBeTruthy(); - - fireEvent.click(yesButton); - expect(input).toHaveAttribute('readonly'); - expect(IDVerificationContextValue.setIdPhotoName).toHaveBeenCalled(); }); - it('disables radio buttons + next button and enables input if account name is blank', async () => { - IDVerificationContextValue.nameOnAccount = ''; - await getPanel(); - - const yesButton = await screen.findByTestId('name-matches-yes'); - const noButton = await screen.findByTestId('name-matches-no'); - const input = await screen.findByTestId('name-input'); - const nextButton = await screen.findByTestId('next-button'); - const errorMessageQuery = await screen.queryByTestId('id-name-feedback-message'); - - expect(yesButton).toBeDisabled(); - expect(noButton).toBeDisabled(); - expect(input).not.toHaveAttribute('readonly'); - expect(nextButton.classList.contains('disabled')).toBe(true); - expect(nextButton).toHaveAttribute('aria-disabled'); - expect(errorMessageQuery).toBeTruthy(); + it('does not show feedback message when user has an non-empty name', async () => { + const idVerificationContextValue = { + ...IDVerificationContextValue, + idPhotoName: 'test', + }; + await getPanel(idVerificationContextValue); + // Ensure the feedback message on name shows when the user has an empty name + expect(await screen.queryByTestId('id-name-feedback-message')).toBeNull(); }); - it('blocks the user from changing account name if managed by a third party', async () => { - IDVerificationContextValue.profileDataManager = 'test-org'; + it('calls setIdPhotoName with correct name', async () => { await getPanel(); - const noButton = await screen.findByTestId('name-matches-no'); const input = await screen.findByTestId('name-input'); - const nextButton = await screen.findByTestId('next-button'); - - fireEvent.click(noButton); - expect(input).toHaveAttribute('readonly'); - expect(nextButton.classList.contains('disabled')).toBe(true); - expect(nextButton).toHaveAttribute('aria-disabled'); - const warning = await screen.getAllByText('test-org'); - expect(warning.length).toEqual(1); + fireEvent.change(input, { target: { value: 'test' } }); + expect(IDVerificationContextValue.setIdPhotoName).toHaveBeenCalledWith('test'); }); it('routes to SummaryPanel', async () => { diff --git a/src/id-verification/tests/panels/SummaryPanel.test.jsx b/src/id-verification/tests/panels/SummaryPanel.test.jsx index adb3d317b..1f2294b3e 100644 --- a/src/id-verification/tests/panels/SummaryPanel.test.jsx +++ b/src/id-verification/tests/panels/SummaryPanel.test.jsx @@ -39,9 +39,7 @@ describe('SummaryPanel', () => { setReachedSummary: jest.fn(), }; - const verifiedNameContextValue = { - verifiedNameEnabled: false, - }; + const verifiedNameContextValue = {}; const getPanel = async () => { await act(async () => render(( @@ -111,7 +109,7 @@ describe('SummaryPanel', () => { await waitFor(() => expect(appContextValue.stopUserMedia).toHaveBeenCalled()); }); - it('does not submit a name if name is blank', async () => { + it('submits a name if name is blank', async () => { appContextValue.idPhotoName = ''; const verificationData = { facePhotoFile: appContextValue.facePhotoFile, @@ -120,6 +118,7 @@ describe('SummaryPanel', () => { idPhotoMode: appContextValue.idPhotoMode, optimizelyExperimentName: appContextValue.optimizelyExperimentName, courseRunKey: null, + idPhotoName: appContextValue.nameOnAccount, }; await getPanel(); const button = await screen.findByTestId('submit-button'); @@ -127,25 +126,8 @@ describe('SummaryPanel', () => { expect(dataService.submitIdVerification).toHaveBeenCalledWith(verificationData); }); - it('does not submit a name if name is unchanged', async () => { - appContextValue.idPhotoName = null; - const verificationData = { - facePhotoFile: appContextValue.facePhotoFile, - idPhotoFile: appContextValue.idPhotoFile, - portraitPhotoMode: appContextValue.portraitPhotoMode, - idPhotoMode: appContextValue.idPhotoMode, - optimizelyExperimentName: appContextValue.optimizelyExperimentName, - courseRunKey: null, - }; - await getPanel(); - const button = await screen.findByTestId('submit-button'); - fireEvent.click(button); - expect(dataService.submitIdVerification).toHaveBeenCalledWith(verificationData); - }); - - it('submits a name if a name is unchanged if verified name feature is enabled', async () => { + it('submits a name if a name is unchanged', async () => { appContextValue.idPhotoName = null; - verifiedNameContextValue.verifiedNameEnabled = true; const verificationData = { facePhotoFile: appContextValue.facePhotoFile, idPhotoFile: appContextValue.idPhotoFile,