index.test.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. import ThumbnailGeneratorPlugin from './index'
  2. import Plugin from '../../core/Plugin'
  3. const delay = duration => new Promise(resolve => setTimeout(resolve, duration))
  4. describe('uploader/ThumbnailGeneratorPlugin', () => {
  5. it('should initialise successfully', () => {
  6. const plugin = new ThumbnailGeneratorPlugin(null, {})
  7. expect(plugin instanceof Plugin).toEqual(true)
  8. })
  9. it('should accept the thumbnailWidth option and override the default', () => {
  10. const plugin1 = new ThumbnailGeneratorPlugin(null) // eslint-disable-line no-new
  11. expect(plugin1.opts.thumbnailWidth).toEqual(200)
  12. const plugin2 = new ThumbnailGeneratorPlugin(null, { thumbnailWidth: 100 }) // eslint-disable-line no-new
  13. expect(plugin2.opts.thumbnailWidth).toEqual(100)
  14. })
  15. describe('install', () => {
  16. it('should subscribe to uppy file-added event', () => {
  17. const core = {
  18. on: jest.fn()
  19. }
  20. const plugin = new ThumbnailGeneratorPlugin(core)
  21. plugin.addToQueue = jest.fn()
  22. plugin.install()
  23. expect(core.on).toHaveBeenCalledTimes(1)
  24. expect(core.on).toHaveBeenCalledWith('file-added', plugin.addToQueue)
  25. })
  26. })
  27. describe('uninstall', () => {
  28. it('should unsubscribe from uppy file-added event', () => {
  29. const core = {
  30. on: jest.fn(),
  31. off: jest.fn()
  32. }
  33. const plugin = new ThumbnailGeneratorPlugin(core)
  34. plugin.addToQueue = jest.fn()
  35. plugin.install()
  36. expect(core.on).toHaveBeenCalledTimes(1)
  37. plugin.uninstall()
  38. expect(core.off).toHaveBeenCalledTimes(1)
  39. expect(core.off).toHaveBeenCalledWith('file-added', plugin.addToQueue)
  40. })
  41. })
  42. describe('queue', () => {
  43. it('should add a new file to the queue and start processing the queue when queueProcessing is false', () => {
  44. const core = {}
  45. const plugin = new ThumbnailGeneratorPlugin(core)
  46. plugin.processQueue = jest.fn()
  47. const file = { foo: 'bar' }
  48. plugin.queueProcessing = false
  49. plugin.addToQueue(file)
  50. expect(plugin.queue).toEqual([{ foo: 'bar' }])
  51. expect(plugin.processQueue).toHaveBeenCalledTimes(1)
  52. const file2 = { foo: 'bar2' }
  53. plugin.queueProcessing = true
  54. plugin.addToQueue(file2)
  55. expect(plugin.queue).toEqual([{ foo: 'bar' }, { foo: 'bar2' }])
  56. expect(plugin.processQueue).toHaveBeenCalledTimes(1)
  57. })
  58. it('should process items in the queue one by one', () => {
  59. const core = {}
  60. const plugin = new ThumbnailGeneratorPlugin(core)
  61. plugin.requestThumbnail = jest.fn(() => delay(100))
  62. const file1 = { foo: 'bar' }
  63. const file2 = { foo: 'bar2' }
  64. const file3 = { foo: 'bar3' }
  65. plugin.addToQueue(file1)
  66. plugin.addToQueue(file2)
  67. plugin.addToQueue(file3)
  68. expect(plugin.requestThumbnail).toHaveBeenCalledTimes(1)
  69. expect(plugin.requestThumbnail).toHaveBeenCalledWith(file1)
  70. return delay(110)
  71. .then(() => {
  72. expect(plugin.requestThumbnail).toHaveBeenCalledTimes(2)
  73. expect(plugin.requestThumbnail).toHaveBeenCalledWith(file2)
  74. return delay(110)
  75. })
  76. .then(() => {
  77. expect(plugin.requestThumbnail).toHaveBeenCalledTimes(3)
  78. expect(plugin.requestThumbnail).toHaveBeenCalledWith(file3)
  79. return delay(110)
  80. })
  81. .then(() => {
  82. expect(plugin.queue).toEqual([])
  83. expect(plugin.queueProcessing).toEqual(false)
  84. })
  85. })
  86. })
  87. describe('requestThumbnail', () => {
  88. it('should call createThumbnail if it is a supported filetype', () => {
  89. const core = {}
  90. const plugin = new ThumbnailGeneratorPlugin(core)
  91. plugin.createThumbnail = jest
  92. .fn()
  93. .mockReturnValue(Promise.resolve('preview'))
  94. plugin.setPreviewURL = jest.fn()
  95. const file = { id: 'file1', type: 'image/png', isRemote: false }
  96. return plugin.requestThumbnail(file).then(() => {
  97. expect(plugin.createThumbnail).toHaveBeenCalledTimes(1)
  98. expect(plugin.createThumbnail).toHaveBeenCalledWith(
  99. file,
  100. plugin.opts.thumbnailWidth
  101. )
  102. })
  103. })
  104. it('should not call createThumbnail if it is not a supported filetype', () => {
  105. const core = {}
  106. const plugin = new ThumbnailGeneratorPlugin(core)
  107. plugin.createThumbnail = jest
  108. .fn()
  109. .mockReturnValue(Promise.resolve('preview'))
  110. plugin.setPreviewURL = jest.fn()
  111. const file = { id: 'file1', type: 'text/html', isRemote: false }
  112. return plugin.requestThumbnail(file).then(() => {
  113. expect(plugin.createThumbnail).toHaveBeenCalledTimes(0)
  114. })
  115. })
  116. it('should not call createThumbnail if the file is remote', () => {
  117. const core = {}
  118. const plugin = new ThumbnailGeneratorPlugin(core)
  119. plugin.createThumbnail = jest
  120. .fn()
  121. .mockReturnValue(Promise.resolve('preview'))
  122. plugin.setPreviewURL = jest.fn()
  123. const file = { id: 'file1', type: 'image/png', isRemote: true }
  124. return plugin.requestThumbnail(file).then(() => {
  125. expect(plugin.createThumbnail).toHaveBeenCalledTimes(0)
  126. })
  127. })
  128. it('should call setPreviewURL with the thumbnail image', () => {
  129. const core = {}
  130. const plugin = new ThumbnailGeneratorPlugin(core)
  131. plugin.createThumbnail = jest
  132. .fn()
  133. .mockReturnValue(Promise.resolve('preview'))
  134. plugin.setPreviewURL = jest.fn()
  135. const file = { id: 'file1', type: 'image/png', isRemote: false }
  136. return plugin.requestThumbnail(file).then(() => {
  137. expect(plugin.setPreviewURL).toHaveBeenCalledTimes(1)
  138. expect(plugin.setPreviewURL).toHaveBeenCalledWith('file1', 'preview')
  139. })
  140. })
  141. })
  142. describe('setPreviewURL', () => {
  143. it('should update the preview url for the specified image', () => {
  144. const core = {
  145. state: {
  146. files: {
  147. file1: {
  148. preview: 'foo'
  149. },
  150. file2: {
  151. preview: 'boo'
  152. }
  153. }
  154. },
  155. setState: jest.fn()
  156. }
  157. const plugin = new ThumbnailGeneratorPlugin(core)
  158. plugin.setPreviewURL('file1', 'moo')
  159. expect(core.setState).toHaveBeenCalledTimes(1)
  160. expect(core.setState).toHaveBeenCalledWith({
  161. files: { file1: { preview: 'moo' }, file2: { preview: 'boo' } }
  162. })
  163. })
  164. })
  165. describe('getProportionalHeight', () => {
  166. it('should calculate the resized height based on the specified width of the image whilst keeping aspect ratio', () => {
  167. const core = {}
  168. const plugin = new ThumbnailGeneratorPlugin(core)
  169. expect(
  170. plugin.getProportionalHeight({ width: 200, height: 100 }, 50)
  171. ).toEqual(25)
  172. expect(
  173. plugin.getProportionalHeight({ width: 66, height: 66 }, 33)
  174. ).toEqual(33)
  175. expect(
  176. plugin.getProportionalHeight({ width: 201.2, height: 198.2 }, 47)
  177. ).toEqual(46)
  178. })
  179. })
  180. describe('canvasToBlob', () => {
  181. it('should use canvas.toBlob if available', () => {
  182. const core = {}
  183. const plugin = new ThumbnailGeneratorPlugin(core)
  184. const canvas = {
  185. toBlob: jest.fn()
  186. }
  187. plugin.canvasToBlob(canvas, 'type', 90)
  188. expect(canvas.toBlob).toHaveBeenCalledTimes(1)
  189. expect(canvas.toBlob.mock.calls[0][1]).toEqual('type')
  190. expect(canvas.toBlob.mock.calls[0][2]).toEqual(90)
  191. })
  192. })
  193. describe('downScaleInSteps', () => {
  194. let originalDocumentCreateElement
  195. let originalURLCreateObjectURL
  196. beforeEach(() => {
  197. originalDocumentCreateElement = document.createElement
  198. originalURLCreateObjectURL = URL.createObjectURL
  199. })
  200. afterEach(() => {
  201. document.createElement = originalDocumentCreateElement
  202. URL.createObjectURL = originalURLCreateObjectURL
  203. })
  204. xit('should scale down the image by the specified number of steps', () => {
  205. const core = {}
  206. const plugin = new ThumbnailGeneratorPlugin(core)
  207. const image = {
  208. width: 1000,
  209. height: 800
  210. }
  211. const context = {
  212. drawImage: jest.fn()
  213. }
  214. const canvas = {
  215. width: 0,
  216. height: 0,
  217. getContext: jest.fn().mockReturnValue(context)
  218. }
  219. document.createElement = jest.fn().mockReturnValue(canvas)
  220. const result = plugin.downScaleInSteps(image, 3)
  221. const newImage = {
  222. getContext: canvas.getContext,
  223. height: 100,
  224. width: 125
  225. }
  226. expect(result).toEqual({
  227. image: newImage,
  228. sourceWidth: 125,
  229. sourceHeight: 100
  230. })
  231. expect(context.drawImage).toHaveBeenCalledTimes(3)
  232. expect(context.drawImage.mock.calls).toEqual([
  233. [{ width: 1000, height: 800 }, 0, 0, 1000, 800, 0, 0, 500, 400],
  234. [
  235. { width: 125, height: 100, getContext: canvas.getContext },
  236. 0,
  237. 0,
  238. 500,
  239. 400,
  240. 0,
  241. 0,
  242. 250,
  243. 200
  244. ],
  245. [
  246. { width: 125, height: 100, getContext: canvas.getContext },
  247. 0,
  248. 0,
  249. 250,
  250. 200,
  251. 0,
  252. 0,
  253. 125,
  254. 100
  255. ]
  256. ])
  257. })
  258. })
  259. describe('resizeImage', () => {
  260. it('should return a canvas with the resized image on it', () => {
  261. const core = {}
  262. const plugin = new ThumbnailGeneratorPlugin(core)
  263. const image = {
  264. width: 1000,
  265. height: 800
  266. }
  267. plugin.downScaleInSteps = jest.fn().mockReturnValue({
  268. image: {
  269. height: 160,
  270. width: 200
  271. },
  272. sourceWidth: 200,
  273. sourceHeight: 160
  274. })
  275. const context = {
  276. drawImage: jest.fn()
  277. }
  278. const canvas = {
  279. width: 0,
  280. height: 0,
  281. getContext: jest.fn().mockReturnValue(context)
  282. }
  283. document.createElement = jest.fn().mockReturnValue(canvas)
  284. const result = plugin.resizeImage(image, 200, 160)
  285. expect(result).toEqual({
  286. width: 200,
  287. height: 160,
  288. getContext: canvas.getContext
  289. })
  290. })
  291. })
  292. })