getImageExtracts.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. 'use strict'
  2. import test from 'ava'
  3. import request from 'supertest'
  4. import sharp from 'sharp'
  5. import fs from 'fs-extra'
  6. import path from 'path'
  7. import { apiPrefix, imageServedUrl, imagesPath } from '../../config'
  8. import { json, getHttpServer } from './_test_functions'
  9. // ROUTE /getImageExtracts
  10. // Before each tests, start a server
  11. test.beforeEach(async t => (t.context.server = await getHttpServer()))
  12. test('GET /getImageExtracts', async t => {
  13. const res = await request(t.context.server)
  14. .get(`${apiPrefix}/getImageExtracts`)
  15. t.is(res.status, 400, json(res))
  16. t.true(res.body.message.includes('Missing parameter'), json(res.body))
  17. t.true(res.body.message.includes('sceneName'), json(res.body))
  18. t.true(res.body.message.includes('imageQuality'), json(res.body))
  19. t.true(res.body.message.includes('horizontalExtractCount'), json(res.body))
  20. t.true(res.body.message.includes('verticalExtractCount'), json(res.body))
  21. })
  22. test('GET /getImageExtracts?sceneName=/../&imageQuality=a&horizontalExtractCount=a&verticalExtractCount=a', async t => {
  23. const res = await request(t.context.server)
  24. .get(`${apiPrefix}/getImageExtracts?sceneName=/../&imageQuality=a&horizontalExtractCount=a&verticalExtractCount=a`)
  25. t.is(res.status, 400, json(res))
  26. t.true(res.body.message.includes('Invalid query parameter'), json(res.body))
  27. t.truthy(res.body.data.find(x => x.match(/The requested scene name.*is not valid/)), json(res.body))
  28. t.truthy(res.body.data.find(x => x.includes('The specified quality is not an integer')), json(res.body))
  29. t.truthy(res.body.data.find(x => x.includes('horizontal axis is not an integer')), json(res.body))
  30. t.truthy(res.body.data.find(x => x.includes('vertical axis is not an integer')), json(res.body))
  31. })
  32. test('GET /getImageExtracts?sceneName=bathroom&horizontalExtractCount=5&verticalExtractCount=2&imageQuality=max&nearestQuality=true', async t => {
  33. const res = await request(t.context.server)
  34. .get(`${apiPrefix}/getImageExtracts?sceneName=bathroom&horizontalExtractCount=5&verticalExtractCount=2&imageQuality=max&nearestQuality=true`)
  35. t.is(res.status, 400, json(res))
  36. t.true(res.body.message.includes('Invalid query parameter'), json(res.body))
  37. t.truthy(res.body.data.find(x => x.match(/Impossible to use.*min.*max.*median.*with.*nearestQuality/)), json(res.body))
  38. })
  39. test('GET /getImageExtracts?sceneName=unknown-scene-name&imageQuality=10&horizontalExtractCount=5&verticalExtractCount=2', async t => {
  40. const res = await request(t.context.server)
  41. .get(`${apiPrefix}/getImageExtracts?sceneName=unknown-scene-name&imageQuality=10&horizontalExtractCount=5&verticalExtractCount=2`)
  42. t.is(res.status, 500, json(res))
  43. t.truthy(res.body.message.match(/Can't access.*scene dir.*Check it exist.*and you have read permission/), json(res.body))
  44. })
  45. test('GET /getImageExtracts?sceneName=bathroom&imageQuality=99999&horizontalExtractCount=5&verticalExtractCount=2', async t => {
  46. const res = await request(t.context.server)
  47. .get(`${apiPrefix}/getImageExtracts?sceneName=bathroom&imageQuality=99999&horizontalExtractCount=5&verticalExtractCount=2`)
  48. t.is(res.status, 404, json(res))
  49. t.truthy(res.body.message.match(/requested quality.*not found for.*scene/), json(res.body))
  50. })
  51. test('GET /getImageExtracts?sceneName=bathroom&imageQuality=10&horizontalExtractCount=0&verticalExtractCount=9999', async t => {
  52. const res = await request(t.context.server)
  53. .get(`${apiPrefix}/getImageExtracts?sceneName=bathroom&imageQuality=10&horizontalExtractCount=0&verticalExtractCount=9999`)
  54. t.is(res.status, 400, json(res))
  55. t.true(res.body.message.includes('Invalid query parameter'), json(res.body))
  56. t.truthy(res.body.data.find(x => x.includes('Incompatible number of horizontal extracts')), json(res.body))
  57. t.truthy(res.body.data.find(x => x.includes('Incompatible number of vertical extracts')), json(res.body))
  58. })
  59. test('GET /getImageExtracts?sceneName=bathroom&imageQuality=min&horizontalExtractCount=5&verticalExtractCount=2', async t => {
  60. const res = await request(t.context.server)
  61. .get(`${apiPrefix}/getImageExtracts?sceneName=bathroom&imageQuality=min&horizontalExtractCount=5&verticalExtractCount=2`)
  62. t.is(res.status, 200, json(res))
  63. t.true(Array.isArray(res.body.data.extracts), json(res.body))
  64. t.is(res.body.data.extracts[0], `${imageServedUrl}/bathroom/extracts/x5_y2/zone00001/bathroom_zone00001_00010.png`, json(res.body))
  65. })
  66. test('GET /getImageExtracts?sceneName=bathroom&imageQuality=median&horizontalExtractCount=5&verticalExtractCount=2', async t => {
  67. const res = await request(t.context.server)
  68. .get(`${apiPrefix}/getImageExtracts?sceneName=bathroom&imageQuality=median&horizontalExtractCount=5&verticalExtractCount=2`)
  69. t.is(res.status, 200, json(res))
  70. t.true(Array.isArray(res.body.data.extracts), json(res.body))
  71. t.is(res.body.data.extracts[0], `${imageServedUrl}/bathroom/extracts/x5_y2/zone00001/bathroom_zone00001_00010.png`, json(res.body))
  72. })
  73. test('GET /getImageExtracts?sceneName=bathroom&imageQuality=max&horizontalExtractCount=5&verticalExtractCount=2', async t => {
  74. const res = await request(t.context.server)
  75. .get(`${apiPrefix}/getImageExtracts?sceneName=bathroom&imageQuality=max&horizontalExtractCount=5&verticalExtractCount=2`)
  76. t.is(res.status, 200, json(res))
  77. t.true(Array.isArray(res.body.data.extracts), json(res.body))
  78. t.is(res.body.data.extracts[0], `${imageServedUrl}/bathroom/extracts/x5_y2/zone00001/bathroom_zone00001_00010.png`, json(res.body))
  79. })
  80. test('GET /getImageExtracts?sceneName=bathroom&imageQuality=99999&horizontalExtractCount=5&verticalExtractCount=2&nearestQuality=true', async t => {
  81. const res = await request(t.context.server)
  82. .get(`${apiPrefix}/getImageExtracts?sceneName=bathroom&imageQuality=99999&horizontalExtractCount=5&verticalExtractCount=2&nearestQuality=true`)
  83. t.is(res.status, 200, json(res))
  84. t.is(res.body.data.extracts[0], `${imageServedUrl}/bathroom/extracts/x5_y2/zone00001/bathroom_zone00001_00010.png`, json(res.body))
  85. })
  86. test.serial('GET /getImageExtracts?sceneName=bathroom&imageQuality=10&horizontalExtractCount=5&verticalExtractCount=2', async t => {
  87. const res = await request(t.context.server)
  88. .get(`${apiPrefix}/getImageExtracts?sceneName=bathroom&imageQuality=10&horizontalExtractCount=5&verticalExtractCount=2`)
  89. t.is(res.status, 200, json(res))
  90. t.true(Array.isArray(res.body.data.extracts), json(res.body))
  91. t.is(res.body.data.extracts[0], `${imageServedUrl}/bathroom/extracts/x5_y2/zone00001/bathroom_zone00001_00010.png`, json(res.body))
  92. t.deepEqual(res.body.data.info, {
  93. extractsConfig: {
  94. x: 5,
  95. y: 2
  96. },
  97. extractsSize: {
  98. width: 160,
  99. height: 400
  100. },
  101. image: {
  102. link: `${imageServedUrl}/bathroom/bathroom_00010.png`,
  103. fileName: 'bathroom_00010.png',
  104. sceneName: 'bathroom',
  105. quality: 10,
  106. ext: 'png',
  107. metadata: {
  108. format: 'png',
  109. width: 800,
  110. height: 800,
  111. space: 'srgb',
  112. channels: 3,
  113. depth: 'uchar',
  114. density: 72,
  115. isProgressive: false,
  116. hasProfile: false,
  117. hasAlpha: false
  118. }
  119. }
  120. }, json(res.body))
  121. // Check link is accessible and is an image
  122. const res2 = await request(t.context.server)
  123. .get(`${imageServedUrl}/bathroom/extracts/x5_y2/zone00001/bathroom_zone00001_00010.png`)
  124. t.is(res2.status, 200, json(res2))
  125. t.is(res2.header['content-type'], 'image/png', json(res2))
  126. })
  127. test.serial('Check extracts were successfully generated', async t => {
  128. // Check the extract on the file system
  129. const extracts = path.resolve(imagesPath, 'bathroom', 'extracts')
  130. const aBathroomConfig = path.resolve(extracts, 'x5_y2')
  131. const aBathroomConfigZone = path.resolve(aBathroomConfig, 'zone00001')
  132. const aBathroomConfigZoneImg = path.resolve(aBathroomConfigZone, 'bathroom_zone00001_00010.png')
  133. const fsp = fs.promises
  134. // Check `bathroom/extracts`
  135. t.true(await fs.pathExists(extracts))
  136. t.deepEqual(await fsp.readdir(extracts), ['x5_y2'])
  137. // Check `bathroom/extracts/x5_y2`
  138. t.true(await fs.pathExists(aBathroomConfig), aBathroomConfig)
  139. t.is((await fsp.readdir(aBathroomConfig)).length, 10)
  140. // Check `bathroom/extracts/x5_y2/zone00001`
  141. t.true(await fs.pathExists(aBathroomConfigZone))
  142. t.is((await fsp.readdir(aBathroomConfigZone)).length, 1)
  143. // Check `bathroom/extracts/x5_y2/zone00001/bathroom_zone00001_00010.png`
  144. t.true(await fs.pathExists(aBathroomConfigZoneImg))
  145. // Check image's type, width and height
  146. const metadata = await sharp(aBathroomConfigZoneImg).metadata()
  147. t.is(metadata.width, 160, json(metadata))
  148. t.is(metadata.height, 400, json(metadata))
  149. t.is(metadata.format, 'png', json(metadata))
  150. })