FileSystemImportManagerTests.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. /* eslint-disable
  2. max-len,
  3. no-return-assign,
  4. no-unused-vars,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS101: Remove unnecessary use of Array.from
  11. * DS102: Remove unnecessary code created because of implicit returns
  12. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  13. */
  14. const sinon = require('sinon')
  15. const chai = require('chai')
  16. const should = chai.should()
  17. const modulePath =
  18. '../../../../app/src/Features/Uploads/FileSystemImportManager.js'
  19. const SandboxedModule = require('sandboxed-module')
  20. describe('FileSystemImportManager', function() {
  21. beforeEach(function() {
  22. this.project_id = 'project-id-123'
  23. this.folder_id = 'folder-id-123'
  24. this.name = 'test-file.tex'
  25. this.path_on_disk = `/path/to/file/${this.name}`
  26. this.replace = 'replace-boolean-flag-mock'
  27. this.user_id = 'mock-user-123'
  28. this.callback = sinon.stub()
  29. this.encoding = 'latin1'
  30. this.DocumentHelper = {
  31. convertTexEncodingsToUtf8: sinon.stub().returnsArg(0)
  32. }
  33. return (this.FileSystemImportManager = SandboxedModule.require(modulePath, {
  34. requires: {
  35. fs: (this.fs = {}),
  36. '../Editor/EditorController': (this.EditorController = {}),
  37. './FileTypeManager': (this.FileTypeManager = {}),
  38. '../Project/ProjectLocator': (this.ProjectLocator = {}),
  39. '../Documents/DocumentHelper': this.DocumentHelper,
  40. 'logger-sharelatex': {
  41. log() {},
  42. err() {}
  43. }
  44. }
  45. }))
  46. })
  47. describe('addDoc', function() {
  48. beforeEach(function() {
  49. this.docContent = 'one\ntwo\nthree'
  50. this.docLines = this.docContent.split('\n')
  51. this.fs.readFile = sinon.stub().callsArgWith(2, null, this.docContent)
  52. return (this.FileSystemImportManager._isSafeOnFileSystem = sinon
  53. .stub()
  54. .callsArgWith(1, null, true))
  55. })
  56. describe('when path is symlink', function() {
  57. beforeEach(function() {
  58. this.FileSystemImportManager._isSafeOnFileSystem = sinon
  59. .stub()
  60. .callsArgWith(1, null, false)
  61. this.EditorController.addDoc = sinon.stub()
  62. return this.FileSystemImportManager.addDoc(
  63. this.user_id,
  64. this.project_id,
  65. this.folder_id,
  66. this.name,
  67. this.path_on_disk,
  68. this.encoding,
  69. false,
  70. this.callback
  71. )
  72. })
  73. it('should not read the file from disk', function() {
  74. return this.fs.readFile.called.should.equal(false)
  75. })
  76. return it('should not insert the doc', function() {
  77. return this.EditorController.addDoc.called.should.equal(false)
  78. })
  79. })
  80. describe('with replace set to false', function() {
  81. beforeEach(function() {
  82. this.EditorController.addDoc = sinon.stub().callsArg(6)
  83. return this.FileSystemImportManager.addDoc(
  84. this.user_id,
  85. this.project_id,
  86. this.folder_id,
  87. this.name,
  88. this.path_on_disk,
  89. this.encoding,
  90. false,
  91. this.callback
  92. )
  93. })
  94. it('should read the file from disk', function() {
  95. return this.fs.readFile.calledWith(this.path_on_disk).should.equal(true)
  96. })
  97. return it('should insert the doc', function() {
  98. return this.EditorController.addDoc
  99. .calledWith(
  100. this.project_id,
  101. this.folder_id,
  102. this.name,
  103. this.docLines,
  104. 'upload',
  105. this.user_id
  106. )
  107. .should.equal(true)
  108. })
  109. })
  110. describe('with windows line ending', function() {
  111. beforeEach(function() {
  112. this.docContent = 'one\r\ntwo\r\nthree'
  113. this.docLines = ['one', 'two', 'three']
  114. this.fs.readFile = sinon.stub().callsArgWith(2, null, this.docContent)
  115. this.EditorController.addDoc = sinon.stub().callsArg(6)
  116. return this.FileSystemImportManager.addDoc(
  117. this.user_id,
  118. this.project_id,
  119. this.folder_id,
  120. this.name,
  121. this.path_on_disk,
  122. this.encoding,
  123. false,
  124. this.callback
  125. )
  126. })
  127. return it('should strip the \\r characters before adding', function() {
  128. return this.EditorController.addDoc
  129. .calledWith(
  130. this.project_id,
  131. this.folder_id,
  132. this.name,
  133. this.docLines,
  134. 'upload',
  135. this.user_id
  136. )
  137. .should.equal(true)
  138. })
  139. })
  140. describe('with \r line endings', function() {
  141. beforeEach(function() {
  142. this.docContent = 'one\rtwo\rthree'
  143. this.docLines = ['one', 'two', 'three']
  144. this.fs.readFile = sinon.stub().callsArgWith(2, null, this.docContent)
  145. this.EditorController.addDoc = sinon.stub().callsArg(6)
  146. return this.FileSystemImportManager.addDoc(
  147. this.user_id,
  148. this.project_id,
  149. this.folder_id,
  150. this.name,
  151. this.path_on_disk,
  152. this.encoding,
  153. false,
  154. this.callback
  155. )
  156. })
  157. return it('should treat the \\r characters as newlines', function() {
  158. return this.EditorController.addDoc
  159. .calledWith(
  160. this.project_id,
  161. this.folder_id,
  162. this.name,
  163. this.docLines,
  164. 'upload',
  165. this.user_id
  166. )
  167. .should.equal(true)
  168. })
  169. })
  170. return describe('with replace set to true', function() {
  171. beforeEach(function() {
  172. this.EditorController.upsertDoc = sinon.stub().yields()
  173. return this.FileSystemImportManager.addDoc(
  174. this.user_id,
  175. this.project_id,
  176. this.folder_id,
  177. this.name,
  178. this.path_on_disk,
  179. this.encoding,
  180. true,
  181. this.callback
  182. )
  183. })
  184. it('should upsert the doc', function() {
  185. return this.EditorController.upsertDoc
  186. .calledWith(
  187. this.project_id,
  188. this.folder_id,
  189. this.name,
  190. this.docLines,
  191. 'upload',
  192. this.user_id
  193. )
  194. .should.equal(true)
  195. })
  196. return it('should read the file with the correct encoding', function() {
  197. return sinon.assert.calledWith(
  198. this.fs.readFile,
  199. this.path_on_disk,
  200. this.encoding
  201. )
  202. })
  203. })
  204. })
  205. describe('addFile with replace set to false', function() {
  206. beforeEach(function() {
  207. this.EditorController.addFile = sinon.stub().yields()
  208. this.FileSystemImportManager._isSafeOnFileSystem = sinon
  209. .stub()
  210. .callsArgWith(1, null, true)
  211. return this.FileSystemImportManager.addFile(
  212. this.user_id,
  213. this.project_id,
  214. this.folder_id,
  215. this.name,
  216. this.path_on_disk,
  217. false,
  218. this.callback
  219. )
  220. })
  221. return it('should add the file', function() {
  222. return this.EditorController.addFile
  223. .calledWith(
  224. this.project_id,
  225. this.folder_id,
  226. this.name,
  227. this.path_on_disk,
  228. null,
  229. 'upload',
  230. this.user_id
  231. )
  232. .should.equal(true)
  233. })
  234. })
  235. describe('addFile with symlink', function() {
  236. beforeEach(function() {
  237. this.EditorController.addFile = sinon.stub()
  238. this.FileSystemImportManager._isSafeOnFileSystem = sinon
  239. .stub()
  240. .callsArgWith(1, null, false)
  241. this.EditorController.replaceFile = sinon.stub()
  242. return this.FileSystemImportManager.addFile(
  243. this.user_id,
  244. this.project_id,
  245. this.folder_id,
  246. this.name,
  247. this.path_on_disk,
  248. false,
  249. this.callback
  250. )
  251. })
  252. return it('should node add the file', function() {
  253. this.EditorController.addFile.called.should.equal(false)
  254. return this.EditorController.replaceFile.called.should.equal(false)
  255. })
  256. })
  257. describe('addFile with replace set to true', function() {
  258. beforeEach(function() {
  259. this.FileSystemImportManager._isSafeOnFileSystem = sinon
  260. .stub()
  261. .callsArgWith(1, null, true)
  262. this.EditorController.upsertFile = sinon.stub().yields()
  263. return this.FileSystemImportManager.addFile(
  264. this.user_id,
  265. this.project_id,
  266. this.folder_id,
  267. this.name,
  268. this.path_on_disk,
  269. true,
  270. this.callback
  271. )
  272. })
  273. return it('should add the file', function() {
  274. return this.EditorController.upsertFile
  275. .calledWith(
  276. this.project_id,
  277. this.folder_id,
  278. this.name,
  279. this.path_on_disk,
  280. null,
  281. 'upload',
  282. this.user_id
  283. )
  284. .should.equal(true)
  285. })
  286. })
  287. describe('addFolder', function() {
  288. beforeEach(function() {
  289. this.new_folder_id = 'new-folder-id'
  290. this.EditorController.addFolder = sinon
  291. .stub()
  292. .callsArgWith(4, null, { _id: this.new_folder_id })
  293. return (this.FileSystemImportManager.addFolderContents = sinon
  294. .stub()
  295. .callsArg(5))
  296. })
  297. describe('successfully', function() {
  298. beforeEach(function() {
  299. this.FileSystemImportManager._isSafeOnFileSystem = sinon
  300. .stub()
  301. .callsArgWith(1, null, true)
  302. return this.FileSystemImportManager.addFolder(
  303. this.user_id,
  304. this.project_id,
  305. this.folder_id,
  306. this.name,
  307. this.path_on_disk,
  308. this.replace,
  309. this.callback
  310. )
  311. })
  312. it('should add a folder to the project', function() {
  313. return this.EditorController.addFolder
  314. .calledWith(this.project_id, this.folder_id, this.name, 'upload')
  315. .should.equal(true)
  316. })
  317. return it('should add the folders contents', function() {
  318. return this.FileSystemImportManager.addFolderContents
  319. .calledWith(
  320. this.user_id,
  321. this.project_id,
  322. this.new_folder_id,
  323. this.path_on_disk,
  324. this.replace
  325. )
  326. .should.equal(true)
  327. })
  328. })
  329. return describe('with symlink', function() {
  330. beforeEach(function() {
  331. this.FileSystemImportManager._isSafeOnFileSystem = sinon
  332. .stub()
  333. .callsArgWith(1, null, false)
  334. return this.FileSystemImportManager.addFolder(
  335. this.user_id,
  336. this.project_id,
  337. this.folder_id,
  338. this.name,
  339. this.path_on_disk,
  340. this.replace,
  341. this.callback
  342. )
  343. })
  344. return it('should not add a folder to the project', function() {
  345. this.EditorController.addFolder.called.should.equal(false)
  346. return this.FileSystemImportManager.addFolderContents.called.should.equal(
  347. false
  348. )
  349. })
  350. })
  351. })
  352. describe('addFolderContents', function() {
  353. beforeEach(function() {
  354. this.folderEntries = ['path1', 'path2', 'path3']
  355. this.ignoredEntries = ['.DS_Store']
  356. this.fs.readdir = sinon
  357. .stub()
  358. .callsArgWith(1, null, this.folderEntries.concat(this.ignoredEntries))
  359. this.FileSystemImportManager.addEntity = sinon.stub().callsArg(6)
  360. this.FileTypeManager.shouldIgnore = (path, callback) => {
  361. return callback(
  362. null,
  363. this.ignoredEntries.indexOf(require('path').basename(path)) !== -1
  364. )
  365. }
  366. this.FileSystemImportManager._isSafeOnFileSystem = sinon
  367. .stub()
  368. .callsArgWith(1, null, true)
  369. return this.FileSystemImportManager.addFolderContents(
  370. this.user_id,
  371. this.project_id,
  372. this.folder_id,
  373. this.path_on_disk,
  374. this.replace,
  375. this.callback
  376. )
  377. })
  378. it('should call addEntity for each file in the folder which is not ignored', function() {
  379. return Array.from(this.folderEntries).map(name =>
  380. this.FileSystemImportManager.addEntity
  381. .calledWith(
  382. this.user_id,
  383. this.project_id,
  384. this.folder_id,
  385. name,
  386. `${this.path_on_disk}/${name}`,
  387. this.replace
  388. )
  389. .should.equal(true)
  390. )
  391. })
  392. it('should not call addEntity for the ignored files', function() {
  393. return Array.from(this.ignoredEntries).map(name =>
  394. this.FileSystemImportManager.addEntity
  395. .calledWith(
  396. this.user_id,
  397. this.project_id,
  398. this.folder_id,
  399. name,
  400. `${this.path_on_disk}/${name}`,
  401. this.replace
  402. )
  403. .should.equal(false)
  404. )
  405. })
  406. return it('should look in the correct directory', function() {
  407. return this.fs.readdir.calledWith(this.path_on_disk).should.equal(true)
  408. })
  409. })
  410. return describe('addEntity', function() {
  411. describe('with directory', function() {
  412. beforeEach(function() {
  413. this.FileTypeManager.isDirectory = sinon
  414. .stub()
  415. .callsArgWith(1, null, true)
  416. this.FileSystemImportManager.addFolder = sinon.stub().callsArg(6)
  417. this.FileSystemImportManager._isSafeOnFileSystem = sinon
  418. .stub()
  419. .callsArgWith(1, null, true)
  420. return this.FileSystemImportManager.addEntity(
  421. this.user_id,
  422. this.project_id,
  423. this.folder_id,
  424. this.name,
  425. this.path_on_disk,
  426. this.replace,
  427. this.callback
  428. )
  429. })
  430. return it('should call addFolder', function() {
  431. return this.FileSystemImportManager.addFolder
  432. .calledWith(
  433. this.user_id,
  434. this.project_id,
  435. this.folder_id,
  436. this.name,
  437. this.path_on_disk,
  438. this.replace
  439. )
  440. .should.equal(true)
  441. })
  442. })
  443. describe('with binary file', function() {
  444. beforeEach(function() {
  445. this.FileTypeManager.isDirectory = sinon
  446. .stub()
  447. .callsArgWith(1, null, false)
  448. this.FileTypeManager.getType = sinon.stub().callsArgWith(2, null, true)
  449. this.FileSystemImportManager._isSafeOnFileSystem = sinon
  450. .stub()
  451. .callsArgWith(1, null, true)
  452. this.FileSystemImportManager.addFile = sinon.stub().callsArg(6)
  453. return this.FileSystemImportManager.addEntity(
  454. this.user_id,
  455. this.project_id,
  456. this.folder_id,
  457. this.name,
  458. this.path_on_disk,
  459. this.replace,
  460. this.callback
  461. )
  462. })
  463. return it('should call addFile', function() {
  464. return this.FileSystemImportManager.addFile
  465. .calledWith(
  466. this.user_id,
  467. this.project_id,
  468. this.folder_id,
  469. this.name,
  470. this.path_on_disk,
  471. this.replace
  472. )
  473. .should.equal(true)
  474. })
  475. })
  476. return describe('with text file', function() {
  477. beforeEach(function() {
  478. this.FileTypeManager.isDirectory = sinon
  479. .stub()
  480. .callsArgWith(1, null, false)
  481. this.FileTypeManager.getType = sinon
  482. .stub()
  483. .callsArgWith(2, null, false, 'latin1')
  484. this.FileSystemImportManager.addDoc = sinon.stub().callsArg(7)
  485. this.FileSystemImportManager._isSafeOnFileSystem = sinon
  486. .stub()
  487. .callsArgWith(1, null, true)
  488. return this.FileSystemImportManager.addEntity(
  489. this.user_id,
  490. this.project_id,
  491. this.folder_id,
  492. this.name,
  493. this.path_on_disk,
  494. this.replace,
  495. this.callback
  496. )
  497. })
  498. return it('should call addFile', function() {
  499. return sinon.assert.calledWith(
  500. this.FileSystemImportManager.addDoc,
  501. this.user_id,
  502. this.project_id,
  503. this.folder_id,
  504. this.name,
  505. this.path_on_disk,
  506. 'latin1',
  507. this.replace
  508. )
  509. })
  510. })
  511. })
  512. })