auto-select-file.test.ts 17 KB

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