reconfirmation-info.test.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import {
  2. fireEvent,
  3. render,
  4. screen,
  5. waitFor,
  6. waitForElementToBeRemoved,
  7. } from '@testing-library/react'
  8. import sinon from 'sinon'
  9. import { expect } from 'chai'
  10. import fetchMock from 'fetch-mock'
  11. import { cloneDeep } from 'lodash'
  12. import ReconfirmationInfo from '../../../../../../frontend/js/features/settings/components/emails/reconfirmation-info'
  13. import { ssoUserData } from '../../fixtures/test-user-email-data'
  14. import { UserEmailData } from '../../../../../../types/user-email'
  15. import { UserEmailsProvider } from '../../../../../../frontend/js/features/settings/context/user-email-context'
  16. import { location } from '@/shared/components/location'
  17. import getMeta from '@/utils/meta'
  18. function renderReconfirmationInfo(data: UserEmailData) {
  19. return render(
  20. <UserEmailsProvider>
  21. <ReconfirmationInfo userEmailData={data} />
  22. </UserEmailsProvider>
  23. )
  24. }
  25. describe('<ReconfirmationInfo/>', function () {
  26. beforeEach(function () {
  27. Object.assign(getMeta('ol-ExposedSettings'), {
  28. samlInitPath: '/saml',
  29. })
  30. fetchMock.get('/user/emails?ensureAffiliation=true', [])
  31. this.locationWrapperSandbox = sinon.createSandbox()
  32. this.locationWrapperStub = this.locationWrapperSandbox.stub(location)
  33. })
  34. afterEach(function () {
  35. fetchMock.removeRoutes().clearHistory()
  36. this.locationWrapperSandbox.restore()
  37. })
  38. describe('reconfirmed via SAML', function () {
  39. beforeEach(function () {
  40. window.metaAttributesCache.set(
  41. 'ol-reconfirmedViaSAML',
  42. 'sso-prof-saml-id'
  43. )
  44. })
  45. it('show reconfirmed confirmation', function () {
  46. renderReconfirmationInfo(ssoUserData)
  47. screen.getByText('SSO University')
  48. screen.getByText(/affiliation is confirmed/)
  49. screen.getByText(/Thank you!/)
  50. })
  51. })
  52. describe('in reconfirm notification period', function () {
  53. let inReconfirmUserData: UserEmailData
  54. beforeEach(function () {
  55. Object.assign(getMeta('ol-ExposedSettings'), {
  56. samlInitPath: '/saml',
  57. })
  58. inReconfirmUserData = cloneDeep(ssoUserData)
  59. if (inReconfirmUserData.affiliation) {
  60. inReconfirmUserData.affiliation.inReconfirmNotificationPeriod = true
  61. }
  62. })
  63. it('renders prompt', function () {
  64. renderReconfirmationInfo(inReconfirmUserData)
  65. screen.getByText(/Are you still at/)
  66. screen.getByText('SSO University')
  67. screen.getByText(
  68. /Please take a moment to confirm your institutional email address/
  69. )
  70. screen.getByRole('link', {
  71. name: 'Learn more about institutional email reconfirmation.',
  72. })
  73. expect(screen.queryByText(/add a new primary email address/)).to.not.exist
  74. })
  75. it('renders default emails prompt', function () {
  76. inReconfirmUserData.default = true
  77. renderReconfirmationInfo(inReconfirmUserData)
  78. screen.getByText(/add a new primary email address/)
  79. })
  80. describe('SAML reconfirmations', function () {
  81. beforeEach(function () {
  82. Object.assign(getMeta('ol-ExposedSettings'), {
  83. hasSamlFeature: true,
  84. samlInitPath: '/saml/init',
  85. })
  86. })
  87. it('redirects to SAML flow', async function () {
  88. renderReconfirmationInfo(inReconfirmUserData)
  89. const confirmButton = screen.getByRole('button', {
  90. name: 'Confirm affiliation',
  91. }) as HTMLButtonElement
  92. await waitFor(() => {
  93. expect(confirmButton.disabled).to.be.false
  94. })
  95. fireEvent.click(confirmButton)
  96. await waitFor(() => {
  97. expect(confirmButton.disabled).to.be.true
  98. })
  99. sinon.assert.calledOnce(this.locationWrapperStub.assign)
  100. sinon.assert.calledWithMatch(
  101. this.locationWrapperStub.assign,
  102. '/saml/init?university_id=2&reconfirm=/user/settings'
  103. )
  104. })
  105. })
  106. describe('Email reconfirmations', function () {
  107. beforeEach(function () {
  108. Object.assign(getMeta('ol-ExposedSettings'), {
  109. hasSamlFeature: false,
  110. })
  111. fetchMock.post('/user/emails/send-confirmation-code', 200)
  112. })
  113. it('sends and resends confirmation email', async function () {
  114. renderReconfirmationInfo(inReconfirmUserData)
  115. const confirmButton = (await screen.findByRole('button', {
  116. name: 'Send confirmation code',
  117. })) as HTMLButtonElement
  118. await waitFor(() => {
  119. expect(confirmButton.disabled).to.be.false
  120. })
  121. fireEvent.click(confirmButton)
  122. await waitFor(() => {
  123. expect(confirmButton.disabled).to.be.true
  124. })
  125. expect(fetchMock.callHistory.called()).to.be.true
  126. // the confirmation text should now be displayed
  127. await screen.findByLabelText(
  128. /Enter the 6-digit code sent to sso-prof@sso-university\.edu/
  129. )
  130. // try the resend button
  131. fetchMock.clearHistory()
  132. const resendButton = await screen.findByRole('button', {
  133. name: /Resend confirmation code/,
  134. })
  135. fireEvent.click(resendButton)
  136. // commented out as it's already gone by this point
  137. // await screen.findByText(/Sending/)
  138. expect(fetchMock.callHistory.called()).to.be.true
  139. await waitForElementToBeRemoved(() =>
  140. screen.getByText('Resending confirmation code')
  141. )
  142. await screen.findByRole('button', {
  143. name: 'Resend confirmation code',
  144. })
  145. })
  146. })
  147. })
  148. })