Ringtone app
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

177 lines
4.7 KiB

  1. import {FastifyInstance} from 'fastify'
  2. import {PrismaClient as RealPrismaClient} from '@prisma/client'
  3. import {container} from 'tsyringe'
  4. import {models} from '@tonality/library-common'
  5. import Uuid from '@tonality/library-uuid'
  6. import {build} from '../../helper'
  7. import {MockPrismaRepository} from '../../../src/utils/mocks'
  8. jest.mock('@prisma/client')
  9. const PrismaClient = RealPrismaClient as jest.Mock
  10. describe('ringtone: /api/ringtones', () => {
  11. let app: FastifyInstance
  12. beforeEach(() => {
  13. PrismaClient.mockImplementationOnce(() => ({
  14. user: new MockPrismaRepository<models.User>([
  15. {
  16. id: Uuid.parse('00000000-0000-0000-0000-000000000000'),
  17. username: 'TheoryOfNekomata',
  18. password: 'dummy password',
  19. },
  20. ], 'id'),
  21. ringtone: new MockPrismaRepository<models.Ringtone>([
  22. {
  23. id: Uuid.parse('00000000-0000-0000-0000-000000000000'),
  24. name: 'Ringtone 1',
  25. data: '4c4',
  26. tempo: 120,
  27. createdAt: new Date('2021-05-01'),
  28. updatedAt: new Date('2021-05-01'),
  29. deletedAt: null,
  30. composerUserId: Uuid.parse('00000000-0000-0000-0000-000000000000'),
  31. },
  32. {
  33. id: Uuid.parse('8df2751c-4c05-4831-9408-92af3b4a63e8'),
  34. name: 'Unique Ringtone 2',
  35. data: '4c4 8c4',
  36. tempo: 120,
  37. createdAt: new Date('2021-05-01'),
  38. updatedAt: new Date('2021-05-01'),
  39. deletedAt: null,
  40. composerUserId: Uuid.parse('00000000-0000-0000-0000-000000000000'),
  41. },
  42. {
  43. id: Uuid.parse('c8423931-6a08-41f6-8320-a5ce5367179f'),
  44. name: 'Deleted Ringtone 1',
  45. data: '4c4',
  46. tempo: 120,
  47. createdAt: new Date('2021-05-01'),
  48. updatedAt: new Date('2021-05-01'),
  49. deletedAt: new Date('2021-05-05'),
  50. composerUserId: Uuid.parse('00000000-0000-0000-0000-000000000000'),
  51. },
  52. ], 'id')
  53. }))
  54. })
  55. beforeEach(async () => {
  56. app = await build()
  57. })
  58. afterEach(async () => {
  59. container.clearInstances()
  60. await app.close()
  61. })
  62. describe('on searching', () => {
  63. it('should send the data to the front-end', async () => {
  64. const res = await app.inject({
  65. url: '/api/search/ringtones',
  66. query: {
  67. q: 'Unique',
  68. },
  69. method: 'GET',
  70. })
  71. const parsedPayload = JSON.parse(res.payload)
  72. expect(Array.isArray(parsedPayload.data)).toBe(true)
  73. })
  74. })
  75. describe('on browsing', () => {
  76. it('should send the data to the front-end', async () => {
  77. const res = await app.inject({
  78. url: '/api/ringtones',
  79. method: 'GET',
  80. })
  81. const parsedPayload = JSON.parse(res.payload)
  82. expect(Array.isArray(parsedPayload.data)).toBe(true)
  83. })
  84. })
  85. describe('on creation', () => {
  86. it('should store the data', async () => {
  87. const res = await app.inject({
  88. url: '/api/ringtones',
  89. method: 'POST',
  90. headers: {
  91. 'Content-Type': 'application/json',
  92. },
  93. payload: JSON.stringify({
  94. name: 'New Ringtone',
  95. data: '4c4',
  96. tempo: 120,
  97. composerUserId: '00000000-0000-0000-0000-000000000000',
  98. })
  99. })
  100. const parsedPayload = JSON.parse(res.payload)
  101. expect(parsedPayload.data).toEqual(expect.objectContaining({
  102. name: 'New Ringtone',
  103. data: '4c4',
  104. tempo: 120,
  105. }))
  106. })
  107. })
  108. describe('on updating', () => {
  109. it('should store the updated data', async () => {
  110. const res = await app.inject({
  111. url: '/api/ringtones/00000000-0000-0000-0000-000000000000',
  112. method: 'PATCH',
  113. headers: {
  114. 'Content-Type': 'application/json',
  115. },
  116. payload: JSON.stringify({
  117. name: 'Updated Ringtone',
  118. data: '4c8',
  119. tempo: 120,
  120. })
  121. })
  122. const parsedPayload = JSON.parse(res.payload)
  123. expect(parsedPayload.data).toEqual(expect.objectContaining({
  124. name: 'Updated Ringtone',
  125. data: '4c8',
  126. tempo: 120,
  127. }))
  128. expect(parsedPayload.data.createdAt).not.toEqual(parsedPayload.data.updatedAt)
  129. })
  130. })
  131. describe('on soft deletion', () => {
  132. it('should be tagged as deleted', async () => {
  133. const res = await app.inject({
  134. url: '/api/ringtones/00000000-0000-0000-0000-000000000000/delete',
  135. method: 'POST',
  136. })
  137. const parsedPayload = JSON.parse(res.payload)
  138. expect(parsedPayload.data).toEqual(expect.objectContaining({
  139. deletedAt: expect.any(String),
  140. }))
  141. })
  142. })
  143. describe('on undoing deletion', () => {
  144. it('should be untagged as deleted', async () => {
  145. const res = await app.inject({
  146. url: '/api/ringtones/00000000-0000-0000-0000-000000000000/delete',
  147. method: 'DELETE',
  148. })
  149. const parsedPayload = JSON.parse(res.payload)
  150. expect(parsedPayload.data).toEqual(expect.objectContaining({
  151. deletedAt: null,
  152. }))
  153. })
  154. })
  155. describe('on hard deletion', () => {
  156. it('should be removed', async () => {
  157. const res = await app.inject({
  158. url: '/api/ringtones/00000000-0000-0000-0000-000000000000',
  159. method: 'DELETE',
  160. })
  161. expect(res.statusCode).toBe(204)
  162. })
  163. })
  164. })