auto-select-file.test.ts 19 KB

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