email-preferences-form.test.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import { expect } from 'chai'
  2. import { fireEvent, screen, render } from '@testing-library/react'
  3. import fetchMock from 'fetch-mock'
  4. import EmailPreferencesForm from '../../../../../../frontend/js/features/settings/components/email-preferences/email-preferences-form'
  5. describe('<EmailPreferencesForm />', function () {
  6. beforeEach(function () {
  7. window.metaAttributesCache.set('ol-newsletter-subscribed', true)
  8. })
  9. afterEach(function () {
  10. fetchMock.removeRoutes().clearHistory()
  11. })
  12. it('shows subscribed state with unsubscribe button', function () {
  13. render(<EmailPreferencesForm />)
  14. screen.getByText('You are', { exact: false })
  15. screen.getByRole('button', { name: 'Unsubscribe' })
  16. screen.getByText('Please note: you will still receive important emails', {
  17. exact: false,
  18. })
  19. })
  20. it('shows unsubscribed state with subscribe button', function () {
  21. window.metaAttributesCache.set('ol-newsletter-subscribed', false)
  22. render(<EmailPreferencesForm />)
  23. screen.getByText('You are', { exact: false })
  24. screen.getByRole('button', { name: 'Subscribe' })
  25. expect(
  26. screen.queryByText(
  27. 'Please note: you will still receive important emails',
  28. { exact: false }
  29. )
  30. ).to.not.exist
  31. })
  32. it('calls unsubscribe endpoint when clicking unsubscribe', async function () {
  33. const unsubscribeMock = fetchMock.post('/user/newsletter/unsubscribe', {
  34. status: 200,
  35. body: { subscribed: false },
  36. })
  37. render(<EmailPreferencesForm />)
  38. const button = screen.getByRole('button', { name: 'Unsubscribe' })
  39. fireEvent.click(button)
  40. expect(unsubscribeMock.callHistory.called()).to.be.true
  41. expect(unsubscribeMock.callHistory.calls().at(-1)?.url).to.equal(
  42. 'https://www.test-overleaf.com/user/newsletter/unsubscribe'
  43. )
  44. })
  45. it('calls subscribe endpoint when clicking subscribe', async function () {
  46. window.metaAttributesCache.set('ol-newsletter-subscribed', false)
  47. const subscribeMock = fetchMock.post('/user/newsletter/subscribe', {
  48. status: 200,
  49. body: { subscribed: true },
  50. })
  51. render(<EmailPreferencesForm />)
  52. const button = screen.getByRole('button', { name: 'Subscribe' })
  53. fireEvent.click(button)
  54. expect(subscribeMock.callHistory.called()).to.be.true
  55. expect(subscribeMock.callHistory.calls().at(-1)?.url).to.equal(
  56. 'https://www.test-overleaf.com/user/newsletter/subscribe'
  57. )
  58. })
  59. it('shows loading state while request is in flight', async function () {
  60. let finishRequest: (value: any) => void = () => {}
  61. fetchMock.post(
  62. '/user/newsletter/unsubscribe',
  63. new Promise(resolve => (finishRequest = resolve))
  64. )
  65. render(<EmailPreferencesForm />)
  66. const button = screen.getByRole('button', { name: 'Unsubscribe' })
  67. fireEvent.click(button)
  68. await screen.findByRole('button', { name: 'Saving…' })
  69. finishRequest({ status: 200, body: { subscribed: false } })
  70. await screen.findByRole('button', { name: 'Subscribe' })
  71. })
  72. it('shows success notification after successful action', async function () {
  73. fetchMock.post('/user/newsletter/unsubscribe', {
  74. status: 200,
  75. body: { subscribed: false },
  76. })
  77. render(<EmailPreferencesForm />)
  78. const button = screen.getByRole('button', { name: 'Unsubscribe' })
  79. fireEvent.click(button)
  80. await screen.findByText('Thanks, your settings have been updated.')
  81. })
  82. it('shows error notification on server error', async function () {
  83. fetchMock.post('/user/newsletter/unsubscribe', 500)
  84. render(<EmailPreferencesForm />)
  85. const button = screen.getByRole('button', { name: 'Unsubscribe' })
  86. fireEvent.click(button)
  87. await screen.findByText('Something went wrong. Please try again.')
  88. })
  89. it('shows error notification with message on 4xx error', async function () {
  90. fetchMock.post('/user/newsletter/unsubscribe', {
  91. status: 400,
  92. body: { message: 'Unable to update preferences' },
  93. })
  94. render(<EmailPreferencesForm />)
  95. const button = screen.getByRole('button', { name: 'Unsubscribe' })
  96. fireEvent.click(button)
  97. await screen.findByText('Unable to update preferences')
  98. })
  99. it('toggles between subscribed and unsubscribed states', async function () {
  100. fetchMock.post('/user/newsletter/unsubscribe', {
  101. status: 200,
  102. body: { subscribed: false },
  103. })
  104. fetchMock.post('/user/newsletter/subscribe', {
  105. status: 200,
  106. body: { subscribed: true },
  107. })
  108. render(<EmailPreferencesForm />)
  109. // Initially subscribed
  110. screen.getByRole('button', { name: 'Unsubscribe' })
  111. // Unsubscribe
  112. fireEvent.click(screen.getByRole('button', { name: 'Unsubscribe' }))
  113. await screen.findByRole('button', { name: 'Subscribe' })
  114. // Subscribe again
  115. fireEvent.click(screen.getByRole('button', { name: 'Subscribe' }))
  116. await screen.findByRole('button', { name: 'Unsubscribe' })
  117. })
  118. })