auto-select-file.test.ts 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  1. import { expect } from 'chai'
  2. import type { FileDiff } from '../../../../../frontend/js/features/history/services/types/file'
  3. import { autoSelectFile } from '../../../../../frontend/js/features/history/utils/auto-select-file'
  4. import type { User } from '../../../../../frontend/js/features/history/services/types/shared'
  5. import { LoadedUpdate } from '../../../../../frontend/js/features/history/services/types/update'
  6. import { fileFinalPathname } from '../../../../../frontend/js/features/history/utils/file-diff'
  7. import { getUpdateForVersion } from '../../../../../frontend/js/features/history/utils/history-details'
  8. describe('autoSelectFile', function () {
  9. const historyUsers: User[] = [
  10. {
  11. first_name: 'first_name',
  12. last_name: 'last_name',
  13. email: 'email@overleaf.com',
  14. id: '6266xb6b7a366460a66186xx',
  15. },
  16. ]
  17. describe('for comparing version with previous', function () {
  18. const comparing = false
  19. it('return the file with `edited` as the last operation', function () {
  20. const files: FileDiff[] = [
  21. {
  22. pathname: 'main.tex',
  23. editable: true,
  24. },
  25. {
  26. pathname: 'sample.bib',
  27. editable: true,
  28. },
  29. {
  30. pathname: 'frog.jpg',
  31. editable: false,
  32. },
  33. {
  34. pathname: 'newfile5.tex',
  35. editable: true,
  36. },
  37. {
  38. pathname: 'newfolder1/newfolder2/newfile2.tex',
  39. editable: true,
  40. },
  41. {
  42. pathname: 'newfolder1/newfile10.tex',
  43. operation: 'edited',
  44. },
  45. ]
  46. const updates: LoadedUpdate[] = [
  47. {
  48. fromV: 25,
  49. toV: 26,
  50. meta: {
  51. users: historyUsers,
  52. start_ts: 1680888731881,
  53. end_ts: 1680888731881,
  54. },
  55. labels: [],
  56. pathnames: ['newfolder1/newfile10.tex'],
  57. project_ops: [],
  58. },
  59. {
  60. fromV: 23,
  61. toV: 25,
  62. meta: {
  63. users: historyUsers,
  64. start_ts: 1680888725098,
  65. end_ts: 1680888729123,
  66. },
  67. labels: [],
  68. pathnames: [],
  69. project_ops: [
  70. {
  71. rename: {
  72. pathname: 'newfolder1/newfile3.tex',
  73. newPathname: 'newfolder1/newfile10.tex',
  74. },
  75. atV: 24,
  76. },
  77. {
  78. rename: {
  79. pathname: 'newfile3.tex',
  80. newPathname: 'newfolder1/newfile3.tex',
  81. },
  82. atV: 23,
  83. },
  84. ],
  85. },
  86. {
  87. fromV: 22,
  88. toV: 23,
  89. meta: {
  90. users: historyUsers,
  91. start_ts: 1680888721015,
  92. end_ts: 1680888721015,
  93. },
  94. labels: [],
  95. pathnames: ['newfile3.tex'],
  96. project_ops: [],
  97. },
  98. {
  99. fromV: 19,
  100. toV: 22,
  101. meta: {
  102. users: historyUsers,
  103. start_ts: 1680888715364,
  104. end_ts: 1680888718726,
  105. },
  106. labels: [],
  107. pathnames: [],
  108. project_ops: [
  109. {
  110. rename: {
  111. pathname: 'newfolder1/newfolder2/newfile3.tex',
  112. newPathname: 'newfile3.tex',
  113. },
  114. atV: 21,
  115. },
  116. {
  117. rename: {
  118. pathname: 'newfolder1/newfile2.tex',
  119. newPathname: 'newfolder1/newfolder2/newfile2.tex',
  120. },
  121. atV: 20,
  122. },
  123. {
  124. rename: {
  125. pathname: 'newfolder1/newfile5.tex',
  126. newPathname: 'newfile5.tex',
  127. },
  128. atV: 19,
  129. },
  130. ],
  131. },
  132. {
  133. fromV: 16,
  134. toV: 19,
  135. meta: {
  136. users: historyUsers,
  137. start_ts: 1680888705042,
  138. end_ts: 1680888712662,
  139. },
  140. labels: [],
  141. pathnames: [
  142. 'main.tex',
  143. 'newfolder1/newfile2.tex',
  144. 'newfolder1/newfile5.tex',
  145. ],
  146. project_ops: [],
  147. },
  148. {
  149. fromV: 0,
  150. toV: 16,
  151. meta: {
  152. users: historyUsers,
  153. start_ts: 1680888456499,
  154. end_ts: 1680888640774,
  155. },
  156. labels: [],
  157. pathnames: [],
  158. project_ops: [
  159. {
  160. add: {
  161. pathname: 'newfolder1/newfile2.tex',
  162. },
  163. atV: 15,
  164. },
  165. {
  166. remove: {
  167. pathname: 'newfile2.tex',
  168. },
  169. atV: 14,
  170. },
  171. {
  172. rename: {
  173. pathname: 'newfolder1/frog.jpg',
  174. newPathname: 'frog.jpg',
  175. },
  176. atV: 13,
  177. },
  178. {
  179. rename: {
  180. pathname: 'newfolder1/newfile2.tex',
  181. newPathname: 'newfile2.tex',
  182. },
  183. atV: 12,
  184. },
  185. {
  186. rename: {
  187. pathname: 'newfile5.tex',
  188. newPathname: 'newfolder1/newfile5.tex',
  189. },
  190. atV: 11,
  191. },
  192. {
  193. rename: {
  194. pathname: 'newfile4.tex',
  195. newPathname: 'newfile5.tex',
  196. },
  197. atV: 10,
  198. },
  199. {
  200. add: {
  201. pathname: 'newfile4.tex',
  202. },
  203. atV: 9,
  204. },
  205. {
  206. remove: {
  207. pathname: 'newfolder1/newfolder2/newfile1.tex',
  208. },
  209. atV: 8,
  210. },
  211. {
  212. rename: {
  213. pathname: 'frog.jpg',
  214. newPathname: 'newfolder1/frog.jpg',
  215. },
  216. atV: 7,
  217. },
  218. {
  219. add: {
  220. pathname: 'newfolder1/newfolder2/newfile3.tex',
  221. },
  222. atV: 6,
  223. },
  224. {
  225. add: {
  226. pathname: 'newfolder1/newfile2.tex',
  227. },
  228. atV: 5,
  229. },
  230. {
  231. rename: {
  232. pathname: 'newfolder1/newfile1.tex',
  233. newPathname: 'newfolder1/newfolder2/newfile1.tex',
  234. },
  235. atV: 4,
  236. },
  237. {
  238. add: {
  239. pathname: 'newfolder1/newfile1.tex',
  240. },
  241. atV: 3,
  242. },
  243. {
  244. add: {
  245. pathname: 'frog.jpg',
  246. },
  247. atV: 2,
  248. },
  249. {
  250. add: {
  251. pathname: 'sample.bib',
  252. },
  253. atV: 1,
  254. },
  255. {
  256. add: {
  257. pathname: 'main.tex',
  258. },
  259. atV: 0,
  260. },
  261. ],
  262. },
  263. ]
  264. const { pathname } = autoSelectFile(
  265. files,
  266. updates[0].toV,
  267. comparing,
  268. getUpdateForVersion(updates[0].toV, updates),
  269. null
  270. )
  271. expect(pathname).to.equal('newfolder1/newfile10.tex')
  272. })
  273. it('return file with `added` operation on highest `atV` value if no other operation is available on the latest `updates` entry', function () {
  274. const files: FileDiff[] = [
  275. {
  276. pathname: 'main.tex',
  277. operation: 'added',
  278. editable: true,
  279. },
  280. {
  281. pathname: 'sample.bib',
  282. operation: 'added',
  283. editable: true,
  284. },
  285. {
  286. pathname: 'frog.jpg',
  287. operation: 'added',
  288. editable: false,
  289. },
  290. {
  291. pathname: 'newfile1.tex',
  292. operation: 'added',
  293. editable: true,
  294. },
  295. ]
  296. const updates: LoadedUpdate[] = [
  297. {
  298. fromV: 0,
  299. toV: 4,
  300. meta: {
  301. users: historyUsers,
  302. start_ts: 1680861468999,
  303. end_ts: 1680861491861,
  304. },
  305. labels: [],
  306. pathnames: [],
  307. project_ops: [
  308. {
  309. add: {
  310. pathname: 'newfile1.tex',
  311. },
  312. atV: 3,
  313. },
  314. {
  315. add: {
  316. pathname: 'frog.jpg',
  317. },
  318. atV: 2,
  319. },
  320. {
  321. add: {
  322. pathname: 'sample.bib',
  323. },
  324. atV: 1,
  325. },
  326. {
  327. add: {
  328. pathname: 'main.tex',
  329. },
  330. atV: 0,
  331. },
  332. ],
  333. },
  334. ]
  335. const { pathname } = autoSelectFile(
  336. files,
  337. updates[0].toV,
  338. comparing,
  339. getUpdateForVersion(updates[0].toV, updates),
  340. null
  341. )
  342. expect(pathname).to.equal('newfile1.tex')
  343. })
  344. it('return the last non-`removed` operation with the highest `atV` value', function () {
  345. const files: FileDiff[] = [
  346. {
  347. pathname: 'main.tex',
  348. operation: 'removed',
  349. deletedAtV: 6,
  350. editable: true,
  351. },
  352. {
  353. pathname: 'sample.bib',
  354. editable: true,
  355. },
  356. {
  357. pathname: 'main2.tex',
  358. operation: 'added',
  359. editable: true,
  360. },
  361. {
  362. pathname: 'main3.tex',
  363. operation: 'added',
  364. editable: true,
  365. },
  366. ]
  367. const updates: LoadedUpdate[] = [
  368. {
  369. fromV: 4,
  370. toV: 7,
  371. meta: {
  372. users: historyUsers,
  373. start_ts: 1680874742389,
  374. end_ts: 1680874755552,
  375. },
  376. labels: [],
  377. pathnames: [],
  378. project_ops: [
  379. {
  380. remove: {
  381. pathname: 'main.tex',
  382. },
  383. atV: 6,
  384. },
  385. {
  386. add: {
  387. pathname: 'main3.tex',
  388. },
  389. atV: 5,
  390. },
  391. {
  392. add: {
  393. pathname: 'main2.tex',
  394. },
  395. atV: 4,
  396. },
  397. ],
  398. },
  399. {
  400. fromV: 0,
  401. toV: 4,
  402. meta: {
  403. users: historyUsers,
  404. start_ts: 1680861975947,
  405. end_ts: 1680861988442,
  406. },
  407. labels: [],
  408. pathnames: [],
  409. project_ops: [
  410. {
  411. remove: {
  412. pathname: 'frog.jpg',
  413. },
  414. atV: 3,
  415. },
  416. {
  417. add: {
  418. pathname: 'frog.jpg',
  419. },
  420. atV: 2,
  421. },
  422. {
  423. add: {
  424. pathname: 'sample.bib',
  425. },
  426. atV: 1,
  427. },
  428. {
  429. add: {
  430. pathname: 'main.tex',
  431. },
  432. atV: 0,
  433. },
  434. ],
  435. },
  436. ]
  437. const { pathname } = autoSelectFile(
  438. files,
  439. updates[0].toV,
  440. comparing,
  441. getUpdateForVersion(updates[0].toV, updates),
  442. null
  443. )
  444. expect(pathname).to.equal('main3.tex')
  445. })
  446. it('if `removed` is the last operation, and no other operation is available on the latest `updates` entry, with `main.tex` available as a file name somewhere in the file tree, return `main.tex`', function () {
  447. const files: FileDiff[] = [
  448. {
  449. pathname: 'main.tex',
  450. editable: true,
  451. },
  452. {
  453. pathname: 'sample.bib',
  454. editable: true,
  455. },
  456. {
  457. pathname: 'frog.jpg',
  458. editable: false,
  459. },
  460. {
  461. pathname: 'newfolder/maybewillbedeleted.tex',
  462. newPathname: 'newfolder2/maybewillbedeleted.tex',
  463. operation: 'removed',
  464. deletedAtV: 10,
  465. editable: true,
  466. },
  467. ]
  468. const updates: LoadedUpdate[] = [
  469. {
  470. fromV: 9,
  471. toV: 11,
  472. meta: {
  473. users: historyUsers,
  474. start_ts: 1680904414419,
  475. end_ts: 1680904417538,
  476. },
  477. labels: [],
  478. pathnames: [],
  479. project_ops: [
  480. {
  481. remove: {
  482. pathname: 'newfolder2/maybewillbedeleted.tex',
  483. },
  484. atV: 10,
  485. },
  486. {
  487. rename: {
  488. pathname: 'newfolder/maybewillbedeleted.tex',
  489. newPathname: 'newfolder2/maybewillbedeleted.tex',
  490. },
  491. atV: 9,
  492. },
  493. ],
  494. },
  495. {
  496. fromV: 8,
  497. toV: 9,
  498. meta: {
  499. users: historyUsers,
  500. start_ts: 1680904410333,
  501. end_ts: 1680904410333,
  502. },
  503. labels: [],
  504. pathnames: ['newfolder/maybewillbedeleted.tex'],
  505. project_ops: [],
  506. },
  507. {
  508. fromV: 7,
  509. toV: 8,
  510. meta: {
  511. users: historyUsers,
  512. start_ts: 1680904407448,
  513. end_ts: 1680904407448,
  514. },
  515. labels: [],
  516. pathnames: [],
  517. project_ops: [
  518. {
  519. rename: {
  520. pathname: 'newfolder/tobedeleted.tex',
  521. newPathname: 'newfolder/maybewillbedeleted.tex',
  522. },
  523. atV: 7,
  524. },
  525. ],
  526. },
  527. {
  528. fromV: 6,
  529. toV: 7,
  530. meta: {
  531. users: historyUsers,
  532. start_ts: 1680904400839,
  533. end_ts: 1680904400839,
  534. },
  535. labels: [],
  536. pathnames: ['newfolder/tobedeleted.tex'],
  537. project_ops: [],
  538. },
  539. {
  540. fromV: 5,
  541. toV: 6,
  542. meta: {
  543. users: historyUsers,
  544. start_ts: 1680904398544,
  545. end_ts: 1680904398544,
  546. },
  547. labels: [],
  548. pathnames: [],
  549. project_ops: [
  550. {
  551. rename: {
  552. pathname: 'tobedeleted.tex',
  553. newPathname: 'newfolder/tobedeleted.tex',
  554. },
  555. atV: 5,
  556. },
  557. ],
  558. },
  559. {
  560. fromV: 4,
  561. toV: 5,
  562. meta: {
  563. users: historyUsers,
  564. start_ts: 1680904389891,
  565. end_ts: 1680904389891,
  566. },
  567. labels: [],
  568. pathnames: ['tobedeleted.tex'],
  569. project_ops: [],
  570. },
  571. {
  572. fromV: 0,
  573. toV: 4,
  574. meta: {
  575. users: historyUsers,
  576. start_ts: 1680904363778,
  577. end_ts: 1680904385308,
  578. },
  579. labels: [],
  580. pathnames: [],
  581. project_ops: [
  582. {
  583. add: {
  584. pathname: 'tobedeleted.tex',
  585. },
  586. atV: 3,
  587. },
  588. {
  589. add: {
  590. pathname: 'frog.jpg',
  591. },
  592. atV: 2,
  593. },
  594. {
  595. add: {
  596. pathname: 'sample.bib',
  597. },
  598. atV: 1,
  599. },
  600. {
  601. add: {
  602. pathname: 'main.tex',
  603. },
  604. atV: 0,
  605. },
  606. ],
  607. },
  608. ]
  609. const { pathname } = autoSelectFile(
  610. files,
  611. updates[0].toV,
  612. comparing,
  613. getUpdateForVersion(updates[0].toV, updates),
  614. null
  615. )
  616. expect(pathname).to.equal('main.tex')
  617. })
  618. it('if `removed` is the last operation, and no other operation is available on the latest `updates` entry, with `main.tex` is not available as a file name somewhere in the file tree, return any tex file based on ascending alphabetical order', function () {
  619. const files: FileDiff[] = [
  620. {
  621. pathname: 'certainly_not_main.tex',
  622. editable: true,
  623. },
  624. {
  625. pathname: 'newfile.tex',
  626. editable: true,
  627. },
  628. {
  629. pathname: 'file2.tex',
  630. editable: true,
  631. },
  632. ]
  633. const updates: LoadedUpdate[] = [
  634. {
  635. fromV: 7,
  636. toV: 8,
  637. meta: {
  638. users: historyUsers,
  639. start_ts: 1680905536168,
  640. end_ts: 1680905536168,
  641. },
  642. labels: [],
  643. pathnames: [],
  644. project_ops: [
  645. {
  646. remove: {
  647. pathname: 'newfolder/tobedeleted.txt',
  648. },
  649. atV: 7,
  650. },
  651. ],
  652. },
  653. {
  654. fromV: 6,
  655. toV: 7,
  656. meta: {
  657. users: historyUsers,
  658. start_ts: 1680905531816,
  659. end_ts: 1680905531816,
  660. },
  661. labels: [],
  662. pathnames: ['newfolder/tobedeleted.txt'],
  663. project_ops: [],
  664. },
  665. {
  666. fromV: 0,
  667. toV: 6,
  668. meta: {
  669. users: historyUsers,
  670. start_ts: 1680905492130,
  671. end_ts: 1680905529186,
  672. },
  673. labels: [],
  674. pathnames: [],
  675. project_ops: [
  676. {
  677. rename: {
  678. pathname: 'tobedeleted.txt',
  679. newPathname: 'newfolder/tobedeleted.txt',
  680. },
  681. atV: 5,
  682. },
  683. {
  684. add: {
  685. pathname: 'file2.tex',
  686. },
  687. atV: 4,
  688. },
  689. {
  690. add: {
  691. pathname: 'newfile.tex',
  692. },
  693. atV: 3,
  694. },
  695. {
  696. add: {
  697. pathname: 'tobedeleted.txt',
  698. },
  699. atV: 2,
  700. },
  701. {
  702. rename: {
  703. pathname: 'main.tex',
  704. newPathname: 'certainly_not_main.tex',
  705. },
  706. atV: 1,
  707. },
  708. {
  709. add: {
  710. pathname: 'main.tex',
  711. },
  712. atV: 0,
  713. },
  714. ],
  715. },
  716. ]
  717. const { pathname } = autoSelectFile(
  718. files,
  719. updates[0].toV,
  720. comparing,
  721. getUpdateForVersion(updates[0].toV, updates),
  722. null
  723. )
  724. expect(pathname).to.equal('certainly_not_main.tex')
  725. })
  726. it('selects renamed file', function () {
  727. const files: FileDiff[] = [
  728. {
  729. pathname: 'main.tex',
  730. editable: true,
  731. },
  732. {
  733. pathname: 'original.bib',
  734. newPathname: 'new.bib',
  735. operation: 'renamed',
  736. editable: true,
  737. },
  738. ]
  739. const updates: LoadedUpdate[] = [
  740. {
  741. fromV: 4,
  742. toV: 7,
  743. meta: {
  744. users: historyUsers,
  745. start_ts: 1680874742389,
  746. end_ts: 1680874755552,
  747. },
  748. labels: [],
  749. pathnames: [],
  750. project_ops: [
  751. {
  752. rename: {
  753. pathname: 'original.bib',
  754. newPathname: 'new.bib',
  755. },
  756. atV: 5,
  757. },
  758. ],
  759. },
  760. {
  761. fromV: 0,
  762. toV: 4,
  763. meta: {
  764. users: historyUsers,
  765. start_ts: 1680861975947,
  766. end_ts: 1680861988442,
  767. },
  768. labels: [],
  769. pathnames: [],
  770. project_ops: [
  771. {
  772. add: {
  773. pathname: 'original.bib',
  774. },
  775. atV: 1,
  776. },
  777. {
  778. add: {
  779. pathname: 'main.tex',
  780. },
  781. atV: 0,
  782. },
  783. ],
  784. },
  785. ]
  786. const pathname = fileFinalPathname(
  787. autoSelectFile(
  788. files,
  789. updates[0].toV,
  790. comparing,
  791. getUpdateForVersion(updates[0].toV, updates),
  792. null
  793. )
  794. )
  795. expect(pathname).to.equal('new.bib')
  796. })
  797. it('ignores binary file', function () {
  798. const files: FileDiff[] = [
  799. {
  800. pathname: 'frog.jpg',
  801. editable: false,
  802. operation: 'added',
  803. },
  804. {
  805. pathname: 'main.tex',
  806. editable: true,
  807. },
  808. {
  809. pathname: 'sample.bib',
  810. editable: true,
  811. },
  812. ]
  813. const updates: LoadedUpdate[] = [
  814. {
  815. fromV: 4,
  816. toV: 7,
  817. meta: {
  818. users: historyUsers,
  819. start_ts: 1680874742389,
  820. end_ts: 1680874755552,
  821. },
  822. labels: [],
  823. pathnames: [],
  824. project_ops: [
  825. {
  826. add: {
  827. pathname: 'frog.jpg',
  828. },
  829. atV: 5,
  830. },
  831. ],
  832. },
  833. {
  834. fromV: 0,
  835. toV: 4,
  836. meta: {
  837. users: historyUsers,
  838. start_ts: 1680861975947,
  839. end_ts: 1680861988442,
  840. },
  841. labels: [],
  842. pathnames: [],
  843. project_ops: [
  844. {
  845. add: {
  846. pathname: 'sample.bib',
  847. },
  848. atV: 1,
  849. },
  850. {
  851. add: {
  852. pathname: 'main.tex',
  853. },
  854. atV: 0,
  855. },
  856. ],
  857. },
  858. ]
  859. const { pathname } = autoSelectFile(
  860. files,
  861. updates[0].toV,
  862. comparing,
  863. getUpdateForVersion(updates[0].toV, updates),
  864. null
  865. )
  866. expect(pathname).to.equal('main.tex')
  867. })
  868. })
  869. })