auto-select-file.test.ts 18 KB

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