mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
promisify FileTreeDiffTests
GitOrigin-RevId: f7c9c119f28bdbf98c526d767ee06286c33ecfa2
This commit is contained in:
committed by
Copybot
parent
808fae694b
commit
8f3d0677c3
@@ -1,72 +1,41 @@
|
||||
/* eslint-disable
|
||||
no-undef,
|
||||
no-unused-vars,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
import sinon from 'sinon'
|
||||
import { expect } from 'chai'
|
||||
import Settings from '@overleaf/settings'
|
||||
import request from 'request'
|
||||
import assert from 'node:assert'
|
||||
import Path from 'node:path'
|
||||
import crypto from 'node:crypto'
|
||||
import mongodb from 'mongodb-legacy'
|
||||
import nock from 'nock'
|
||||
import * as ProjectHistoryClient from './helpers/ProjectHistoryClient.js'
|
||||
import * as ProjectHistoryApp from './helpers/ProjectHistoryApp.js'
|
||||
import * as HistoryId from './helpers/HistoryId.js'
|
||||
const { ObjectId } = mongodb
|
||||
|
||||
const MockHistoryStore = () => nock('http://127.0.0.1:3100')
|
||||
const MockFileStore = () => nock('http://127.0.0.1:3009')
|
||||
const MockWeb = () => nock('http://127.0.0.1:3000')
|
||||
|
||||
const sha = data => crypto.createHash('sha1').update(data).digest('hex')
|
||||
|
||||
describe('FileTree Diffs', function () {
|
||||
beforeEach(function (done) {
|
||||
return ProjectHistoryApp.ensureRunning(error => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
beforeEach(async function () {
|
||||
await ProjectHistoryApp.promises.ensureRunning()
|
||||
|
||||
this.historyId = new ObjectId().toString()
|
||||
this.projectId = new ObjectId().toString()
|
||||
this.historyId = new ObjectId().toString()
|
||||
this.projectId = new ObjectId().toString()
|
||||
|
||||
MockHistoryStore().post('/api/projects').reply(200, {
|
||||
projectId: this.historyId,
|
||||
})
|
||||
MockWeb()
|
||||
.get(`/project/${this.projectId}/details`)
|
||||
.reply(200, {
|
||||
name: 'Test Project',
|
||||
overleaf: { history: { id: this.historyId } },
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.initializeProject(
|
||||
this.historyId,
|
||||
(error, olProject) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
return done()
|
||||
}
|
||||
)
|
||||
MockHistoryStore().post('/api/projects').reply(200, {
|
||||
projectId: this.historyId,
|
||||
})
|
||||
MockWeb()
|
||||
.get(`/project/${this.projectId}/details`)
|
||||
.reply(200, {
|
||||
name: 'Test Project',
|
||||
overleaf: { history: { id: this.historyId } },
|
||||
})
|
||||
|
||||
await ProjectHistoryClient.promises.initializeProject(this.historyId)
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
return nock.cleanAll()
|
||||
})
|
||||
|
||||
it('should return a diff of the updates to a doc from a single chunk', function (done) {
|
||||
it('should return a diff of the updates to a doc from a single chunk', async function () {
|
||||
MockHistoryStore()
|
||||
.get(`/api/projects/${this.historyId}/versions/7/history`)
|
||||
.reply(200, {
|
||||
@@ -139,45 +108,39 @@ describe('FileTree Diffs', function () {
|
||||
authors: [{ id: 31, email: 'james.allen@overleaf.com', name: 'James' }],
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.getFileTreeDiff(
|
||||
const { diff } = await ProjectHistoryClient.getFileTreeDiff(
|
||||
this.projectId,
|
||||
3,
|
||||
7,
|
||||
(error, diff) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'foo.tex',
|
||||
operation: 'edited',
|
||||
},
|
||||
{
|
||||
pathname: 'deleted.tex',
|
||||
operation: 'removed',
|
||||
deletedAtV: 5,
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
newPathname: 'newName.tex',
|
||||
pathname: 'renamed.tex',
|
||||
operation: 'renamed',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
pathname: 'added.tex',
|
||||
operation: 'added',
|
||||
editable: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
return done()
|
||||
}
|
||||
7
|
||||
)
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'foo.tex',
|
||||
operation: 'edited',
|
||||
},
|
||||
{
|
||||
pathname: 'deleted.tex',
|
||||
operation: 'removed',
|
||||
deletedAtV: 5,
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
newPathname: 'newName.tex',
|
||||
pathname: 'renamed.tex',
|
||||
operation: 'renamed',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
pathname: 'added.tex',
|
||||
operation: 'added',
|
||||
editable: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('should return a diff of the updates to a doc across multiple chunks', function (done) {
|
||||
it('should return a diff of the updates to a doc across multiple chunks', async function () {
|
||||
MockHistoryStore()
|
||||
.get(`/api/projects/${this.historyId}/versions/5/history`)
|
||||
.reply(200, {
|
||||
@@ -299,53 +262,47 @@ describe('FileTree Diffs', function () {
|
||||
authors: [{ id: 31, email: 'james.allen@overleaf.com', name: 'James' }],
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.getFileTreeDiff(
|
||||
const { diff } = await ProjectHistoryClient.getFileTreeDiff(
|
||||
this.projectId,
|
||||
2,
|
||||
7,
|
||||
(error, diff) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'foo.tex',
|
||||
operation: 'edited',
|
||||
},
|
||||
{
|
||||
pathname: 'bar.tex',
|
||||
operation: 'edited',
|
||||
},
|
||||
{
|
||||
pathname: 'baz.tex',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
pathname: 'deleted.tex',
|
||||
operation: 'removed',
|
||||
deletedAtV: 4,
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
newPathname: 'newName.tex',
|
||||
pathname: 'renamed.tex',
|
||||
operation: 'renamed',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
pathname: 'added.tex',
|
||||
operation: 'added',
|
||||
editable: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
return done()
|
||||
}
|
||||
7
|
||||
)
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'foo.tex',
|
||||
operation: 'edited',
|
||||
},
|
||||
{
|
||||
pathname: 'bar.tex',
|
||||
operation: 'edited',
|
||||
},
|
||||
{
|
||||
pathname: 'baz.tex',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
pathname: 'deleted.tex',
|
||||
operation: 'removed',
|
||||
deletedAtV: 4,
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
newPathname: 'newName.tex',
|
||||
pathname: 'renamed.tex',
|
||||
operation: 'renamed',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
pathname: 'added.tex',
|
||||
operation: 'added',
|
||||
editable: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('should return a diff that includes multiple renames', function (done) {
|
||||
it('should return a diff that includes multiple renames', async function () {
|
||||
MockHistoryStore()
|
||||
.get(`/api/projects/${this.historyId}/versions/5/history`)
|
||||
.reply(200, {
|
||||
@@ -387,30 +344,24 @@ describe('FileTree Diffs', function () {
|
||||
authors: [{ id: 31, email: 'james.allen@overleaf.com', name: 'James' }],
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.getFileTreeDiff(
|
||||
const { diff } = await ProjectHistoryClient.getFileTreeDiff(
|
||||
this.projectId,
|
||||
3,
|
||||
5,
|
||||
(error, diff) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
newPathname: 'three.tex',
|
||||
pathname: 'one.tex',
|
||||
operation: 'renamed',
|
||||
editable: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
return done()
|
||||
}
|
||||
5
|
||||
)
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
newPathname: 'three.tex',
|
||||
pathname: 'one.tex',
|
||||
operation: 'renamed',
|
||||
editable: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle deleting then re-adding a file', function (done) {
|
||||
it('should handle deleting then re-adding a file', async function () {
|
||||
MockHistoryStore()
|
||||
.get(`/api/projects/${this.historyId}/versions/5/history`)
|
||||
.reply(200, {
|
||||
@@ -454,29 +405,23 @@ describe('FileTree Diffs', function () {
|
||||
authors: [{ id: 31, email: 'james.allen@overleaf.com', name: 'James' }],
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.getFileTreeDiff(
|
||||
const { diff } = await ProjectHistoryClient.getFileTreeDiff(
|
||||
this.projectId,
|
||||
3,
|
||||
5,
|
||||
(error, diff) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'one.tex',
|
||||
operation: 'added',
|
||||
editable: null,
|
||||
},
|
||||
],
|
||||
})
|
||||
return done()
|
||||
}
|
||||
5
|
||||
)
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'one.tex',
|
||||
operation: 'added',
|
||||
editable: null,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle deleting the renaming a file to the same place', function (done) {
|
||||
it('should handle deleting the renaming a file to the same place', async function () {
|
||||
MockHistoryStore()
|
||||
.get(`/api/projects/${this.historyId}/versions/5/history`)
|
||||
.reply(200, {
|
||||
@@ -522,30 +467,24 @@ describe('FileTree Diffs', function () {
|
||||
authors: [{ id: 31, email: 'james.allen@overleaf.com', name: 'James' }],
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.getFileTreeDiff(
|
||||
const { diff } = await ProjectHistoryClient.getFileTreeDiff(
|
||||
this.projectId,
|
||||
3,
|
||||
5,
|
||||
(error, diff) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'two.tex',
|
||||
newPathname: 'one.tex',
|
||||
operation: 'renamed',
|
||||
editable: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
return done()
|
||||
}
|
||||
5
|
||||
)
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'two.tex',
|
||||
newPathname: 'one.tex',
|
||||
operation: 'renamed',
|
||||
editable: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle adding then renaming a file', function (done) {
|
||||
it('should handle adding then renaming a file', async function () {
|
||||
MockHistoryStore()
|
||||
.get(`/api/projects/${this.historyId}/versions/5/history`)
|
||||
.reply(200, {
|
||||
@@ -585,29 +524,23 @@ describe('FileTree Diffs', function () {
|
||||
authors: [{ id: 31, email: 'james.allen@overleaf.com', name: 'James' }],
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.getFileTreeDiff(
|
||||
const { diff } = await ProjectHistoryClient.getFileTreeDiff(
|
||||
this.projectId,
|
||||
3,
|
||||
5,
|
||||
(error, diff) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'two.tex',
|
||||
operation: 'added',
|
||||
editable: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
return done()
|
||||
}
|
||||
5
|
||||
)
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'two.tex',
|
||||
operation: 'added',
|
||||
editable: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('should return 422 with a chunk with an invalid rename', function (done) {
|
||||
it('should return 422 with a chunk with an invalid rename', async function () {
|
||||
MockHistoryStore()
|
||||
.get(`/api/projects/${this.historyId}/versions/6/history`)
|
||||
.reply(200, {
|
||||
@@ -643,21 +576,15 @@ describe('FileTree Diffs', function () {
|
||||
authors: [{ id: 31, email: 'james.allen@overleaf.com', name: 'James' }],
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.getFileTreeDiff(
|
||||
const { statusCode } = await ProjectHistoryClient.getFileTreeDiff(
|
||||
this.projectId,
|
||||
5,
|
||||
6,
|
||||
(error, diff, statusCode) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
expect(statusCode).to.equal(422)
|
||||
return done()
|
||||
}
|
||||
6
|
||||
)
|
||||
expect(statusCode).to.equal(422)
|
||||
})
|
||||
|
||||
it('should return 200 with a chunk with an invalid add', function (done) {
|
||||
it('should return 200 with a chunk with an invalid add', async function () {
|
||||
MockHistoryStore()
|
||||
.get(`/api/projects/${this.historyId}/versions/6/history`)
|
||||
.reply(200, {
|
||||
@@ -691,30 +618,24 @@ describe('FileTree Diffs', function () {
|
||||
authors: [{ id: 31, email: 'james.allen@overleaf.com', name: 'James' }],
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.getFileTreeDiff(
|
||||
const { diff, statusCode } = await ProjectHistoryClient.getFileTreeDiff(
|
||||
this.projectId,
|
||||
5,
|
||||
6,
|
||||
(error, diff, statusCode) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'foo.tex',
|
||||
operation: 'added',
|
||||
editable: null,
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(statusCode).to.equal(200)
|
||||
return done()
|
||||
}
|
||||
6
|
||||
)
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
pathname: 'foo.tex',
|
||||
operation: 'added',
|
||||
editable: null,
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(statusCode).to.equal(200)
|
||||
})
|
||||
|
||||
it('should handle edits of missing/invalid files ', function (done) {
|
||||
it('should handle edits of missing/invalid files ', async function () {
|
||||
MockHistoryStore()
|
||||
.get(`/api/projects/${this.historyId}/versions/5/history`)
|
||||
.reply(200, {
|
||||
@@ -751,28 +672,22 @@ describe('FileTree Diffs', function () {
|
||||
authors: [{ id: 31, email: 'james.allen@overleaf.com', name: 'James' }],
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.getFileTreeDiff(
|
||||
const { diff } = await ProjectHistoryClient.getFileTreeDiff(
|
||||
this.projectId,
|
||||
3,
|
||||
5,
|
||||
(error, diff) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
operation: 'edited',
|
||||
pathname: 'new.tex',
|
||||
},
|
||||
],
|
||||
})
|
||||
return done()
|
||||
}
|
||||
5
|
||||
)
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [
|
||||
{
|
||||
operation: 'edited',
|
||||
pathname: 'new.tex',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle deletions of missing/invalid files ', function (done) {
|
||||
it('should handle deletions of missing/invalid files ', async function () {
|
||||
MockHistoryStore()
|
||||
.get(`/api/projects/${this.historyId}/versions/5/history`)
|
||||
.reply(200, {
|
||||
@@ -809,23 +724,17 @@ describe('FileTree Diffs', function () {
|
||||
authors: [{ id: 31, email: 'james.allen@overleaf.com', name: 'James' }],
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.getFileTreeDiff(
|
||||
const { diff } = await ProjectHistoryClient.getFileTreeDiff(
|
||||
this.projectId,
|
||||
3,
|
||||
5,
|
||||
(error, diff) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [],
|
||||
})
|
||||
return done()
|
||||
}
|
||||
5
|
||||
)
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [],
|
||||
})
|
||||
})
|
||||
|
||||
return it('should handle renames of missing/invalid files ', function (done) {
|
||||
return it('should handle renames of missing/invalid files ', async function () {
|
||||
MockHistoryStore()
|
||||
.get(`/api/projects/${this.historyId}/versions/5/history`)
|
||||
.reply(200, {
|
||||
@@ -862,19 +771,13 @@ describe('FileTree Diffs', function () {
|
||||
authors: [{ id: 31, email: 'james.allen@overleaf.com', name: 'James' }],
|
||||
})
|
||||
|
||||
return ProjectHistoryClient.getFileTreeDiff(
|
||||
const { diff } = await ProjectHistoryClient.getFileTreeDiff(
|
||||
this.projectId,
|
||||
3,
|
||||
5,
|
||||
(error, diff) => {
|
||||
if (error != null) {
|
||||
throw error
|
||||
}
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [],
|
||||
})
|
||||
return done()
|
||||
}
|
||||
5
|
||||
)
|
||||
expect(diff).to.deep.equal({
|
||||
diff: [],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -4,7 +4,11 @@ import Settings from '@overleaf/settings'
|
||||
import RedisWrapper from '@overleaf/redis-wrapper'
|
||||
import { db } from '../../../../app/js/mongodb.js'
|
||||
import { promisify } from '@overleaf/promise-utils'
|
||||
import { fetchJsonWithResponse, fetchNothing } from '@overleaf/fetch-utils'
|
||||
import {
|
||||
fetchJsonWithResponse,
|
||||
fetchNothing,
|
||||
RequestFailedError,
|
||||
} from '@overleaf/fetch-utils'
|
||||
|
||||
const rclient = RedisWrapper.createClient(Settings.redis.project_history)
|
||||
const Keys = Settings.redis.project_history.key_schema
|
||||
@@ -81,23 +85,22 @@ export async function getDiff(projectId, pathname, from, to) {
|
||||
return json
|
||||
}
|
||||
|
||||
export function getFileTreeDiff(projectId, from, to, callback) {
|
||||
request.get(
|
||||
{
|
||||
url: `http://127.0.0.1:3054/project/${projectId}/filetree/diff`,
|
||||
qs: {
|
||||
from,
|
||||
to,
|
||||
},
|
||||
json: true,
|
||||
},
|
||||
(error, res, body) => {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
callback(error, body, res.statusCode)
|
||||
}
|
||||
export async function getFileTreeDiff(projectId, from, to) {
|
||||
const url = new URL(
|
||||
`http://127.0.0.1:3054/project/${projectId}/filetree/diff`
|
||||
)
|
||||
url.searchParams.set('from', from)
|
||||
url.searchParams.set('to', to)
|
||||
|
||||
try {
|
||||
const { response, json } = await fetchJsonWithResponse(url.toString())
|
||||
return { diff: json, statusCode: response.status }
|
||||
} catch (error) {
|
||||
if (error instanceof RequestFailedError) {
|
||||
return { diff: null, statusCode: error.response.status }
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export function getChangesInChunkSince(projectId, since, options, callback) {
|
||||
|
||||
Reference in New Issue
Block a user