UpdateMergerTests.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. const SandboxedModule = require('sandboxed-module')
  2. const sinon = require('sinon')
  3. const modulePath = require('path').join(
  4. __dirname,
  5. '../../../../app/src/Features/ThirdPartyDataStore/UpdateMerger.js'
  6. )
  7. const BufferedStream = require('bufferedstream')
  8. describe('UpdateMerger :', function () {
  9. beforeEach(function () {
  10. this.updateMerger = SandboxedModule.require(modulePath, {
  11. requires: {
  12. fs: (this.fs = { unlink: sinon.stub().callsArgWith(1) }),
  13. '../Editor/EditorController': (this.EditorController = {}),
  14. '../Uploads/FileTypeManager': (this.FileTypeManager = {}),
  15. '../../infrastructure/FileWriter': (this.FileWriter = {}),
  16. '../Project/ProjectEntityHandler': (this.ProjectEntityHandler = {}),
  17. '@overleaf/settings': { path: { dumpPath: 'dump_here' } },
  18. },
  19. })
  20. this.project_id = 'project_id_here'
  21. this.user_id = 'mock-user-id'
  22. this.docPath = this.newDocPath = '/folder/doc.tex'
  23. this.filePath = this.newFilePath = '/folder/file.png'
  24. this.existingDocPath = '/folder/other.tex'
  25. this.existingFilePath = '/folder/fig1.pdf'
  26. this.linkedFileData = { provider: 'url' }
  27. this.existingDocs = [{ path: '/main.tex' }, { path: '/folder/other.tex' }]
  28. this.existingFiles = [{ path: '/figure.pdf' }, { path: '/folder/fig1.pdf' }]
  29. this.ProjectEntityHandler.getAllEntities = sinon
  30. .stub()
  31. .callsArgWith(1, null, this.existingDocs, this.existingFiles)
  32. this.fsPath = '/tmp/file/path'
  33. this.source = 'dropbox'
  34. this.updateRequest = new BufferedStream()
  35. this.FileWriter.writeStreamToDisk = sinon.stub().yields(null, this.fsPath)
  36. this.callback = sinon.stub()
  37. })
  38. describe('mergeUpdate', function () {
  39. describe('doc updates for a new doc', function () {
  40. beforeEach(function () {
  41. this.FileTypeManager.getType = sinon
  42. .stub()
  43. .yields(null, { binary: false, encoding: 'utf-8' })
  44. this.updateMerger.p.processDoc = sinon.stub().yields()
  45. this.updateMerger.mergeUpdate(
  46. this.user_id,
  47. this.project_id,
  48. this.docPath,
  49. this.updateRequest,
  50. this.source,
  51. this.callback
  52. )
  53. })
  54. it('should look at the file contents', function () {
  55. this.FileTypeManager.getType.called.should.equal(true)
  56. })
  57. it('should process update as doc', function () {
  58. this.updateMerger.p.processDoc
  59. .calledWith(
  60. this.project_id,
  61. this.user_id,
  62. this.fsPath,
  63. this.docPath,
  64. this.source
  65. )
  66. .should.equal(true)
  67. })
  68. it('removes the temp file from disk', function () {
  69. this.fs.unlink.calledWith(this.fsPath).should.equal(true)
  70. })
  71. })
  72. describe('file updates for a new file ', function () {
  73. beforeEach(function () {
  74. this.FileTypeManager.getType = sinon
  75. .stub()
  76. .yields(null, { binary: true })
  77. this.updateMerger.p.processFile = sinon.stub().yields()
  78. this.updateMerger.mergeUpdate(
  79. this.user_id,
  80. this.project_id,
  81. this.filePath,
  82. this.updateRequest,
  83. this.source,
  84. this.callback
  85. )
  86. })
  87. it('should look at the file contents', function () {
  88. this.FileTypeManager.getType.called.should.equal(true)
  89. })
  90. it('should process update as file', function () {
  91. this.updateMerger.p.processFile
  92. .calledWith(
  93. this.project_id,
  94. this.fsPath,
  95. this.filePath,
  96. this.source,
  97. this.user_id
  98. )
  99. .should.equal(true)
  100. })
  101. it('removes the temp file from disk', function () {
  102. this.fs.unlink.calledWith(this.fsPath).should.equal(true)
  103. })
  104. })
  105. describe('doc updates for an existing doc', function () {
  106. beforeEach(function () {
  107. this.FileTypeManager.getType = sinon
  108. .stub()
  109. .yields(null, { binary: false, encoding: 'utf-8' })
  110. this.updateMerger.p.processDoc = sinon.stub().yields()
  111. this.updateMerger.mergeUpdate(
  112. this.user_id,
  113. this.project_id,
  114. this.existingDocPath,
  115. this.updateRequest,
  116. this.source,
  117. this.callback
  118. )
  119. })
  120. it('should look at the file contents', function () {
  121. this.FileTypeManager.getType.called.should.equal(true)
  122. })
  123. it('should process update as doc', function () {
  124. this.updateMerger.p.processDoc
  125. .calledWith(
  126. this.project_id,
  127. this.user_id,
  128. this.fsPath,
  129. this.existingDocPath,
  130. this.source
  131. )
  132. .should.equal(true)
  133. })
  134. it('removes the temp file from disk', function () {
  135. this.fs.unlink.calledWith(this.fsPath).should.equal(true)
  136. })
  137. })
  138. describe('file updates for an existing file', function () {
  139. beforeEach(function () {
  140. this.FileTypeManager.getType = sinon
  141. .stub()
  142. .yields(null, { binary: true })
  143. this.updateMerger.p.processFile = sinon.stub().yields()
  144. this.updateMerger.mergeUpdate(
  145. this.user_id,
  146. this.project_id,
  147. this.existingFilePath,
  148. this.updateRequest,
  149. this.source,
  150. this.callback
  151. )
  152. })
  153. it('should look at the file contents', function () {
  154. this.FileTypeManager.getType.called.should.equal(true)
  155. })
  156. it('should process update as file', function () {
  157. this.updateMerger.p.processFile
  158. .calledWith(
  159. this.project_id,
  160. this.fsPath,
  161. this.existingFilePath,
  162. this.source,
  163. this.user_id
  164. )
  165. .should.equal(true)
  166. })
  167. it('removes the temp file from disk', function () {
  168. this.fs.unlink.calledWith(this.fsPath).should.equal(true)
  169. })
  170. })
  171. })
  172. describe('file updates for an existing doc', function () {
  173. beforeEach(function () {
  174. this.FileTypeManager.getType = sinon.stub().yields(null, { binary: true })
  175. this.updateMerger.deleteUpdate = sinon.stub().yields()
  176. this.updateMerger.p.processFile = sinon.stub().yields()
  177. this.updateMerger.mergeUpdate(
  178. this.user_id,
  179. this.project_id,
  180. this.existingDocPath,
  181. this.updateRequest,
  182. this.source,
  183. this.callback
  184. )
  185. })
  186. it('should look at the file contents', function () {
  187. this.FileTypeManager.getType.called.should.equal(true)
  188. })
  189. it('should delete the existing doc', function () {
  190. this.updateMerger.deleteUpdate
  191. .calledWith(
  192. this.user_id,
  193. this.project_id,
  194. this.existingDocPath,
  195. this.source
  196. )
  197. .should.equal(true)
  198. })
  199. it('should process update as file', function () {
  200. this.updateMerger.p.processFile
  201. .calledWith(
  202. this.project_id,
  203. this.fsPath,
  204. this.existingDocPath,
  205. this.source,
  206. this.user_id
  207. )
  208. .should.equal(true)
  209. })
  210. it('removes the temp file from disk', function () {
  211. this.fs.unlink.calledWith(this.fsPath).should.equal(true)
  212. })
  213. })
  214. describe('doc updates for an existing file', function () {
  215. beforeEach(function () {
  216. this.FileTypeManager.getType = sinon.stub().yields(null, { binary: true })
  217. this.updateMerger.deleteUpdate = sinon.stub().yields()
  218. this.updateMerger.p.processFile = sinon.stub().yields()
  219. this.updateMerger.mergeUpdate(
  220. this.user_id,
  221. this.project_id,
  222. this.existingFilePath,
  223. this.updateRequest,
  224. this.source,
  225. this.callback
  226. )
  227. })
  228. it('should look at the file contents', function () {
  229. this.FileTypeManager.getType.called.should.equal(true)
  230. })
  231. it('should not delete the existing file', function () {
  232. this.updateMerger.deleteUpdate.called.should.equal(false)
  233. })
  234. it('should process update as file', function () {
  235. this.updateMerger.p.processFile
  236. .calledWith(
  237. this.project_id,
  238. this.fsPath,
  239. this.existingFilePath,
  240. this.source,
  241. this.user_id
  242. )
  243. .should.equal(true)
  244. })
  245. it('removes the temp file from disk', function () {
  246. this.fs.unlink.calledWith(this.fsPath).should.equal(true)
  247. })
  248. })
  249. describe('deleteUpdate', function () {
  250. beforeEach(function () {
  251. this.EditorController.deleteEntityWithPath = sinon.stub().yields()
  252. this.updateMerger.deleteUpdate(
  253. this.user_id,
  254. this.project_id,
  255. this.docPath,
  256. this.source,
  257. this.callback
  258. )
  259. })
  260. it('should delete the entity in the editor controller', function () {
  261. this.EditorController.deleteEntityWithPath
  262. .calledWith(this.project_id, this.docPath, this.source, this.user_id)
  263. .should.equal(true)
  264. })
  265. })
  266. describe('private methods', function () {
  267. describe('processDoc', function () {
  268. beforeEach(function () {
  269. this.docLines =
  270. '\\documentclass{article}\n\\usepackage[utf8]{inputenc}\n\n\\title{42}\n\\author{Jane Doe}\n\\date{June 2011}'
  271. this.updateMerger.p.readFileIntoTextArray = sinon
  272. .stub()
  273. .yields(null, this.docLines)
  274. this.EditorController.upsertDocWithPath = sinon.stub().yields()
  275. this.updateMerger.p.processDoc(
  276. this.project_id,
  277. this.user_id,
  278. this.fsPath,
  279. this.docPath,
  280. this.source,
  281. this.callback
  282. )
  283. })
  284. it('reads the temp file from disk', function () {
  285. this.updateMerger.p.readFileIntoTextArray
  286. .calledWith(this.fsPath)
  287. .should.equal(true)
  288. })
  289. it('should upsert the doc in the editor controller', function () {
  290. this.EditorController.upsertDocWithPath
  291. .calledWith(
  292. this.project_id,
  293. this.docPath,
  294. this.docLines,
  295. this.source,
  296. this.user_id
  297. )
  298. .should.equal(true)
  299. })
  300. })
  301. describe('processFile', function () {
  302. beforeEach(function () {
  303. this.EditorController.upsertFileWithPath = sinon.stub().yields()
  304. this.updateMerger.p.processFile(
  305. this.project_id,
  306. this.fsPath,
  307. this.filePath,
  308. this.source,
  309. this.user_id,
  310. this.callback
  311. )
  312. })
  313. it('should upsert the file in the editor controller', function () {
  314. this.EditorController.upsertFileWithPath
  315. .calledWith(
  316. this.project_id,
  317. this.filePath,
  318. this.fsPath,
  319. null,
  320. this.source,
  321. this.user_id
  322. )
  323. .should.equal(true)
  324. })
  325. })
  326. })
  327. })