sso-widget.test.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import { expect } from 'chai'
  2. import sinon from 'sinon'
  3. import { screen, fireEvent, render, waitFor } from '@testing-library/react'
  4. import { FetchError } from '../../../../../../frontend/js/infrastructure/fetch-json'
  5. import { SSOLinkingWidget } from '../../../../../../frontend/js/features/settings/components/linking/sso-widget'
  6. describe('<SSOLinkingWidget />', function () {
  7. const defaultProps = {
  8. providerId: 'integration_id',
  9. title: 'integration',
  10. description: 'integration description',
  11. helpPath: '/help/integration',
  12. linkPath: '/integration/link',
  13. onUnlink: () => Promise.resolve(),
  14. }
  15. it('should render', function () {
  16. render(<SSOLinkingWidget {...defaultProps} />)
  17. screen.getByText('integration')
  18. screen.getByText('integration description')
  19. expect(
  20. screen.getByRole('link', { name: 'Learn more' }).getAttribute('href')
  21. ).to.equal('/help/integration')
  22. })
  23. describe('when unlinked', function () {
  24. it('should render a link to `linkPath`', function () {
  25. render(<SSOLinkingWidget {...defaultProps} linked={false} />)
  26. expect(
  27. screen.getByRole('link', { name: 'Link' }).getAttribute('href')
  28. ).to.equal('/integration/link?intent=link')
  29. })
  30. })
  31. describe('when linked', function () {
  32. let unlinkFunction: sinon.SinonStub
  33. beforeEach(function () {
  34. unlinkFunction = sinon.stub()
  35. render(
  36. <SSOLinkingWidget {...defaultProps} linked onUnlink={unlinkFunction} />
  37. )
  38. })
  39. it('should display an `unlink` button', function () {
  40. screen.getByRole('button', { name: 'Unlink' })
  41. })
  42. it('should open a modal to confirm integration unlinking', function () {
  43. fireEvent.click(screen.getByRole('button', { name: 'Unlink' }))
  44. screen.getByText('Unlink integration Account')
  45. screen.getByText(
  46. 'Warning: When you unlink your account from integration you will not be able to sign in using integration anymore.'
  47. )
  48. })
  49. it('should cancel unlinking when clicking cancel in the confirmation modal', async function () {
  50. fireEvent.click(screen.getByRole('button', { name: 'Unlink' }))
  51. const cancelBtn = screen.getByRole('button', {
  52. name: 'Cancel',
  53. hidden: false,
  54. })
  55. fireEvent.click(cancelBtn)
  56. await waitFor(() =>
  57. screen.getByRole('button', { name: 'Cancel', hidden: true })
  58. )
  59. expect(unlinkFunction).not.to.have.been.called
  60. })
  61. })
  62. describe('unlinking an account', function () {
  63. let confirmBtn: HTMLElement, unlinkFunction: sinon.SinonStub
  64. beforeEach(function () {
  65. unlinkFunction = sinon.stub()
  66. render(
  67. <SSOLinkingWidget {...defaultProps} linked onUnlink={unlinkFunction} />
  68. )
  69. fireEvent.click(screen.getByRole('button', { name: 'Unlink' }))
  70. confirmBtn = screen.getByRole('button', {
  71. name: 'Unlink',
  72. hidden: false,
  73. })
  74. })
  75. it('should make an `unlink` request', function () {
  76. unlinkFunction.resolves()
  77. fireEvent.click(confirmBtn)
  78. expect(unlinkFunction).to.have.been.called
  79. })
  80. it('should display feedback while the request is inflight', async function () {
  81. unlinkFunction.returns(
  82. new Promise<void>(resolve => {
  83. setTimeout(resolve, 500)
  84. })
  85. )
  86. fireEvent.click(confirmBtn)
  87. await waitFor(() =>
  88. expect(screen.getByRole('button', { name: 'Unlinking' }))
  89. )
  90. })
  91. })
  92. describe('when unlinking fails', function () {
  93. beforeEach(function () {
  94. const unlinkFunction = sinon
  95. .stub()
  96. .rejects(new FetchError('unlinking failed', ''))
  97. render(
  98. <SSOLinkingWidget {...defaultProps} linked onUnlink={unlinkFunction} />
  99. )
  100. fireEvent.click(screen.getByRole('button', { name: 'Unlink' }))
  101. const confirmBtn = screen.getByRole('button', {
  102. name: 'Unlink',
  103. hidden: false,
  104. })
  105. fireEvent.click(confirmBtn)
  106. })
  107. it('should display an error message ', async function () {
  108. await waitFor(() =>
  109. screen.getByText('Something went wrong. Please try again.')
  110. )
  111. })
  112. it('should display the unlink button ', async function () {
  113. await waitFor(() => screen.getByRole('button', { name: 'Unlink' }))
  114. })
  115. })
  116. })