overleaf/services/web/test/frontend/features/history/utils/auto-select-file.test.ts

900 lines
21 KiB
TypeScript
Raw Normal View History

import { expect } from 'chai'
import type { FileDiff } from '../../../../../frontend/js/features/history/services/types/file'
import { autoSelectFile } from '../../../../../frontend/js/features/history/utils/auto-select-file'
import type { User } from '../../../../../frontend/js/features/history/services/types/shared'
import { LoadedUpdate } from '../../../../../frontend/js/features/history/services/types/update'
import { fileFinalPathname } from '../../../../../frontend/js/features/history/utils/file-diff'
import { getUpdateForVersion } from '../../../../../frontend/js/features/history/utils/history-details'
describe('autoSelectFile', function () {
const historyUsers: User[] = [
{
first_name: 'first_name',
last_name: 'last_name',
email: 'email@overleaf.com',
id: '6266xb6b7a366460a66186xx',
},
]
describe('for comparing version with previous', function () {
const comparing = false
it('return the file with `edited` as the last operation', function () {
const files: FileDiff[] = [
{
pathname: 'main.tex',
editable: true,
},
{
pathname: 'sample.bib',
editable: true,
},
{
pathname: 'frog.jpg',
editable: false,
},
{
pathname: 'newfile5.tex',
editable: true,
},
{
pathname: 'newfolder1/newfolder2/newfile2.tex',
editable: true,
},
{
pathname: 'newfolder1/newfile10.tex',
operation: 'edited',
},
]
const updates: LoadedUpdate[] = [
{
fromV: 25,
toV: 26,
meta: {
users: historyUsers,
start_ts: 1680888731881,
end_ts: 1680888731881,
},
labels: [],
pathnames: ['newfolder1/newfile10.tex'],
project_ops: [],
},
{
fromV: 23,
toV: 25,
meta: {
users: historyUsers,
start_ts: 1680888725098,
end_ts: 1680888729123,
},
labels: [],
pathnames: [],
project_ops: [
{
rename: {
pathname: 'newfolder1/newfile3.tex',
newPathname: 'newfolder1/newfile10.tex',
},
atV: 24,
},
{
rename: {
pathname: 'newfile3.tex',
newPathname: 'newfolder1/newfile3.tex',
},
atV: 23,
},
],
},
{
fromV: 22,
toV: 23,
meta: {
users: historyUsers,
start_ts: 1680888721015,
end_ts: 1680888721015,
},
labels: [],
pathnames: ['newfile3.tex'],
project_ops: [],
},
{
fromV: 19,
toV: 22,
meta: {
users: historyUsers,
start_ts: 1680888715364,
end_ts: 1680888718726,
},
labels: [],
pathnames: [],
project_ops: [
{
rename: {
pathname: 'newfolder1/newfolder2/newfile3.tex',
newPathname: 'newfile3.tex',
},
atV: 21,
},
{
rename: {
pathname: 'newfolder1/newfile2.tex',
newPathname: 'newfolder1/newfolder2/newfile2.tex',
},
atV: 20,
},
{
rename: {
pathname: 'newfolder1/newfile5.tex',
newPathname: 'newfile5.tex',
},
atV: 19,
},
],
},
{
fromV: 16,
toV: 19,
meta: {
users: historyUsers,
start_ts: 1680888705042,
end_ts: 1680888712662,
},
labels: [],
pathnames: [
'main.tex',
'newfolder1/newfile2.tex',
'newfolder1/newfile5.tex',
],
project_ops: [],
},
{
fromV: 0,
toV: 16,
meta: {
users: historyUsers,
start_ts: 1680888456499,
end_ts: 1680888640774,
},
labels: [],
pathnames: [],
project_ops: [
{
add: {
pathname: 'newfolder1/newfile2.tex',
},
atV: 15,
},
{
remove: {
pathname: 'newfile2.tex',
},
atV: 14,
},
{
rename: {
pathname: 'newfolder1/frog.jpg',
newPathname: 'frog.jpg',
},
atV: 13,
},
{
rename: {
pathname: 'newfolder1/newfile2.tex',
newPathname: 'newfile2.tex',
},
atV: 12,
},
{
rename: {
pathname: 'newfile5.tex',
newPathname: 'newfolder1/newfile5.tex',
},
atV: 11,
},
{
rename: {
pathname: 'newfile4.tex',
newPathname: 'newfile5.tex',
},
atV: 10,
},
{
add: {
pathname: 'newfile4.tex',
},
atV: 9,
},
{
remove: {
pathname: 'newfolder1/newfolder2/newfile1.tex',
},
atV: 8,
},
{
rename: {
pathname: 'frog.jpg',
newPathname: 'newfolder1/frog.jpg',
},
atV: 7,
},
{
add: {
pathname: 'newfolder1/newfolder2/newfile3.tex',
},
atV: 6,
},
{
add: {
pathname: 'newfolder1/newfile2.tex',
},
atV: 5,
},
{
rename: {
pathname: 'newfolder1/newfile1.tex',
newPathname: 'newfolder1/newfolder2/newfile1.tex',
},
atV: 4,
},
{
add: {
pathname: 'newfolder1/newfile1.tex',
},
atV: 3,
},
{
add: {
pathname: 'frog.jpg',
},
atV: 2,
},
{
add: {
pathname: 'sample.bib',
},
atV: 1,
},
{
add: {
pathname: 'main.tex',
},
atV: 0,
},
],
},
]
const { pathname } = autoSelectFile(
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('newfolder1/newfile10.tex')
})
it('return file with `added` operation on highest `atV` value if no other operation is available on the latest `updates` entry', function () {
const files: FileDiff[] = [
{
pathname: 'main.tex',
operation: 'added',
editable: true,
},
{
pathname: 'sample.bib',
operation: 'added',
editable: true,
},
{
pathname: 'frog.jpg',
operation: 'added',
editable: false,
},
{
pathname: 'newfile1.tex',
operation: 'added',
editable: true,
},
]
const updates: LoadedUpdate[] = [
{
fromV: 0,
toV: 4,
meta: {
users: historyUsers,
start_ts: 1680861468999,
end_ts: 1680861491861,
},
labels: [],
pathnames: [],
project_ops: [
{
add: {
pathname: 'newfile1.tex',
},
atV: 3,
},
{
add: {
pathname: 'frog.jpg',
},
atV: 2,
},
{
add: {
pathname: 'sample.bib',
},
atV: 1,
},
{
add: {
pathname: 'main.tex',
},
atV: 0,
},
],
},
]
const { pathname } = autoSelectFile(
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('newfile1.tex')
})
it('return the last non-`removed` operation with the highest `atV` value', function () {
const files: FileDiff[] = [
{
pathname: 'main.tex',
operation: 'removed',
deletedAtV: 6,
editable: true,
},
{
pathname: 'sample.bib',
editable: true,
},
{
pathname: 'main2.tex',
operation: 'added',
editable: true,
},
{
pathname: 'main3.tex',
operation: 'added',
editable: true,
},
]
const updates: LoadedUpdate[] = [
{
fromV: 4,
toV: 7,
meta: {
users: historyUsers,
start_ts: 1680874742389,
end_ts: 1680874755552,
},
labels: [],
pathnames: [],
project_ops: [
{
remove: {
pathname: 'main.tex',
},
atV: 6,
},
{
add: {
pathname: 'main3.tex',
},
atV: 5,
},
{
add: {
pathname: 'main2.tex',
},
atV: 4,
},
],
},
{
fromV: 0,
toV: 4,
meta: {
users: historyUsers,
start_ts: 1680861975947,
end_ts: 1680861988442,
},
labels: [],
pathnames: [],
project_ops: [
{
remove: {
pathname: 'frog.jpg',
},
atV: 3,
},
{
add: {
pathname: 'frog.jpg',
},
atV: 2,
},
{
add: {
pathname: 'sample.bib',
},
atV: 1,
},
{
add: {
pathname: 'main.tex',
},
atV: 0,
},
],
},
]
const { pathname } = autoSelectFile(
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('main3.tex')
})
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 () {
const files: FileDiff[] = [
{
pathname: 'main.tex',
editable: true,
},
{
pathname: 'sample.bib',
editable: true,
},
{
pathname: 'frog.jpg',
editable: false,
},
{
pathname: 'newfolder/maybewillbedeleted.tex',
newPathname: 'newfolder2/maybewillbedeleted.tex',
operation: 'removed',
deletedAtV: 10,
editable: true,
},
]
const updates: LoadedUpdate[] = [
{
fromV: 9,
toV: 11,
meta: {
users: historyUsers,
start_ts: 1680904414419,
end_ts: 1680904417538,
},
labels: [],
pathnames: [],
project_ops: [
{
remove: {
pathname: 'newfolder2/maybewillbedeleted.tex',
},
atV: 10,
},
{
rename: {
pathname: 'newfolder/maybewillbedeleted.tex',
newPathname: 'newfolder2/maybewillbedeleted.tex',
},
atV: 9,
},
],
},
{
fromV: 8,
toV: 9,
meta: {
users: historyUsers,
start_ts: 1680904410333,
end_ts: 1680904410333,
},
labels: [],
pathnames: ['newfolder/maybewillbedeleted.tex'],
project_ops: [],
},
{
fromV: 7,
toV: 8,
meta: {
users: historyUsers,
start_ts: 1680904407448,
end_ts: 1680904407448,
},
labels: [],
pathnames: [],
project_ops: [
{
rename: {
pathname: 'newfolder/tobedeleted.tex',
newPathname: 'newfolder/maybewillbedeleted.tex',
},
atV: 7,
},
],
},
{
fromV: 6,
toV: 7,
meta: {
users: historyUsers,
start_ts: 1680904400839,
end_ts: 1680904400839,
},
labels: [],
pathnames: ['newfolder/tobedeleted.tex'],
project_ops: [],
},
{
fromV: 5,
toV: 6,
meta: {
users: historyUsers,
start_ts: 1680904398544,
end_ts: 1680904398544,
},
labels: [],
pathnames: [],
project_ops: [
{
rename: {
pathname: 'tobedeleted.tex',
newPathname: 'newfolder/tobedeleted.tex',
},
atV: 5,
},
],
},
{
fromV: 4,
toV: 5,
meta: {
users: historyUsers,
start_ts: 1680904389891,
end_ts: 1680904389891,
},
labels: [],
pathnames: ['tobedeleted.tex'],
project_ops: [],
},
{
fromV: 0,
toV: 4,
meta: {
users: historyUsers,
start_ts: 1680904363778,
end_ts: 1680904385308,
},
labels: [],
pathnames: [],
project_ops: [
{
add: {
pathname: 'tobedeleted.tex',
},
atV: 3,
},
{
add: {
pathname: 'frog.jpg',
},
atV: 2,
},
{
add: {
pathname: 'sample.bib',
},
atV: 1,
},
{
add: {
pathname: 'main.tex',
},
atV: 0,
},
],
},
]
const { pathname } = autoSelectFile(
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('main.tex')
})
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 () {
const files: FileDiff[] = [
{
pathname: 'certainly_not_main.tex',
editable: true,
},
{
pathname: 'newfile.tex',
editable: true,
},
{
pathname: 'file2.tex',
editable: true,
},
]
const updates: LoadedUpdate[] = [
{
fromV: 7,
toV: 8,
meta: {
users: historyUsers,
start_ts: 1680905536168,
end_ts: 1680905536168,
},
labels: [],
pathnames: [],
project_ops: [
{
remove: {
pathname: 'newfolder/tobedeleted.txt',
},
atV: 7,
},
],
},
{
fromV: 6,
toV: 7,
meta: {
users: historyUsers,
start_ts: 1680905531816,
end_ts: 1680905531816,
},
labels: [],
pathnames: ['newfolder/tobedeleted.txt'],
project_ops: [],
},
{
fromV: 0,
toV: 6,
meta: {
users: historyUsers,
start_ts: 1680905492130,
end_ts: 1680905529186,
},
labels: [],
pathnames: [],
project_ops: [
{
rename: {
pathname: 'tobedeleted.txt',
newPathname: 'newfolder/tobedeleted.txt',
},
atV: 5,
},
{
add: {
pathname: 'file2.tex',
},
atV: 4,
},
{
add: {
pathname: 'newfile.tex',
},
atV: 3,
},
{
add: {
pathname: 'tobedeleted.txt',
},
atV: 2,
},
{
rename: {
pathname: 'main.tex',
newPathname: 'certainly_not_main.tex',
},
atV: 1,
},
{
add: {
pathname: 'main.tex',
},
atV: 0,
},
],
},
]
const { pathname } = autoSelectFile(
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('certainly_not_main.tex')
})
it('selects renamed file', function () {
const files: FileDiff[] = [
{
pathname: 'main.tex',
editable: true,
},
{
pathname: 'original.bib',
newPathname: 'new.bib',
operation: 'renamed',
editable: true,
},
]
const updates: LoadedUpdate[] = [
{
fromV: 4,
toV: 7,
meta: {
users: historyUsers,
start_ts: 1680874742389,
end_ts: 1680874755552,
},
labels: [],
pathnames: [],
project_ops: [
{
rename: {
pathname: 'original.bib',
newPathname: 'new.bib',
},
atV: 5,
},
],
},
{
fromV: 0,
toV: 4,
meta: {
users: historyUsers,
start_ts: 1680861975947,
end_ts: 1680861988442,
},
labels: [],
pathnames: [],
project_ops: [
{
add: {
pathname: 'original.bib',
},
atV: 1,
},
{
add: {
pathname: 'main.tex',
},
atV: 0,
},
],
},
]
const pathname = fileFinalPathname(
autoSelectFile(
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates),
null
)
)
expect(pathname).to.equal('new.bib')
})
it('ignores binary file', function () {
const files: FileDiff[] = [
{
pathname: 'frog.jpg',
editable: false,
operation: 'added',
},
{
pathname: 'main.tex',
editable: true,
},
{
pathname: 'sample.bib',
editable: true,
},
]
const updates: LoadedUpdate[] = [
{
fromV: 4,
toV: 7,
meta: {
users: historyUsers,
start_ts: 1680874742389,
end_ts: 1680874755552,
},
labels: [],
pathnames: [],
project_ops: [
{
add: {
pathname: 'frog.jpg',
},
atV: 5,
},
],
},
{
fromV: 0,
toV: 4,
meta: {
users: historyUsers,
start_ts: 1680861975947,
end_ts: 1680861988442,
},
labels: [],
pathnames: [],
project_ops: [
{
add: {
pathname: 'sample.bib',
},
atV: 1,
},
{
add: {
pathname: 'main.tex',
},
atV: 0,
},
],
},
]
const { pathname } = autoSelectFile(
files,
updates[0].toV,
comparing,
getUpdateForVersion(updates[0].toV, updates),
null
)
expect(pathname).to.equal('main.tex')
})
})
})