guided-setup-manual-email-notification.spec.ts 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { getNode } from '@formkit/core'
  3. import { getByRole, queryByRole } from '@testing-library/vue'
  4. import { flushPromises } from '@vue/test-utils'
  5. import { visitView } from '#tests/support/components/visitView.ts'
  6. import { mockApplicationConfig } from '#tests/support/mock-applicationConfig.ts'
  7. import { mockAuthentication } from '#tests/support/mock-authentication.ts'
  8. import { mockPermissions } from '#tests/support/mock-permissions.ts'
  9. import { mockFormUpdaterQuery } from '#shared/components/Form/graphql/queries/formUpdater.mocks.ts'
  10. import { EnumSystemSetupInfoStatus } from '#shared/graphql/types.ts'
  11. import { mockChannelEmailSetNotificationConfigurationMutation } from '#desktop/entities/channel-email/graphql/mutations/channelEmailSetNotificationConfiguration.mocks.ts'
  12. import {
  13. mockChannelEmailValidateConfigurationOutboundMutation,
  14. waitForChannelEmailValidateConfigurationOutboundMutationCalls,
  15. } from '#desktop/entities/channel-email/graphql/mutations/channelEmailValidateConfigurationOutbound.mocks.ts'
  16. import { mockSystemSetupInfoQuery } from '../graphql/queries/systemSetupInfo.mocks.ts'
  17. describe('guided setup manual email notification', () => {
  18. describe('when system is not ready', () => {
  19. beforeEach(() => {
  20. mockApplicationConfig({
  21. system_init_done: false,
  22. })
  23. })
  24. it('redirects to guided setup start', async () => {
  25. mockSystemSetupInfoQuery({
  26. systemSetupInfo: {
  27. status: EnumSystemSetupInfoStatus.New,
  28. type: null,
  29. },
  30. })
  31. const view = await visitView('/guided-setup/manual/email-notification')
  32. await vi.waitFor(() => {
  33. expect(
  34. view,
  35. 'correctly redirects to guided setup start screen',
  36. ).toHaveCurrentUrl('/guided-setup')
  37. })
  38. view.getByText('Set up a new system')
  39. })
  40. })
  41. describe('when system is ready for optional steps', () => {
  42. beforeEach(() => {
  43. mockApplicationConfig({
  44. system_init_done: true,
  45. })
  46. mockPermissions(['admin'])
  47. mockAuthentication(true)
  48. mockFormUpdaterQuery({
  49. formUpdater: {
  50. fields: {
  51. adapter: {
  52. initialValue: 'sendmail',
  53. options: [
  54. {
  55. value: 'smtp',
  56. label: 'SMTP - configure your own outgoing SMTP settings',
  57. },
  58. {
  59. value: 'sendmail',
  60. label:
  61. 'Local MTA (Sendmail/Postfix/Exim/â\u0080¦) - use server setup',
  62. },
  63. ],
  64. },
  65. notification_sender: {
  66. initialValue: 'Zammad Helpdesk <noreply@zammad.example.com>',
  67. },
  68. },
  69. },
  70. })
  71. })
  72. it('can save and continue to channels step', async () => {
  73. mockChannelEmailValidateConfigurationOutboundMutation({
  74. channelEmailValidateConfigurationOutbound: {
  75. success: true,
  76. errors: null,
  77. },
  78. })
  79. mockChannelEmailSetNotificationConfigurationMutation({
  80. channelEmailSetNotificationConfiguration: {
  81. success: true,
  82. },
  83. })
  84. const view = await visitView('/guided-setup/manual/email-notification')
  85. await flushPromises()
  86. await getNode('email-notification-setup')?.settled
  87. expect(view.getByText('Email Notification')).toBeInTheDocument()
  88. expect(view.getByLabelText('Send mails via')).toBeInTheDocument()
  89. const continueButton = view.getByRole('button', {
  90. name: 'Save and Continue',
  91. })
  92. await view.events.click(continueButton)
  93. await vi.waitFor(() => {
  94. expect(
  95. view,
  96. 'correctly redirects to guided setup email channel step',
  97. ).toHaveCurrentUrl('/guided-setup/manual/channels')
  98. })
  99. })
  100. it('shows warning when SSL verification is turned off', async () => {
  101. const view = await visitView('/guided-setup/manual/email-notification')
  102. await flushPromises()
  103. await getNode('email-notification-setup')?.settled
  104. const form = view.getByTestId('email-notification-setup')
  105. expect(queryByRole(form, 'alert')).not.toBeInTheDocument()
  106. const adapterField = view.getByLabelText('Send mails via')
  107. await view.events.click(adapterField)
  108. await view.events.click(view.getAllByRole('option')[0])
  109. expect(queryByRole(form, 'alert')).not.toBeInTheDocument()
  110. await view.events.click(view.getByLabelText('SSL verification'))
  111. let alert = getByRole(form, 'alert')
  112. expect(alert).toHaveTextContent(
  113. 'Turning off SSL verification is a security risk and should be used only temporary. Use this option at your own risk!',
  114. )
  115. await view.events.click(view.getByLabelText('SSL verification'))
  116. expect(alert).not.toBeInTheDocument()
  117. await view.events.click(view.getByLabelText('SSL verification'))
  118. alert = getByRole(form, 'alert')
  119. expect(alert).toBeInTheDocument()
  120. await view.events.click(adapterField)
  121. await view.events.click(view.getAllByRole('option')[1])
  122. expect(alert).not.toBeInTheDocument()
  123. })
  124. it('toggles SSL verification disabled state when a port number is provided', async () => {
  125. const view = await visitView('/guided-setup/manual/email-notification')
  126. await flushPromises()
  127. await getNode('email-notification-setup')?.settled
  128. const adapterField = view.getByLabelText('Send mails via')
  129. await view.events.click(adapterField)
  130. await view.events.click(view.getAllByRole('option')[0])
  131. expect(view.getByLabelText('SSL verification')).not.toBeDisabled()
  132. await view.events.type(view.getByLabelText('Port'), '25')
  133. await vi.waitFor(() => {
  134. expect(view.getByLabelText('SSL verification')).toBeDisabled()
  135. })
  136. await view.events.clear(view.getByLabelText('Port'))
  137. await vi.waitFor(() => {
  138. expect(view.getByLabelText('SSL verification')).not.toBeDisabled()
  139. })
  140. await view.events.type(view.getByLabelText('Port'), '465')
  141. await vi.waitFor(() => {
  142. expect(view.getByLabelText('SSL verification')).not.toBeDisabled()
  143. })
  144. await view.events.type(view.getByLabelText('Port'), '587')
  145. await vi.waitFor(() => {
  146. expect(view.getByLabelText('SSL verification')).not.toBeDisabled()
  147. })
  148. })
  149. it('submits `false` value when SSL verification is disabled', async () => {
  150. mockChannelEmailValidateConfigurationOutboundMutation({
  151. channelEmailValidateConfigurationOutbound: {
  152. success: true,
  153. errors: null,
  154. },
  155. })
  156. mockChannelEmailSetNotificationConfigurationMutation({
  157. channelEmailSetNotificationConfiguration: {
  158. success: true,
  159. },
  160. })
  161. const view = await visitView('/guided-setup/manual/email-notification')
  162. await flushPromises()
  163. await getNode('email-notification-setup')?.settled
  164. const adapterField = view.getByLabelText('Send mails via')
  165. await view.events.click(adapterField)
  166. await view.events.click(view.getAllByRole('option')[0])
  167. await view.events.type(view.getByLabelText('Host'), 'mail')
  168. await view.events.type(
  169. view.getByLabelText('User'),
  170. 'zammad@mail.test.dc.zammad.com',
  171. )
  172. await view.events.type(view.getByLabelText('Password'), 'zammad')
  173. await view.events.type(view.getByLabelText('Port'), '25')
  174. expect(
  175. getNode('email-notification-setup')?.find('sslVerify')?.value,
  176. ).toBe(true)
  177. await view.events.click(
  178. view.getByRole('button', {
  179. name: 'Save and Continue',
  180. }),
  181. )
  182. const calls =
  183. await waitForChannelEmailValidateConfigurationOutboundMutationCalls()
  184. expect(calls.at(-1)?.variables).toEqual(
  185. expect.objectContaining({
  186. outboundConfiguration: expect.objectContaining({
  187. sslVerify: false,
  188. }),
  189. }),
  190. )
  191. })
  192. it('can go back to system information step', async () => {
  193. const view = await visitView('/guided-setup/manual/email-notification')
  194. const goBackButton = view.getByRole('button', { name: 'Go Back' })
  195. await view.events.click(goBackButton)
  196. await vi.waitFor(() => {
  197. expect(
  198. view,
  199. 'correctly redirects to email notification step',
  200. ).toHaveCurrentUrl('/guided-setup/manual/system-information')
  201. })
  202. })
  203. it('can skip to channels step', async () => {
  204. const view = await visitView('/guided-setup/manual/email-notification')
  205. const skipButton = view.getByRole('button', { name: 'Skip' })
  206. await view.events.click(skipButton)
  207. await vi.waitFor(() => {
  208. expect(view, 'correctly redirects to channels step').toHaveCurrentUrl(
  209. '/guided-setup/manual/channels',
  210. )
  211. })
  212. })
  213. })
  214. })