editing-avatar.spec.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. import type { ExtendedRenderResult } from '@tests/support/components'
  3. import { visitView } from '@tests/support/components/visitView'
  4. import { mockAccount } from '@tests/support/mock-account'
  5. import { mockGraphQLApi } from '@tests/support/mock-graphql-api'
  6. import { defineComponent } from 'vue'
  7. import { AccountAvatarActiveDocument } from '../avatar/graphql/queries/active.api'
  8. import { AccountAvatarAddDocument } from '../avatar/graphql/mutations/add.api'
  9. import { AccountAvatarDeleteDocument } from '../avatar/graphql/mutations/delete.api'
  10. vi.mock('vue-advanced-cropper', () => {
  11. const Cropper = defineComponent({
  12. emits: ['change'],
  13. mounted() {
  14. this.$emit('change', {
  15. canvas: {
  16. toDataURL() {
  17. return 'cropped image url'
  18. },
  19. },
  20. })
  21. },
  22. template: '<div></div>',
  23. })
  24. return {
  25. Cropper,
  26. }
  27. })
  28. const mockAvatarImage =
  29. 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='
  30. const getAvatarObject = (deletable: boolean) => {
  31. return {
  32. id: 'Z2lkOi8vemFtbWFkL0F2YXRhci8yNA',
  33. default: true,
  34. deletable,
  35. initial: false,
  36. imageFull: mockAvatarImage,
  37. imageResize: mockAvatarImage,
  38. createdAt: '2022-07-12T06:54:45Z',
  39. updatedAt: '2022-07-12T06:54:45Z',
  40. }
  41. }
  42. const mockActiveAvatar = async (deletable = true) => {
  43. mockGraphQLApi(AccountAvatarActiveDocument).willResolve({
  44. accountAvatarActive: getAvatarObject(deletable),
  45. })
  46. }
  47. const mockAddAvatar = async () => {
  48. mockGraphQLApi(AccountAvatarAddDocument).willResolve({
  49. accountAvatarAdd: {
  50. avatar: getAvatarObject(true),
  51. errors: null,
  52. },
  53. })
  54. }
  55. const mockDeleteAvatar = async () => {
  56. mockGraphQLApi(AccountAvatarDeleteDocument).willResolve({
  57. accountAvatarDelete: {
  58. success: true,
  59. errors: null,
  60. },
  61. })
  62. }
  63. const checkShownAvatar = async (view: ExtendedRenderResult, image: string) => {
  64. const waitForAvatar = await view.findByTestId('common-avatar')
  65. expect(waitForAvatar).toHaveStyle({
  66. 'background-image': image,
  67. })
  68. }
  69. const uploadFile = async (view: ExtendedRenderResult, testFlag: string) => {
  70. expect(view.queryByText('Save')).not.toBeInTheDocument()
  71. const file = new File([], 'test.jpg', { type: 'image/jpeg' })
  72. await view.events.upload(view.getByTestId(testFlag), file)
  73. const saveButton = await view.findByText('Save')
  74. expect(saveButton).toBeVisible()
  75. await view.events.click(saveButton)
  76. }
  77. const removeAvatar = async (view: ExtendedRenderResult) => {
  78. await view.events.click(view.getByText('Delete'))
  79. await view.findByText('Delete avatar')
  80. await view.events.click(view.getByText('Delete avatar'))
  81. await checkShownAvatar(view, '')
  82. }
  83. describe('editing avatar', () => {
  84. beforeEach(() => {
  85. mockAccount({
  86. firstname: 'John',
  87. lastname: 'Doe',
  88. })
  89. })
  90. afterEach(() => {
  91. vi.spyOn(console, 'log').mockRestore()
  92. })
  93. it('shows the avatar', async () => {
  94. mockActiveAvatar()
  95. const view = await visitView('/account/avatar')
  96. await checkShownAvatar(view, `url(${mockAvatarImage})`)
  97. })
  98. it('can remove avatar', async () => {
  99. mockActiveAvatar()
  100. mockDeleteAvatar()
  101. const view = await visitView('/account/avatar')
  102. await view.findByText('Delete')
  103. await checkShownAvatar(view, `url(${mockAvatarImage})`)
  104. await removeAvatar(view)
  105. const avatar = await view.findByTestId('common-avatar')
  106. expect(avatar).toHaveTextContent('JD')
  107. })
  108. it('can not remove undeletable avatars', async () => {
  109. mockActiveAvatar(false)
  110. mockDeleteAvatar()
  111. const view = await visitView('/account/avatar')
  112. await view.findByTestId('common-avatar')
  113. const deleteButton = await view.findByText('Delete')
  114. expect(deleteButton).toHaveAttribute('disabled')
  115. })
  116. it('can upload image from camera', async () => {
  117. mockAddAvatar()
  118. mockActiveAvatar()
  119. const view = await visitView('/account/avatar')
  120. await uploadFile(view, 'fileCameraInput')
  121. await checkShownAvatar(view, `url(${mockAvatarImage})`)
  122. })
  123. it('can upload image from gallery', async () => {
  124. mockAddAvatar()
  125. mockActiveAvatar()
  126. const view = await visitView('/account/avatar')
  127. await uploadFile(view, 'fileGalleryInput')
  128. await checkShownAvatar(view, `url(${mockAvatarImage})`)
  129. })
  130. it('even after deleting I can upload an image', async () => {
  131. mockAddAvatar()
  132. mockActiveAvatar()
  133. mockDeleteAvatar()
  134. const view = await visitView('/account/avatar')
  135. await view.findByTestId('common-avatar')
  136. await checkShownAvatar(view, `url(${mockAvatarImage})`)
  137. await removeAvatar(view)
  138. await uploadFile(view, 'fileGalleryInput')
  139. await checkShownAvatar(view, `url(${mockAvatarImage})`)
  140. })
  141. it('after selecting image I can cancel the cropping', async () => {
  142. mockActiveAvatar()
  143. const view = await visitView('/account/avatar')
  144. const file = new File([], 'test.jpg', { type: 'image/jpeg' })
  145. await view.events.upload(view.getByTestId('fileGalleryInput'), file)
  146. const cancelButton = await view.findByText('Cancel')
  147. expect(cancelButton).toBeInTheDocument()
  148. await view.events.click(view.getByText('Cancel'))
  149. await checkShownAvatar(view, `url(${mockAvatarImage})`)
  150. })
  151. })