FileSystemImportManagerTests.js 16 KB

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