UrlCacheTests.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /* eslint-disable
  2. no-return-assign,
  3. no-unused-vars,
  4. */
  5. // TODO: This file was created by bulk-decaffeinate.
  6. // Fix any style issues and re-enable lint.
  7. /*
  8. * decaffeinate suggestions:
  9. * DS101: Remove unnecessary use of Array.from
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  12. */
  13. const SandboxedModule = require('sandboxed-module')
  14. const sinon = require('sinon')
  15. const modulePath = require('path').join(__dirname, '../../../app/js/UrlCache')
  16. const { EventEmitter } = require('events')
  17. describe('UrlCache', function () {
  18. beforeEach(function () {
  19. this.callback = sinon.stub()
  20. this.url = 'www.example.com/file'
  21. this.project_id = 'project-id-123'
  22. return (this.UrlCache = SandboxedModule.require(modulePath, {
  23. requires: {
  24. './db': {},
  25. './UrlFetcher': (this.UrlFetcher = {}),
  26. 'settings-sharelatex': (this.Settings = {
  27. path: { clsiCacheDir: '/cache/dir' }
  28. }),
  29. fs: (this.fs = {})
  30. }
  31. }))
  32. })
  33. describe('_doesUrlNeedDownloading', function () {
  34. beforeEach(function () {
  35. this.lastModified = new Date()
  36. return (this.lastModifiedRoundedToSeconds = new Date(
  37. Math.floor(this.lastModified.getTime() / 1000) * 1000
  38. ))
  39. })
  40. describe('when URL does not exist in cache', function () {
  41. beforeEach(function () {
  42. this.UrlCache._findUrlDetails = sinon.stub().callsArgWith(2, null, null)
  43. return this.UrlCache._doesUrlNeedDownloading(
  44. this.project_id,
  45. this.url,
  46. this.lastModified,
  47. this.callback
  48. )
  49. })
  50. return it('should return the callback with true', function () {
  51. return this.callback.calledWith(null, true).should.equal(true)
  52. })
  53. })
  54. return describe('when URL does exist in cache', function () {
  55. beforeEach(function () {
  56. this.urlDetails = {}
  57. return (this.UrlCache._findUrlDetails = sinon
  58. .stub()
  59. .callsArgWith(2, null, this.urlDetails))
  60. })
  61. describe('when the modified date is more recent than the cached modified date', function () {
  62. beforeEach(function () {
  63. this.urlDetails.lastModified = new Date(
  64. this.lastModified.getTime() - 1000
  65. )
  66. return this.UrlCache._doesUrlNeedDownloading(
  67. this.project_id,
  68. this.url,
  69. this.lastModified,
  70. this.callback
  71. )
  72. })
  73. it('should get the url details', function () {
  74. return this.UrlCache._findUrlDetails
  75. .calledWith(this.project_id, this.url)
  76. .should.equal(true)
  77. })
  78. return it('should return the callback with true', function () {
  79. return this.callback.calledWith(null, true).should.equal(true)
  80. })
  81. })
  82. describe('when the cached modified date is more recent than the modified date', function () {
  83. beforeEach(function () {
  84. this.urlDetails.lastModified = new Date(
  85. this.lastModified.getTime() + 1000
  86. )
  87. return this.UrlCache._doesUrlNeedDownloading(
  88. this.project_id,
  89. this.url,
  90. this.lastModified,
  91. this.callback
  92. )
  93. })
  94. return it('should return the callback with false', function () {
  95. return this.callback.calledWith(null, false).should.equal(true)
  96. })
  97. })
  98. describe('when the cached modified date is equal to the modified date', function () {
  99. beforeEach(function () {
  100. this.urlDetails.lastModified = this.lastModified
  101. return this.UrlCache._doesUrlNeedDownloading(
  102. this.project_id,
  103. this.url,
  104. this.lastModified,
  105. this.callback
  106. )
  107. })
  108. return it('should return the callback with false', function () {
  109. return this.callback.calledWith(null, false).should.equal(true)
  110. })
  111. })
  112. describe('when the provided modified date does not exist', function () {
  113. beforeEach(function () {
  114. this.lastModified = null
  115. return this.UrlCache._doesUrlNeedDownloading(
  116. this.project_id,
  117. this.url,
  118. this.lastModified,
  119. this.callback
  120. )
  121. })
  122. return it('should return the callback with true', function () {
  123. return this.callback.calledWith(null, true).should.equal(true)
  124. })
  125. })
  126. return describe('when the URL does not have a modified date', function () {
  127. beforeEach(function () {
  128. this.urlDetails.lastModified = null
  129. return this.UrlCache._doesUrlNeedDownloading(
  130. this.project_id,
  131. this.url,
  132. this.lastModified,
  133. this.callback
  134. )
  135. })
  136. return it('should return the callback with true', function () {
  137. return this.callback.calledWith(null, true).should.equal(true)
  138. })
  139. })
  140. })
  141. })
  142. describe('_ensureUrlIsInCache', function () {
  143. beforeEach(function () {
  144. this.UrlFetcher.pipeUrlToFileWithRetry = sinon.stub().callsArg(2)
  145. return (this.UrlCache._updateOrCreateUrlDetails = sinon
  146. .stub()
  147. .callsArg(3))
  148. })
  149. describe('when the URL needs updating', function () {
  150. beforeEach(function () {
  151. this.UrlCache._doesUrlNeedDownloading = sinon
  152. .stub()
  153. .callsArgWith(3, null, true)
  154. return this.UrlCache._ensureUrlIsInCache(
  155. this.project_id,
  156. this.url,
  157. this.lastModified,
  158. this.callback
  159. )
  160. })
  161. it('should check that the url needs downloading', function () {
  162. return this.UrlCache._doesUrlNeedDownloading
  163. .calledWith(
  164. this.project_id,
  165. this.url,
  166. this.lastModifiedRoundedToSeconds
  167. )
  168. .should.equal(true)
  169. })
  170. it('should download the URL to the cache file', function () {
  171. return this.UrlFetcher.pipeUrlToFileWithRetry
  172. .calledWith(
  173. this.url,
  174. this.UrlCache._cacheFilePathForUrl(this.project_id, this.url)
  175. )
  176. .should.equal(true)
  177. })
  178. it('should update the database entry', function () {
  179. return this.UrlCache._updateOrCreateUrlDetails
  180. .calledWith(
  181. this.project_id,
  182. this.url,
  183. this.lastModifiedRoundedToSeconds
  184. )
  185. .should.equal(true)
  186. })
  187. return it('should return the callback with the cache file path', function () {
  188. return this.callback
  189. .calledWith(
  190. null,
  191. this.UrlCache._cacheFilePathForUrl(this.project_id, this.url)
  192. )
  193. .should.equal(true)
  194. })
  195. })
  196. return describe('when the URL does not need updating', function () {
  197. beforeEach(function () {
  198. this.UrlCache._doesUrlNeedDownloading = sinon
  199. .stub()
  200. .callsArgWith(3, null, false)
  201. return this.UrlCache._ensureUrlIsInCache(
  202. this.project_id,
  203. this.url,
  204. this.lastModified,
  205. this.callback
  206. )
  207. })
  208. it('should not download the URL to the cache file', function () {
  209. return this.UrlFetcher.pipeUrlToFileWithRetry.called.should.equal(false)
  210. })
  211. return it('should return the callback with the cache file path', function () {
  212. return this.callback
  213. .calledWith(
  214. null,
  215. this.UrlCache._cacheFilePathForUrl(this.project_id, this.url)
  216. )
  217. .should.equal(true)
  218. })
  219. })
  220. })
  221. describe('downloadUrlToFile', function () {
  222. beforeEach(function () {
  223. this.cachePath = 'path/to/cached/url'
  224. this.destPath = 'path/to/destination'
  225. this.UrlCache._copyFile = sinon.stub().callsArg(2)
  226. this.UrlCache._ensureUrlIsInCache = sinon
  227. .stub()
  228. .callsArgWith(3, null, this.cachePath)
  229. return this.UrlCache.downloadUrlToFile(
  230. this.project_id,
  231. this.url,
  232. this.destPath,
  233. this.lastModified,
  234. this.callback
  235. )
  236. })
  237. it('should ensure the URL is downloaded and updated in the cache', function () {
  238. return this.UrlCache._ensureUrlIsInCache
  239. .calledWith(this.project_id, this.url, this.lastModified)
  240. .should.equal(true)
  241. })
  242. it('should copy the file to the new location', function () {
  243. return this.UrlCache._copyFile
  244. .calledWith(this.cachePath, this.destPath)
  245. .should.equal(true)
  246. })
  247. return it('should call the callback', function () {
  248. return this.callback.called.should.equal(true)
  249. })
  250. })
  251. describe('_deleteUrlCacheFromDisk', function () {
  252. beforeEach(function () {
  253. this.fs.unlink = sinon.stub().callsArg(1)
  254. return this.UrlCache._deleteUrlCacheFromDisk(
  255. this.project_id,
  256. this.url,
  257. this.callback
  258. )
  259. })
  260. it('should delete the cache file', function () {
  261. return this.fs.unlink
  262. .calledWith(
  263. this.UrlCache._cacheFilePathForUrl(this.project_id, this.url)
  264. )
  265. .should.equal(true)
  266. })
  267. return it('should call the callback', function () {
  268. return this.callback.called.should.equal(true)
  269. })
  270. })
  271. describe('_clearUrlFromCache', function () {
  272. beforeEach(function () {
  273. this.UrlCache._deleteUrlCacheFromDisk = sinon.stub().callsArg(2)
  274. this.UrlCache._clearUrlDetails = sinon.stub().callsArg(2)
  275. return this.UrlCache._clearUrlFromCache(
  276. this.project_id,
  277. this.url,
  278. this.callback
  279. )
  280. })
  281. it('should delete the file on disk', function () {
  282. return this.UrlCache._deleteUrlCacheFromDisk
  283. .calledWith(this.project_id, this.url)
  284. .should.equal(true)
  285. })
  286. it('should clear the entry in the database', function () {
  287. return this.UrlCache._clearUrlDetails
  288. .calledWith(this.project_id, this.url)
  289. .should.equal(true)
  290. })
  291. return it('should call the callback', function () {
  292. return this.callback.called.should.equal(true)
  293. })
  294. })
  295. return describe('clearProject', function () {
  296. beforeEach(function () {
  297. this.urls = ['www.example.com/file1', 'www.example.com/file2']
  298. this.UrlCache._findAllUrlsInProject = sinon
  299. .stub()
  300. .callsArgWith(1, null, this.urls)
  301. this.UrlCache._clearUrlFromCache = sinon.stub().callsArg(2)
  302. return this.UrlCache.clearProject(this.project_id, this.callback)
  303. })
  304. it('should clear the cache for each url in the project', function () {
  305. return Array.from(this.urls).map((url) =>
  306. this.UrlCache._clearUrlFromCache
  307. .calledWith(this.project_id, url)
  308. .should.equal(true)
  309. )
  310. })
  311. return it('should call the callback', function () {
  312. return this.callback.called.should.equal(true)
  313. })
  314. })
  315. })