project-notifications-setting.test.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import { screen, render, waitFor } from '@testing-library/react'
  2. import { expect } from 'chai'
  3. import fetchMock from 'fetch-mock'
  4. import userEvent from '@testing-library/user-event'
  5. import { EditorProviders, PROJECT_ID } from '../../../helpers/editor-providers'
  6. import { SettingsModalProvider } from '@/features/settings/context/settings-modal-context'
  7. import ProjectNotificationsSetting from '@/features/settings/components/editor-settings/project-notifications-setting'
  8. const preferencesUrl = `/notifications/preferences/project/${PROJECT_ID}`
  9. const allNotificationsOn = {
  10. trackedChangesOnOwnProject: true,
  11. trackedChangesOnInvitedProject: true,
  12. commentOnOwnProject: true,
  13. commentOnInvitedProject: true,
  14. repliesOnOwnProject: true,
  15. repliesOnInvitedProject: true,
  16. repliesOnAuthoredThread: true,
  17. repliesOnParticipatingThread: true,
  18. }
  19. const repliesOnlyPreferences = {
  20. trackedChangesOnOwnProject: false,
  21. trackedChangesOnInvitedProject: false,
  22. commentOnOwnProject: false,
  23. commentOnInvitedProject: false,
  24. repliesOnOwnProject: false,
  25. repliesOnInvitedProject: false,
  26. repliesOnAuthoredThread: true,
  27. repliesOnParticipatingThread: true,
  28. }
  29. const allNotificationsOff = {
  30. trackedChangesOnOwnProject: false,
  31. trackedChangesOnInvitedProject: false,
  32. commentOnOwnProject: false,
  33. commentOnInvitedProject: false,
  34. repliesOnOwnProject: false,
  35. repliesOnInvitedProject: false,
  36. repliesOnAuthoredThread: false,
  37. repliesOnParticipatingThread: false,
  38. }
  39. function renderComponent() {
  40. return render(
  41. <EditorProviders>
  42. <SettingsModalProvider>
  43. <ProjectNotificationsSetting />
  44. </SettingsModalProvider>
  45. </EditorProviders>
  46. )
  47. }
  48. describe('<ProjectNotificationsSetting />', function () {
  49. afterEach(function () {
  50. fetchMock.removeRoutes().clearHistory()
  51. })
  52. it('selects "All project activity" when all notifications are on', async function () {
  53. fetchMock.get(preferencesUrl, allNotificationsOn)
  54. renderComponent()
  55. await waitFor(
  56. () =>
  57. expect(
  58. (
  59. screen.getByLabelText('All project activity', {
  60. exact: false,
  61. }) as HTMLInputElement
  62. ).checked
  63. ).to.be.true
  64. )
  65. expect(
  66. (
  67. screen.getByLabelText('Replies to your activity only', {
  68. exact: false,
  69. }) as HTMLInputElement
  70. ).checked
  71. ).to.be.false
  72. expect(
  73. (screen.getByLabelText('Off', { exact: false }) as HTMLInputElement)
  74. .checked
  75. ).to.be.false
  76. })
  77. it('selects "Replies to your activity only" when only reply notifications are on', async function () {
  78. fetchMock.get(preferencesUrl, repliesOnlyPreferences)
  79. renderComponent()
  80. await waitFor(
  81. () =>
  82. expect(
  83. (
  84. screen.getByLabelText('Replies to your activity only', {
  85. exact: false,
  86. }) as HTMLInputElement
  87. ).checked
  88. ).to.be.true
  89. )
  90. expect(
  91. (
  92. screen.getByLabelText('All project activity', {
  93. exact: false,
  94. }) as HTMLInputElement
  95. ).checked
  96. ).to.be.false
  97. expect(
  98. (screen.getByLabelText('Off', { exact: false }) as HTMLInputElement)
  99. .checked
  100. ).to.be.false
  101. })
  102. it('selects "Off" when all notifications are off', async function () {
  103. fetchMock.get(preferencesUrl, allNotificationsOff)
  104. renderComponent()
  105. await waitFor(
  106. () =>
  107. expect(
  108. (screen.getByLabelText('Off', { exact: false }) as HTMLInputElement)
  109. .checked
  110. ).to.be.true
  111. )
  112. expect(
  113. (
  114. screen.getByLabelText('All project activity', {
  115. exact: false,
  116. }) as HTMLInputElement
  117. ).checked
  118. ).to.be.false
  119. expect(
  120. (
  121. screen.getByLabelText('Replies to your activity only', {
  122. exact: false,
  123. }) as HTMLInputElement
  124. ).checked
  125. ).to.be.false
  126. })
  127. it('POSTs "replies" preferences when "Replies to your activity only" is selected', async function () {
  128. fetchMock.get(preferencesUrl, allNotificationsOn)
  129. const saveMock = fetchMock.post(preferencesUrl, { status: 200 })
  130. renderComponent()
  131. await waitFor(
  132. () =>
  133. expect(
  134. (
  135. screen.getByLabelText('All project activity', {
  136. exact: false,
  137. }) as HTMLInputElement
  138. ).checked
  139. ).to.be.true
  140. )
  141. await userEvent.click(
  142. screen.getByLabelText('Replies to your activity only', { exact: false })
  143. )
  144. expect(
  145. saveMock.callHistory.called(preferencesUrl, {
  146. body: repliesOnlyPreferences,
  147. })
  148. ).to.be.true
  149. })
  150. it('POSTs "off" preferences when "Off" is selected', async function () {
  151. fetchMock.get(preferencesUrl, allNotificationsOn)
  152. const saveMock = fetchMock.post(preferencesUrl, { status: 200 })
  153. renderComponent()
  154. await waitFor(
  155. () =>
  156. expect(
  157. (
  158. screen.getByLabelText('All project activity', {
  159. exact: false,
  160. }) as HTMLInputElement
  161. ).checked
  162. ).to.be.true
  163. )
  164. await userEvent.click(screen.getByLabelText('Off', { exact: false }))
  165. expect(
  166. saveMock.callHistory.called(preferencesUrl, {
  167. body: allNotificationsOff,
  168. })
  169. ).to.be.true
  170. })
  171. it('POSTs "all" preferences when "All project activity" is selected', async function () {
  172. fetchMock.get(preferencesUrl, allNotificationsOff)
  173. const saveMock = fetchMock.post(preferencesUrl, { status: 200 })
  174. renderComponent()
  175. await waitFor(
  176. () =>
  177. expect(
  178. (screen.getByLabelText('Off', { exact: false }) as HTMLInputElement)
  179. .checked
  180. ).to.be.true
  181. )
  182. await userEvent.click(
  183. screen.getByLabelText('All project activity', { exact: false })
  184. )
  185. expect(
  186. saveMock.callHistory.called(preferencesUrl, {
  187. body: allNotificationsOn,
  188. })
  189. ).to.be.true
  190. })
  191. })