ニジカ投稿局 https://tv.nizika.tv
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.
 
 
 
 
 

195 lines
5.8 KiB

  1. /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
  2. import { expect } from 'chai'
  3. import { pathExists } from 'fs-extra/esm'
  4. import { readFile } from 'fs/promises'
  5. import { join, parse } from 'path'
  6. import { HttpStatusCode } from '@peertube/peertube-models'
  7. import { buildAbsoluteFixturePath } from '@peertube/peertube-node-utils'
  8. import { makeGetRequest, PeerTubeServer } from '@peertube/peertube-server-commands'
  9. // Default interval -> 5 minutes
  10. function dateIsValid (dateString: string | Date, interval = 300000) {
  11. const dateToCheck = new Date(dateString)
  12. const now = new Date()
  13. return Math.abs(now.getTime() - dateToCheck.getTime()) <= interval
  14. }
  15. function expectStartWith (str: string, start: string) {
  16. expect(str.startsWith(start), `${str} does not start with ${start}`).to.be.true
  17. }
  18. function expectNotStartWith (str: string, start: string) {
  19. expect(str.startsWith(start), `${str} does not start with ${start}`).to.be.false
  20. }
  21. function expectEndWith (str: string, end: string) {
  22. expect(str.endsWith(end), `${str} does not end with ${end}`).to.be.true
  23. }
  24. // ---------------------------------------------------------------------------
  25. async function expectLogDoesNotContain (server: PeerTubeServer, str: string) {
  26. const content = await server.servers.getLogContent()
  27. expect(content.toString()).to.not.contain(str)
  28. }
  29. async function expectLogContain (server: PeerTubeServer, str: string) {
  30. const content = await server.servers.getLogContent()
  31. expect(content.toString()).to.contain(str)
  32. }
  33. async function testAvatarSize (options: {
  34. url: string
  35. imageName: string
  36. avatar: {
  37. width: number
  38. path: string
  39. }
  40. }) {
  41. const { url, imageName, avatar } = options
  42. const { body } = await makeGetRequest({
  43. url,
  44. path: avatar.path,
  45. expectedStatus: HttpStatusCode.OK_200
  46. })
  47. const extension = parse(avatar.path).ext
  48. // We don't test big GIF avatars
  49. if (extension === '.gif' && avatar.width > 150) return
  50. const data = await readFile(buildAbsoluteFixturePath(imageName + extension))
  51. const minLength = data.length - ((40 * data.length) / 100)
  52. const maxLength = data.length + ((40 * data.length) / 100)
  53. expect(body.length).to.be.above(minLength, 'the generated image is way smaller than the recorded fixture')
  54. expect(body.length).to.be.below(maxLength, 'the generated image is way larger than the recorded fixture')
  55. }
  56. async function testImageGeneratedByFFmpeg (url: string, imageName: string, imageHTTPPath: string, extension = '.jpg') {
  57. if (process.env.ENABLE_FFMPEG_THUMBNAIL_PIXEL_COMPARISON_TESTS !== 'true') {
  58. console.log(
  59. 'Pixel comparison of image generated by ffmpeg is disabled. ' +
  60. 'You can enable it using `ENABLE_FFMPEG_THUMBNAIL_PIXEL_COMPARISON_TESTS=true env variable')
  61. return
  62. }
  63. return testImage(url, imageName, imageHTTPPath, extension)
  64. }
  65. async function testImage (url: string, imageName: string, imageHTTPPath: string, extension = '.jpg') {
  66. const res = await makeGetRequest({
  67. url,
  68. path: imageHTTPPath,
  69. expectedStatus: HttpStatusCode.OK_200
  70. })
  71. const body = res.body
  72. const data = await readFile(buildAbsoluteFixturePath(imageName + extension))
  73. const { PNG } = await import('pngjs')
  74. const JPEG = await import('jpeg-js')
  75. const pixelmatch = (await import('pixelmatch')).default
  76. const img1 = imageHTTPPath.endsWith('.png')
  77. ? PNG.sync.read(body)
  78. : JPEG.decode(body)
  79. const img2 = extension === '.png'
  80. ? PNG.sync.read(data)
  81. : JPEG.decode(data)
  82. const errorMsg = `${imageHTTPPath} image is not the same as ${imageName}${extension}`
  83. try {
  84. const result = pixelmatch(img1.data, img2.data, null, img1.width, img1.height, { threshold: 0.1 })
  85. expect(result).to.equal(0, errorMsg)
  86. } catch (err) {
  87. throw new Error(`${errorMsg}: ${err.message}`)
  88. }
  89. }
  90. async function testFileExistsOnFSOrNot (server: PeerTubeServer, directory: string, filePath: string, exist: boolean) {
  91. const base = server.servers.buildDirectory(directory)
  92. expect(await pathExists(join(base, filePath))).to.equal(exist)
  93. }
  94. // ---------------------------------------------------------------------------
  95. function checkBadStartPagination (url: string, path: string, token?: string, query = {}) {
  96. return makeGetRequest({
  97. url,
  98. path,
  99. token,
  100. query: { ...query, start: 'hello' },
  101. expectedStatus: HttpStatusCode.BAD_REQUEST_400
  102. })
  103. }
  104. async function checkBadCountPagination (url: string, path: string, token?: string, query = {}) {
  105. await makeGetRequest({
  106. url,
  107. path,
  108. token,
  109. query: { ...query, count: 'hello' },
  110. expectedStatus: HttpStatusCode.BAD_REQUEST_400
  111. })
  112. await makeGetRequest({
  113. url,
  114. path,
  115. token,
  116. query: { ...query, count: 2000 },
  117. expectedStatus: HttpStatusCode.BAD_REQUEST_400
  118. })
  119. }
  120. function checkBadSortPagination (url: string, path: string, token?: string, query = {}) {
  121. return makeGetRequest({
  122. url,
  123. path,
  124. token,
  125. query: { ...query, sort: 'hello' },
  126. expectedStatus: HttpStatusCode.BAD_REQUEST_400
  127. })
  128. }
  129. // ---------------------------------------------------------------------------
  130. async function checkVideoDuration (server: PeerTubeServer, videoUUID: string, duration: number) {
  131. const video = await server.videos.get({ id: videoUUID })
  132. expect(video.duration).to.be.approximately(duration, 1)
  133. for (const file of video.files) {
  134. const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
  135. for (const stream of metadata.streams) {
  136. expect(Math.round(stream.duration)).to.be.approximately(duration, 1)
  137. }
  138. }
  139. }
  140. export {
  141. dateIsValid,
  142. testImageGeneratedByFFmpeg,
  143. testAvatarSize,
  144. testImage,
  145. expectLogDoesNotContain,
  146. testFileExistsOnFSOrNot,
  147. expectStartWith,
  148. expectNotStartWith,
  149. expectEndWith,
  150. checkBadStartPagination,
  151. checkBadCountPagination,
  152. checkBadSortPagination,
  153. checkVideoDuration,
  154. expectLogContain
  155. }