Przeglądaj źródła

[web] Replace token-link validation on reconfirm affiliation notifications (#27250)

* Update Reconfirm Affiliation (Pug) in Portal page

Change the notification so it directs users to the settings page instead of triggering an email confirmation with token-link

* Update Reconfirm Affiliation (React) in Settings page

Update the component so it sends the 6-digits code and opens the modal to enter it

* Update Reconfirm Affiliation (React) in Projects page

Update the component so it sends the 6-digits code and opens the modal to enter it

* `cleanup_unused_locales`

* `bin/run web npm run extract-translations`

* Update tests

* Minor updates in tests

* Update Pug notifications with the notification mixin

* De-center the "reconfirmed notification"

* Update "Learn more" links to "Learn more about institutional email reconfirmation"

* Update tests

GitOrigin-RevId: cb65623e209217614786eec56f7f5d28b9e8cec5
Antoine Clausse 1 rok temu
rodzic
commit
e7eb7d32c5

+ 1 - 0
services/web/app/views/_mixins/notification.pug

@@ -24,6 +24,7 @@ mixin notification(options)
 					p
 						b #{title}
 				| !{content}
+				block
 			//- TODO: handle action
 			//- if action
 			//- 	.notification-cta

+ 31 - 52
services/web/app/views/_mixins/reconfirm_affiliation-marketing.pug

@@ -1,55 +1,34 @@
-mixin reconfirmAffiliationNotification-marketing(userEmail, location)
-	form(data-ol-async-form action='/user/emails/send-reconfirmation')
-		input(name='_csrf' type='hidden' value=csrfToken)
-		input(name='email' type='hidden' value=userEmail.email)
-		+formMessages
-
-		.reconfirm-notification
-			div(data-ol-not-sent style='width: 100%')
-				i.fa.fa-warning
-
-				- var ssoEnabled = userEmail.affiliation && userEmail.affiliation.institution && userEmail.affiliation.institution.ssoEnabled
-				if ssoEnabled
-					- var institutionId = userEmail.affiliation && userEmail.affiliation.institution && userEmail.affiliation.institution.id
-					a.btn-reconfirm.btn.btn-sm.btn-info(
-						data-ol-slow-link
-						href=`${settings.saml.ukamf.initPath}?university_id=${institutionId}&reconfirm=${location}`
-					)
-						span(data-ol-inflight='idle') #{translate("confirm_affiliation")}
-						span(hidden data-ol-inflight='pending') #{translate("pending")}…
-
-				else
-					button.btn-reconfirm.btn.btn-sm.btn-info(
-						type='submit'
-						data-ol-disabled-inflight
-					)
-						span(data-ol-inflight='idle') #{translate("confirm_affiliation")}
-						span(hidden data-ol-inflight='pending') #{translate("pending")}…
+include ./notification
 
-				| !{translate("are_you_still_at", {institutionName: userEmail.affiliation.institution.name}, ['strong'])} 
-
-				if location == '/user/settings'
-					| !{translate('please_reconfirm_institutional_email', {}, [{ name: 'span' }])}
-					if userEmail.default
-						span  #{translate('need_to_add_new_primary_before_remove')}
-				else
-					| !{translate("please_reconfirm_institutional_email", {}, [{name: 'a', attrs: {href: '/user/settings?remove=' + userEmail.email}}])}
-
-				|  
-				a(href='/learn/how-to/Institutional_Email_Reconfirmation' target='_blank') #{translate("learn_more")}
-
-			div(hidden data-ol-sent)
-				| !{translate("please_check_your_inbox_to_confirm", {institutionName: userEmail.affiliation.institution.name}, ['strong'])}
-				|  
-				button.btn-inline-link(type='submit' data-ol-disabled-inflight)
-					span(data-ol-inflight='idle') #{translate('resend_confirmation_email')}
-					span(hidden data-ol-inflight='pending') #{translate("pending")}…
+mixin reconfirmAffiliationNotification-marketing(userEmail, location)
+	- var ssoEnabled = userEmail.affiliation && userEmail.affiliation.institution && userEmail.affiliation.institution.ssoEnabled
+	if ssoEnabled
+		- var institutionId = userEmail.affiliation && userEmail.affiliation.institution && userEmail.affiliation.institution.id
+		a.btn-reconfirm.btn.btn-sm.btn-info(
+			data-ol-slow-link
+			href=`${settings.saml.ukamf.initPath}?university_id=${institutionId}&reconfirm=${location}`
+		)
+			span(data-ol-inflight='idle') #{translate("confirm_affiliation")}
+			span(hidden data-ol-inflight='pending') #{translate("pending")}…
+
+	else
+		a.btn-reconfirm.btn.btn-sm.btn-info(data-ol-slow-link href='/user/settings')
+			span(data-ol-inflight='idle') #{translate("go_to_account_settings")}
+			span(hidden data-ol-inflight='pending') #{translate("redirecting")}… 
+
+	| !{translate("are_you_still_at", { institutionName: userEmail.affiliation.institution.name }, ['strong'])} 
+
+	if location == '/user/settings'
+		| !{translate('please_reconfirm_institutional_email', {}, [{ name: 'span' }])}
+		if userEmail.default
+			span  #{translate('need_to_add_new_primary_before_remove')}
+	else
+		| !{translate("please_reconfirm_institutional_email_2")}
+
+	|  
+	a(href='/learn/how-to/Institutional_Email_Reconfirmation' target='_blank') #{translate("learn_more_about_email_reconfirmation")}
 
 mixin reconfirmedAffiliationNotification-marketing(userEmail)
-	.alert.alert-info
-		.reconfirm-notification
-			div(style='width: 100%')
-				//- extra div for flex styling
-				| !{translate("your_affiliation_is_confirmed", {institutionName: userEmail.affiliation.institution.name}, ['strong'])}
-				|
-				| #{translate('thank_you_exclamation')}
+	| !{translate("your_affiliation_is_confirmed", {institutionName: userEmail.affiliation.institution.name}, ['strong'])}
+	|
+	| #{translate('thank_you_exclamation')}

+ 1 - 3
services/web/frontend/extracted-translations.json

@@ -930,6 +930,7 @@
   "learn_more": "",
   "learn_more_about": "",
   "learn_more_about_account": "",
+  "learn_more_about_email_reconfirmation": "",
   "learn_more_about_link_sharing": "",
   "learn_more_about_managed_users": "",
   "learn_more_about_other_causes_of_compile_timeouts": "",
@@ -1253,7 +1254,6 @@
   "please_ask_the_project_owner_to_upgrade_more_collaborators": "",
   "please_ask_the_project_owner_to_upgrade_to_track_changes": "",
   "please_change_primary_to_remove": "",
-  "please_check_your_inbox_to_confirm": "",
   "please_compile_pdf_before_download": "",
   "please_compile_pdf_before_word_count": "",
   "please_confirm_primary_email_or_edit": "",
@@ -1440,7 +1440,6 @@
   "republish": "",
   "resend": "",
   "resend_confirmation_code": "",
-  "resend_confirmation_email": "",
   "resend_group_invite": "",
   "resend_link_sso": "",
   "resend_managed_user_invite": "",
@@ -1561,7 +1560,6 @@
   "send_first_message": "",
   "send_message": "",
   "send_request": "",
-  "sending": "",
   "server_error": "",
   "server_pro_license_entitlement_line_1": "",
   "server_pro_license_entitlement_line_2": "",

+ 29 - 94
services/web/frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirm-affiliation.tsx

@@ -1,17 +1,12 @@
-import { useState, useEffect } from 'react'
+import { useState } from 'react'
 import { useTranslation, Trans } from 'react-i18next'
 import getMeta from '../../../../../../utils/meta'
-import useAsync from '../../../../../../shared/hooks/use-async'
-import {
-  FetchError,
-  postJSON,
-} from '../../../../../../infrastructure/fetch-json'
 import { UserEmailData } from '../../../../../../../../types/user-email'
 import { Institution } from '../../../../../../../../types/institution'
 import { useLocation } from '../../../../../../shared/hooks/use-location'
-import { debugConsole } from '@/utils/debugging'
 import OLButton from '@/features/ui/components/ol/ol-button'
 import Notification from '@/features/project-list/components/notifications/notification'
+import ResendConfirmationCodeModal from '@/features/settings/components/emails/resend-confirmation-code-modal'
 
 type ReconfirmAffiliationProps = {
   email: UserEmailData['email']
@@ -24,78 +19,13 @@ function ReconfirmAffiliation({
 }: ReconfirmAffiliationProps) {
   const { t } = useTranslation()
   const { samlInitPath } = getMeta('ol-ExposedSettings')
-  const { error, isLoading, isError, isSuccess, runAsync } = useAsync()
-  const [hasSent, setHasSent] = useState(false)
+  const [isSuccess, setIsSuccess] = useState(false)
+  const [isLoading, setIsLoading] = useState(false)
   const [isPending, setIsPending] = useState(false)
   const ssoEnabled = institution.ssoEnabled
   const location = useLocation()
 
-  useEffect(() => {
-    if (isSuccess) {
-      setHasSent(true)
-    }
-  }, [isSuccess])
-
-  const handleRequestReconfirmation = () => {
-    if (ssoEnabled) {
-      setIsPending(true)
-      location.assign(
-        `${samlInitPath}?university_id=${institution.id}&reconfirm=/project`
-      )
-    } else {
-      runAsync(
-        postJSON('/user/emails/send-reconfirmation', {
-          body: { email },
-        })
-      ).catch(debugConsole.error)
-    }
-  }
-
-  const rateLimited =
-    error && error instanceof FetchError && error.response?.status === 429
-
-  if (hasSent) {
-    return (
-      <Notification
-        type="info"
-        content={
-          <>
-            <Trans
-              i18nKey="please_check_your_inbox_to_confirm"
-              components={[<b />]} // eslint-disable-line react/jsx-key
-              values={{ institutionName: institution.name }}
-              shouldUnescape
-              tOptions={{ interpolation: { escapeValue: true } }}
-            />
-            &nbsp;
-            {isError && (
-              <>
-                <br />
-                <div>
-                  {rateLimited
-                    ? t('too_many_requests')
-                    : t('generic_something_went_wrong')}
-                </div>
-              </>
-            )}
-          </>
-        }
-        action={
-          <OLButton
-            variant="link"
-            onClick={handleRequestReconfirmation}
-            className="btn-inline-link"
-            disabled={isLoading}
-            isLoading={isLoading}
-            loadingLabel={t('sending') + '…'}
-          >
-            {t('resend_confirmation_email')}
-          </OLButton>
-        }
-      />
-    )
-  }
-
+  if (isSuccess) return null
   return (
     <Notification
       type="info"
@@ -119,29 +49,34 @@ function ReconfirmAffiliation({
             href="/learn/how-to/Institutional_Email_Reconfirmation"
             target="_blank"
           >
-            {t('learn_more')}
+            {t('learn_more_about_email_reconfirmation')}
           </a>
-          {isError && (
-            <>
-              <br />
-              <div>
-                {rateLimited
-                  ? t('too_many_requests')
-                  : t('generic_something_went_wrong')}
-              </div>
-            </>
-          )}
         </>
       }
       action={
-        <OLButton
-          variant="secondary"
-          isLoading={isLoading || isPending}
-          disabled={isLoading || isPending}
-          onClick={handleRequestReconfirmation}
-        >
-          {t('confirm_affiliation')}
-        </OLButton>
+        ssoEnabled ? (
+          <OLButton
+            variant="secondary"
+            isLoading={isPending}
+            disabled={isPending}
+            onClick={() => {
+              setIsPending(true)
+              location.assign(
+                `${samlInitPath}?university_id=${institution.id}&reconfirm=/project`
+              )
+            }}
+          >
+            {t('confirm_affiliation')}
+          </OLButton>
+        ) : (
+          <ResendConfirmationCodeModal
+            email={email}
+            setGroupLoading={setIsLoading}
+            groupLoading={isLoading}
+            onSuccess={() => setIsSuccess(true)}
+            triggerVariant="secondary"
+          />
+        )
       }
     />
   )

+ 49 - 122
services/web/frontend/js/features/settings/components/emails/reconfirmation-info.tsx

@@ -1,4 +1,4 @@
-import { useState, useEffect, useLayoutEffect } from 'react'
+import { useState } from 'react'
 import { UserEmailData } from '../../../../../../types/user-email'
 import getMeta from '../../../../utils/meta'
 import ReconfirmationInfoSuccess from './reconfirmation-info/reconfirmation-info-success'
@@ -7,14 +7,11 @@ import OLRow from '@/features/ui/components/ol/ol-row'
 import OLCol from '@/features/ui/components/ol/ol-col'
 import OLNotification from '@/features/ui/components/ol/ol-notification'
 import { useUserEmailsContext } from '@/features/settings/context/user-email-context'
-import { FetchError, postJSON } from '@/infrastructure/fetch-json'
-import { debugConsole } from '@/utils/debugging'
 import { ssoAvailableForInstitution } from '@/features/settings/utils/sso'
-import { Trans, useTranslation } from 'react-i18next'
-import useAsync from '@/shared/hooks/use-async'
+import { useTranslation } from 'react-i18next'
 import { useLocation } from '@/shared/hooks/use-location'
 import OLButton from '@/features/ui/components/ol/ol-button'
-import LoadingSpinner from '@/shared/components/loading-spinner'
+import ResendConfirmationCodeModal from '@/features/settings/components/emails/resend-confirmation-code-modal'
 
 type ReconfirmationInfoProps = {
   userEmailData: UserEmailData
@@ -22,50 +19,21 @@ type ReconfirmationInfoProps = {
 
 function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
   const reconfirmedViaSAML = getMeta('ol-reconfirmedViaSAML')
-
+  const affiliation = userEmailData.affiliation
   const { t } = useTranslation()
   const { samlInitPath } = getMeta('ol-ExposedSettings')
-  const { error, isLoading, isError, isSuccess, runAsync } = useAsync()
-  const { state, setLoading: setUserEmailsContextLoading } =
-    useUserEmailsContext()
-  const [hasSent, setHasSent] = useState(false)
+  const {
+    state,
+    setLoading: setUserEmailsContextLoading,
+    getEmails,
+  } = useUserEmailsContext()
   const [isPending, setIsPending] = useState(false)
   const location = useLocation()
   const ssoAvailable = Boolean(
-    ssoAvailableForInstitution(userEmailData.affiliation?.institution ?? null)
+    ssoAvailableForInstitution(affiliation?.institution ?? null)
   )
 
-  const handleRequestReconfirmation = () => {
-    if (userEmailData.affiliation?.institution && ssoAvailable) {
-      setIsPending(true)
-      location.assign(
-        `${samlInitPath}?university_id=${userEmailData.affiliation.institution.id}&reconfirm=/user/settings`
-      )
-    } else {
-      runAsync(
-        postJSON('/user/emails/send-reconfirmation', {
-          body: {
-            email: userEmailData.email,
-          },
-        })
-      ).catch(debugConsole.error)
-    }
-  }
-
-  useEffect(() => {
-    setUserEmailsContextLoading(isLoading)
-  }, [setUserEmailsContextLoading, isLoading])
-
-  useLayoutEffect(() => {
-    if (isSuccess) {
-      setHasSent(true)
-    }
-  }, [isSuccess])
-
-  const rateLimited =
-    isError && error instanceof FetchError && error.response?.status === 429
-
-  if (!userEmailData.affiliation) {
+  if (!affiliation) {
     return null
   }
 
@@ -80,7 +48,7 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
             type="info"
             content={
               <ReconfirmationInfoSuccess
-                institution={userEmailData.affiliation.institution}
+                institution={affiliation.institution}
               />
             }
           />
@@ -89,86 +57,45 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
     )
   }
 
-  if (userEmailData.affiliation.inReconfirmNotificationPeriod) {
-    return (
-      <OLRow>
-        <OLCol lg={12}>
-          <OLNotification
-            type="info"
-            content={
-              <>
-                {hasSent ? (
-                  <Trans
-                    i18nKey="please_check_your_inbox_to_confirm"
-                    values={{
-                      institutionName:
-                        userEmailData.affiliation.institution.name,
-                    }}
-                    shouldUnescape
-                    tOptions={{ interpolation: { escapeValue: true } }}
-                    components={
-                      /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
-                      [<strong />]
-                    }
-                  />
-                ) : (
-                  <ReconfirmationInfoPromptText
-                    institutionName={userEmailData.affiliation.institution.name}
-                    primary={userEmailData.default}
-                  />
-                )}
-                <br />
-                {isError && (
-                  <div className="text-danger">
-                    {rateLimited
-                      ? t('too_many_requests')
-                      : t('generic_something_went_wrong')}
-                  </div>
-                )}
-              </>
-            }
-            action={
-              hasSent ? (
-                <>
-                  {isLoading ? (
-                    <>
-                      <LoadingSpinner loadingText={`${t('sending')}…`} />
-                    </>
-                  ) : (
-                    <OLButton
-                      variant="link"
-                      disabled={state.isLoading}
-                      onClick={handleRequestReconfirmation}
-                      className="btn-inline-link"
-                    >
-                      {t('resend_confirmation_email')}
-                    </OLButton>
-                  )}
-                </>
-              ) : (
-                <OLButton
-                  variant="secondary"
-                  disabled={isPending}
-                  isLoading={isLoading}
-                  onClick={handleRequestReconfirmation}
-                >
-                  {isLoading ? (
-                    <>
-                      <LoadingSpinner loadingText={`${t('sending')}…`} />
-                    </>
-                  ) : (
-                    t('confirm_affiliation')
-                  )}
-                </OLButton>
-              )
-            }
-          />
-        </OLCol>
-      </OLRow>
-    )
+  if (!affiliation.inReconfirmNotificationPeriod) {
+    return null
   }
 
-  return null
+  return (
+    <OLNotification
+      type="info"
+      content={
+        <ReconfirmationInfoPromptText
+          institutionName={affiliation.institution.name}
+          primary={userEmailData.default}
+        />
+      }
+      action={
+        affiliation?.institution && ssoAvailable ? (
+          <OLButton
+            variant="secondary"
+            disabled={isPending}
+            onClick={() => {
+              setIsPending(true)
+              location.assign(
+                `${samlInitPath}?university_id=${affiliation.institution.id}&reconfirm=/user/settings`
+              )
+            }}
+          >
+            {t('confirm_affiliation')}
+          </OLButton>
+        ) : (
+          <ResendConfirmationCodeModal
+            email={userEmailData.email}
+            setGroupLoading={setUserEmailsContextLoading}
+            groupLoading={state.isLoading}
+            onSuccess={getEmails}
+            triggerVariant="secondary"
+          />
+        )
+      }
+    />
+  )
 }
 
 export default ReconfirmationInfo

+ 1 - 1
services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-prompt-text.tsx

@@ -37,7 +37,7 @@ function ReconfirmationInfoPromptText({
         href="/learn/how-to/Institutional_Email_Reconfirmation"
         target="_blank"
       >
-        {t('learn_more')}
+        {t('learn_more_about_email_reconfirmation')}
       </a>
       <br />
       {primary ? <i>{t('need_to_add_new_primary_before_remove')}</i> : null}

+ 2 - 2
services/web/locales/en.json

@@ -1207,6 +1207,7 @@
   "learn_more": "Learn more",
   "learn_more_about": "Learn more about __appName__",
   "learn_more_about_account": "<0>Learn more</0> about managing your __appName__ account.",
+  "learn_more_about_email_reconfirmation": "Learn more about institutional email reconfirmation.",
   "learn_more_about_emails": "<0>Learn more</0> about managing your __appName__ emails.",
   "learn_more_about_link_sharing": "Learn more about Link Sharing",
   "learn_more_about_managed_users": "Learn more about Managed Users.",
@@ -1648,7 +1649,6 @@
   "please_ask_the_project_owner_to_upgrade_more_collaborators": "Please ask the project owner to upgrade their plan to allow more collaborators.",
   "please_ask_the_project_owner_to_upgrade_to_track_changes": "Please ask the project owner to upgrade to use track changes",
   "please_change_primary_to_remove": "Please change your primary email in order to remove",
-  "please_check_your_inbox_to_confirm": "Please check your email inbox to confirm your <0>__institutionName__</0> affiliation.",
   "please_compile_pdf_before_download": "Please compile your project before downloading the PDF",
   "please_compile_pdf_before_word_count": "Please compile your project before performing a word count",
   "please_confirm_email": "Please confirm your email __emailAddress__ by clicking on the link in the confirmation email ",
@@ -1665,6 +1665,7 @@
   "please_provide_a_subject": "Please provide a subject",
   "please_provide_a_valid_email_address": "Please provide a valid email address",
   "please_reconfirm_institutional_email": "Please take a moment to confirm your institutional email address or <0>remove it</0> from your account.",
+  "please_reconfirm_institutional_email_2": "Please take a moment to confirm your institutional email address or remove it from your account.",
   "please_reconfirm_your_affiliation_before_making_this_primary": "Please confirm your affiliation before making this the primary.",
   "please_refresh": "Please refresh the page to continue.",
   "please_request_a_new_password_reset_email_and_follow_the_link": "Please request a new password reset email and follow the link",
@@ -1879,7 +1880,6 @@
   "required": "Required",
   "resend": "Resend",
   "resend_confirmation_code": "Resend confirmation code",
-  "resend_confirmation_email": "Resend confirmation email",
   "resend_group_invite": "Resend group invite",
   "resend_link_sso": "Resend SSO invite",
   "resend_managed_user_invite": "Resend managed user invite",

+ 7 - 9
services/web/test/frontend/features/project-list/components/notifications.test.tsx

@@ -842,24 +842,22 @@ describe('<UserNotifications />', function () {
       )
 
       const sendReconfirmationMock = fetchMock.post(
-        '/user/emails/send-reconfirmation',
+        '/user/emails/send-confirmation-code',
         200
       )
       fireEvent.click(
-        screen.getByRole('button', { name: /confirm affiliation/i })
+        screen.getByRole('button', { name: 'Send confirmation code' })
       )
 
       await waitForElementToBeRemoved(() => screen.getByText(/loading/i))
-      screen.getByText(/check your email inbox to confirm/i)
-      expect(screen.queryByRole('button', { name: /confirm affiliation/i })).to
-        .be.null
-      expect(screen.queryByRole('link', { name: /remove it/i })).to.be.null
-      expect(screen.queryByRole('link', { name: /learn more/i })).to.be.null
+      screen.getByText(/Enter the 6-digit code sent to foo@overleaf.com/i)
       expect(sendReconfirmationMock.callHistory.called()).to.be.true
       fireEvent.click(
-        screen.getByRole('button', { name: /resend confirmation email/i })
+        screen.getByRole('button', { name: /resend confirmation code/i })
+      )
+      await waitForElementToBeRemoved(() =>
+        screen.getByText('Resending confirmation code')
       )
-      await waitForElementToBeRemoved(() => screen.getByText('Sending…'))
       expect(sendReconfirmationMock.callHistory.calls()).to.have.lengthOf(2)
     })
 

+ 13 - 7
services/web/test/frontend/features/settings/components/emails/reconfirmation-info.test.tsx

@@ -76,7 +76,9 @@ describe('<ReconfirmationInfo/>', function () {
       screen.getByText(
         /Please take a moment to confirm your institutional email address/
       )
-      screen.getByRole('link', { name: 'Learn more' })
+      screen.getByRole('link', {
+        name: 'Learn more about institutional email reconfirmation.',
+      })
       expect(screen.queryByText(/add a new primary email address/)).to.not.exist
     })
 
@@ -121,13 +123,13 @@ describe('<ReconfirmationInfo/>', function () {
         Object.assign(getMeta('ol-ExposedSettings'), {
           hasSamlFeature: false,
         })
-        fetchMock.post('/user/emails/send-reconfirmation', 200)
+        fetchMock.post('/user/emails/send-confirmation-code', 200)
       })
 
       it('sends and resends confirmation email', async function () {
         renderReconfirmationInfo(inReconfirmUserData)
         const confirmButton = (await screen.findByRole('button', {
-          name: 'Confirm affiliation',
+          name: 'Send confirmation code',
         })) as HTMLButtonElement
 
         await waitFor(() => {
@@ -141,12 +143,14 @@ describe('<ReconfirmationInfo/>', function () {
         expect(fetchMock.callHistory.called()).to.be.true
 
         // the confirmation text should now be displayed
-        await screen.findByText(/Please check your email inbox to confirm/)
+        await screen.findByLabelText(
+          /Enter the 6-digit code sent to sso-prof@sso-university\.edu/
+        )
 
         // try the resend button
         fetchMock.clearHistory()
         const resendButton = await screen.findByRole('button', {
-          name: 'Resend confirmation email',
+          name: /Resend confirmation code/,
         })
 
         fireEvent.click(resendButton)
@@ -154,9 +158,11 @@ describe('<ReconfirmationInfo/>', function () {
         // commented out as it's already gone by this point
         // await screen.findByText(/Sending/)
         expect(fetchMock.callHistory.called()).to.be.true
-        await waitForElementToBeRemoved(() => screen.getByText('Sending…'))
+        await waitForElementToBeRemoved(() =>
+          screen.getByText('Resending confirmation code')
+        )
         await screen.findByRole('button', {
-          name: 'Resend confirmation email',
+          name: 'Resend confirmation code',
         })
       })
     })