overleaf/services/web/test/acceptance/src/ProjectStructureTests.js
Miguel Serrano 27985458ea Uploading an empty zipfile throws specific error (#1909)
Added a counter for the total files extracted from a zip. If no files are extracted a specific error is thrown.

GitOrigin-RevId: 391bb669500c86e2e7fecebd90e2201248a8afd3
2019-07-02 10:58:58 +00:00

1505 lines
46 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* eslint-disable
camelcase,
max-len,
no-path-concat,
no-return-assign,
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
*/
const async = require('async')
const { expect } = require('chai')
const mkdirp = require('mkdirp')
const { ObjectId } = require('mongojs')
const Path = require('path')
const fs = require('fs')
const Settings = require('settings-sharelatex')
const _ = require('underscore')
const ProjectGetter = require('../../../app/src/Features/Project/ProjectGetter.js')
const MockDocUpdaterApi = require('./helpers/MockDocUpdaterApi')
const MockFileStoreApi = require('./helpers/MockFileStoreApi')
const MockProjectHistoryApi = require('./helpers/MockProjectHistoryApi')
const request = require('./helpers/request')
const User = require('./helpers/User')
describe('ProjectStructureChanges', function() {
let example_project_id = null
let example_doc_id = null
let example_file_id = null
let example_folder_id_1 = null
let example_folder_id_2 = null
before(function(done) {
this.owner = new User()
return this.owner.login(done)
})
describe('creating a project from the example template', function() {
before(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
return this.owner.createProject(
'example-project',
{ template: 'example' },
(error, project_id) => {
if (error != null) {
throw error
}
example_project_id = project_id
return done()
}
)
})
it('should version creating a doc', function() {
const {
docUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
expect(updates.length).to.equal(2)
_.each(updates, update => {
expect(update.userId).to.equal(this.owner._id)
return expect(update.docLines).to.be.a('string')
})
expect(_.where(updates, { pathname: '/main.tex' }).length).to.equal(1)
expect(_.where(updates, { pathname: '/references.bib' }).length).to.equal(
1
)
return expect(version).to.equal(3)
})
it('should version creating a file', function() {
const {
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/universe.jpg')
expect(update.url).to.be.a('string')
return expect(version).to.equal(3)
})
})
describe('duplicating a project', function() {
before(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
return this.owner.request.post(
{
uri: `/Project/${example_project_id}/clone`,
json: {
projectName: 'new.tex'
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to add doc ${res.statusCode}`)
}
this.dup_project_id = body.project_id
return done()
}
)
})
it('should version the docs created', function() {
const {
docUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(this.dup_project_id)
expect(updates.length).to.equal(2)
_.each(updates, update => {
expect(update.userId).to.equal(this.owner._id)
return expect(update.docLines).to.be.a('string')
})
expect(_.where(updates, { pathname: '/main.tex' }).length).to.equal(1)
expect(_.where(updates, { pathname: '/references.bib' }).length).to.equal(
1
)
return expect(version).to.equal(3)
})
it('should version the files created', function() {
const {
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(this.dup_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/universe.jpg')
expect(update.url).to.be.a('string')
return expect(version).to.equal(3)
})
})
describe('adding a doc', function() {
before(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
return ProjectGetter.getProject(example_project_id, (error, project) => {
if (error != null) {
throw error
}
this.project_0 = project
return this.owner.request.post(
{
uri: `project/${example_project_id}/doc`,
json: {
name: 'new.tex',
parent_folder_id: project.rootFolder[0]._id
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to add doc ${res.statusCode}`)
}
example_doc_id = body._id
return ProjectGetter.getProject(
example_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
return done()
}
)
}
)
})
})
it('should version the doc added', function() {
const {
docUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/new.tex')
expect(update.docLines).to.be.a('string')
return expect(version).to.equal(this.project_0.version + 1)
})
it('should increment the project structure version number', function() {
return expect(this.project_1.version).to.equal(this.project_0.version + 1)
})
})
describe('uploading a project', function() {
before(function(done) {
let req
MockDocUpdaterApi.clearProjectStructureUpdates()
const zip_file = fs.createReadStream(
Path.resolve(__dirname + '/../files/test_project.zip')
)
this.test_project_name = 'wombat'
return (req = this.owner.request.post(
{
uri: 'project/new/upload',
formData: {
qqfile: zip_file
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload project ${res.statusCode}`)
}
this.uploaded_project_id = JSON.parse(body).project_id
return done()
}
))
})
it('should version the docs created', function() {
const {
docUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(this.uploaded_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/main.tex')
expect(update.docLines).to.equal('Test')
return expect(version).to.equal(2)
})
it('should version the files created', function() {
const {
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(this.uploaded_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/1pixel.png')
expect(update.url).to.be.a('string')
return expect(version).to.equal(2)
})
})
describe('uploading a project with a name', function() {
before(function(done) {
let req
MockDocUpdaterApi.clearProjectStructureUpdates()
const zip_file = fs.createReadStream(
Path.resolve(__dirname + '/../files/test_project_with_name.zip')
)
this.test_project_name = 'wombat'
return (req = this.owner.request.post(
{
uri: 'project/new/upload',
formData: {
qqfile: zip_file
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload project ${res.statusCode}`)
}
this.uploaded_project_id = JSON.parse(body).project_id
return done()
}
))
})
it('should set the project name from the zip contents', function(done) {
return ProjectGetter.getProject(
this.uploaded_project_id,
(error, project) => {
expect(error).not.to.exist
expect(project.name).to.equal(this.test_project_name)
return done()
}
)
})
})
describe('uploading a project with an invalid name', function() {
before(function(done) {
let req
MockDocUpdaterApi.clearProjectStructureUpdates()
const zip_file = fs.createReadStream(
Path.resolve(__dirname + '/../files/test_project_with_invalid_name.zip')
)
this.test_project_match = /^bad[^\\]+name$/
return (req = this.owner.request.post(
{
uri: 'project/new/upload',
formData: {
qqfile: zip_file
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload project ${res.statusCode}`)
}
this.uploaded_project_id = JSON.parse(body).project_id
return done()
}
))
})
it('should set the project name from the zip contents', function(done) {
return ProjectGetter.getProject(
this.uploaded_project_id,
(error, project) => {
expect(error).not.to.exist
expect(project.name).to.match(this.test_project_match)
return done()
}
)
})
})
describe('uploading an empty zipfile', function() {
let zipFile = null
before(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
zipFile = fs.createReadStream(
Path.resolve(__dirname + '/../files/test_project_empty.zip')
)
done()
})
it('should fail with 422 error', function(done) {
this.owner.request.post(
{
uri: 'project/new/upload',
formData: {
qqfile: zipFile
}
},
(error, res) => {
if (error != null) {
throw error
}
expect(res.statusCode).to.equal(422)
done()
}
)
})
})
describe('uploading a zipfile containing only empty directories', function() {
let zipFile = null
before(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
zipFile = fs.createReadStream(
Path.resolve(__dirname + '/../files/test_project_with_empty_folder.zip')
)
done()
})
it('should fail with 422 error', function(done) {
this.owner.request.post(
{
uri: 'project/new/upload',
formData: {
qqfile: zipFile
}
},
(error, res) => {
if (error != null) {
throw error
}
expect(res.statusCode).to.equal(422)
done()
}
)
})
})
describe('uploading a project with a shared top-level folder', function() {
before(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
const zip_file = fs.createReadStream(
Path.resolve(
__dirname + '/../files/test_project_with_shared_top_level_folder.zip'
)
)
return this.owner.request.post(
{
uri: 'project/new/upload',
formData: {
qqfile: zip_file
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload project ${res.statusCode}`)
}
this.uploaded_project_id = JSON.parse(body).project_id
return done()
}
)
})
it('should not create the top-level folder', function(done) {
return ProjectGetter.getProject(this.uploaded_project_id, function(
error,
project
) {
expect(error).not.to.exist
expect(project.rootFolder[0].folders.length).to.equal(0)
expect(project.rootFolder[0].docs.length).to.equal(2)
return done()
})
})
})
describe('uploading a project with backslashes in the path names', function() {
before(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
const zip_file = fs.createReadStream(
Path.resolve(
__dirname + '/../files/test_project_with_backslash_in_filename.zip'
)
)
return this.owner.request.post(
{
uri: 'project/new/upload',
formData: {
qqfile: zip_file
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload project ${res.statusCode}`)
}
this.uploaded_project_id = JSON.parse(body).project_id
return done()
}
)
})
it('should treat the backslash as a directory separator', function(done) {
return ProjectGetter.getProject(this.uploaded_project_id, function(
error,
project
) {
expect(error).not.to.exist
expect(project.rootFolder[0].folders[0].name).to.equal('styles')
expect(project.rootFolder[0].folders[0].docs[0].name).to.equal('ao.sty')
return done()
})
})
})
describe('uploading a project with files in different encodings', function() {
before(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
const zip_file = fs.createReadStream(
Path.resolve(__dirname + '/../files/charsets/charsets.zip')
)
return this.owner.request.post(
{
uri: 'project/new/upload',
formData: {
qqfile: zip_file
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload project ${res.statusCode}`)
}
this.uploaded_project_id = JSON.parse(body).project_id
return done()
}
)
})
it('should correctly parse windows-1252', function() {
const {
docUpdates: updates
} = MockDocUpdaterApi.getProjectStructureUpdates(this.uploaded_project_id)
const update = _.find(
updates,
update => update.pathname === '/test-german-windows-1252.tex'
)
return expect(update.docLines).to.contain(
'Der schnelle braune Fuchs sprang träge über den Hund.'
)
})
it('should correctly parse German utf8', function() {
const {
docUpdates: updates
} = MockDocUpdaterApi.getProjectStructureUpdates(this.uploaded_project_id)
const update = _.find(
updates,
update => update.pathname === '/test-german-utf8x.tex'
)
return expect(update.docLines).to.contain(
'Der schnelle braune Fuchs sprang träge über den Hund.'
)
})
it('should correctly parse little-endian utf16', function() {
const {
docUpdates: updates
} = MockDocUpdaterApi.getProjectStructureUpdates(this.uploaded_project_id)
const update = _.find(
updates,
update => update.pathname === '/test-greek-utf16-le-bom.tex'
)
return expect(update.docLines).to.contain(
'Η γρήγορη καστανή αλεπού πήδηξε χαλαρά πάνω από το σκυλί.'
)
})
it('should correctly parse Greek utf8', function() {
const {
docUpdates: updates
} = MockDocUpdaterApi.getProjectStructureUpdates(this.uploaded_project_id)
const update = _.find(
updates,
update => update.pathname === '/test-greek-utf8x.tex'
)
return expect(update.docLines).to.contain(
'Η γρήγορη καστανή αλεπού πήδηξε χαλαρά πάνω από το σκυλί.'
)
})
})
describe('uploading a file', function() {
beforeEach(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
return ProjectGetter.getProject(example_project_id, (error, project) => {
if (error != null) {
throw error
}
this.root_folder_id = project.rootFolder[0]._id.toString()
this.project_0 = project
return done()
})
})
it('should version a newly uploaded file', function(done) {
let req
const image_file = fs.createReadStream(
Path.resolve(__dirname + '/../files/1pixel.png')
)
return (req = this.owner.request.post(
{
uri: `project/${example_project_id}/upload`,
qs: {
folder_id: this.root_folder_id
},
formData: {
qqfile: {
value: image_file,
options: {
filename: '1pixel.png',
contentType: 'image/png'
}
}
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload file ${res.statusCode}`)
}
example_file_id = JSON.parse(body).entity_id
const {
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/1pixel.png')
expect(update.url).to.be.a('string')
this.original_file_url = update.url
expect(version).to.equal(this.project_0.version + 1)
return ProjectGetter.getProject(
example_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// uploading a new file does change the project structure
expect(this.project_1.version).to.equal(
this.project_0.version + 1
)
return done()
}
)
}
))
})
it('should version a replacement file', function(done) {
let req
const image_file = fs.createReadStream(
Path.resolve(__dirname + '/../files/2pixel.png')
)
return (req = this.owner.request.post(
{
uri: `project/${example_project_id}/upload`,
qs: {
folder_id: this.root_folder_id
},
formData: {
qqfile: {
value: image_file,
options: {
filename: '1pixel.png',
contentType: 'image/png'
}
}
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload file ${res.statusCode}`)
}
example_file_id = JSON.parse(body).entity_id
const {
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
expect(updates.length).to.equal(2)
let update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/1pixel.png')
// expect(update.url).to.be.a('string');
update = updates[1]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/1pixel.png')
expect(update.url).to.be.a('string')
expect(version).to.equal(this.project_0.version + 1)
return ProjectGetter.getProject(
example_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(
this.project_0.version + 1
)
return done()
}
)
}
))
})
})
describe('moving entities', function() {
before(function(done) {
return this.owner.request.post(
{
uri: `project/${example_project_id}/folder`,
json: {
name: 'foo'
}
},
(error, res, body) => {
if (error != null) {
throw error
}
example_folder_id_1 = body._id
return done()
}
)
})
beforeEach(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
return ProjectGetter.getProject(example_project_id, (error, project) => {
if (error != null) {
throw error
}
this.root_folder_id = project.rootFolder[0]._id.toString()
this.project_0 = project
return done()
})
})
it('should version moving a doc', function(done) {
return this.owner.request.post(
{
uri: `project/${example_project_id}/Doc/${example_doc_id}/move`,
json: {
folder_id: example_folder_id_1
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to move doc ${res.statusCode}`)
}
const {
docUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/new.tex')
expect(update.newPathname).to.equal('/foo/new.tex')
expect(version).to.equal(this.project_0.version + 2)
return ProjectGetter.getProject(
example_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(
this.project_0.version + 2
) // 2 because it's a delete and then add
return done()
}
)
}
)
})
it('should version moving a file', function(done) {
return this.owner.request.post(
{
uri: `project/${example_project_id}/File/${example_file_id}/move`,
json: {
folder_id: example_folder_id_1
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to move file ${res.statusCode}`)
}
const {
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/1pixel.png')
expect(update.newPathname).to.equal('/foo/1pixel.png')
expect(version).to.equal(this.project_0.version + 2)
return ProjectGetter.getProject(
example_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(
this.project_0.version + 2
) // 2 because it's a delete and then add
return done()
}
)
}
)
})
it('should version moving a folder', function(done) {
return this.owner.request.post(
{
uri: `project/${example_project_id}/folder`,
json: {
name: 'bar'
}
},
(error, res, body) => {
if (error != null) {
throw error
}
example_folder_id_2 = body._id
return this.owner.request.post(
{
uri: `project/${example_project_id}/Folder/${example_folder_id_1}/move`,
json: {
folder_id: example_folder_id_2
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to move folder ${res.statusCode}`)
}
let {
docUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(
example_project_id
)
expect(updates.length).to.equal(1)
let update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/foo/new.tex')
expect(update.newPathname).to.equal('/bar/foo/new.tex')
expect(version).to.equal(this.project_0.version + 3)
;({
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(
example_project_id
))
expect(updates.length).to.equal(1)
update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/foo/1pixel.png')
expect(update.newPathname).to.equal('/bar/foo/1pixel.png')
expect(version).to.equal(this.project_0.version + 3)
return ProjectGetter.getProject(
example_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(
this.project_0.version + 3
) // because folder and 2 files move
return done()
}
)
}
)
}
)
})
})
describe('renaming entities', function() {
beforeEach(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
return ProjectGetter.getProject(example_project_id, (error, project) => {
if (error != null) {
throw error
}
this.root_folder_id = project.rootFolder[0]._id.toString()
this.project_0 = project
return done()
})
})
it('should version renaming a doc', function(done) {
return this.owner.request.post(
{
uri: `project/${example_project_id}/Doc/${example_doc_id}/rename`,
json: {
name: 'new_renamed.tex'
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to move doc ${res.statusCode}`)
}
const {
docUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/bar/foo/new.tex')
expect(update.newPathname).to.equal('/bar/foo/new_renamed.tex')
expect(version).to.equal(this.project_0.version + 1)
return ProjectGetter.getProject(
example_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(
this.project_0.version + 1
)
return done()
}
)
}
)
})
it('should version renaming a file', function(done) {
return this.owner.request.post(
{
uri: `project/${example_project_id}/File/${example_file_id}/rename`,
json: {
name: '1pixel_renamed.png'
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to move file ${res.statusCode}`)
}
const {
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/bar/foo/1pixel.png')
expect(update.newPathname).to.equal('/bar/foo/1pixel_renamed.png')
expect(version).to.equal(this.project_0.version + 1)
return ProjectGetter.getProject(
example_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(
this.project_0.version + 1
)
return done()
}
)
}
)
})
it('should version renaming a folder', function(done) {
return this.owner.request.post(
{
uri: `project/${example_project_id}/Folder/${example_folder_id_1}/rename`,
json: {
name: 'foo_renamed'
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to move folder ${res.statusCode}`)
}
let {
docUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
expect(updates.length).to.equal(1)
let update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/bar/foo/new_renamed.tex')
expect(update.newPathname).to.equal(
'/bar/foo_renamed/new_renamed.tex'
)
expect(version).to.equal(this.project_0.version + 1)
;({
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id))
expect(updates.length).to.equal(1)
update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/bar/foo/1pixel_renamed.png')
expect(update.newPathname).to.equal(
'/bar/foo_renamed/1pixel_renamed.png'
)
expect(version).to.equal(this.project_0.version + 1)
return ProjectGetter.getProject(
example_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(
this.project_0.version + 1
)
return done()
}
)
}
)
})
})
describe('deleting entities', function() {
beforeEach(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
return ProjectGetter.getProject(example_project_id, (error, project) => {
if (error != null) {
throw error
}
this.root_folder_id = project.rootFolder[0]._id.toString()
this.project_0 = project
return done()
})
})
it('should version deleting a folder', function(done) {
return this.owner.request.delete(
{
uri: `project/${example_project_id}/Folder/${example_folder_id_2}`
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to delete folder ${res.statusCode}`)
}
let {
docUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
expect(updates.length).to.equal(1)
let update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/bar/foo_renamed/new_renamed.tex')
expect(update.newPathname).to.equal('')
expect(version).to.equal(this.project_0.version + 1)
;({
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id))
expect(updates.length).to.equal(1)
update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal(
'/bar/foo_renamed/1pixel_renamed.png'
)
expect(update.newPathname).to.equal('')
expect(version).to.equal(this.project_0.version + 1)
return ProjectGetter.getProject(
example_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(
this.project_0.version + 1
)
return done()
}
)
}
)
})
})
describe('tpds', function() {
before(function(done) {
this.tpds_project_name = `tpds-project-${new ObjectId().toString()}`
return this.owner.createProject(
this.tpds_project_name,
(error, project_id) => {
if (error != null) {
throw error
}
this.tpds_project_id = project_id
return mkdirp(Settings.path.dumpFolder, done)
}
)
})
beforeEach(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
return ProjectGetter.getProject(
this.tpds_project_id,
(error, project) => {
if (error != null) {
throw error
}
this.root_folder_id = project.rootFolder[0]._id.toString()
this.project_0 = project
return done()
}
)
})
it('should version adding a doc', function(done) {
const tex_file = fs.createReadStream(
Path.resolve(__dirname + '/../files/test.tex')
)
const req = this.owner.request.post({
uri: `/user/${this.owner._id}/update/${
this.tpds_project_name
}/test.tex`,
auth: {
user: _.keys(Settings.httpAuthUsers)[0],
pass: _.values(Settings.httpAuthUsers)[0],
sendImmediately: true
}
})
tex_file.on('error', function(err) {
throw err
})
req.on('error', function(err) {
throw err
})
req.on('response', res => {
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload file ${res.statusCode}`)
}
const {
docUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(this.tpds_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/test.tex')
expect(update.docLines).to.equal('Test')
expect(version).to.equal(this.project_0.version + 1)
return ProjectGetter.getProject(
this.tpds_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(this.project_0.version + 1)
return done()
}
)
})
return tex_file.pipe(req)
})
it('should version adding a new file', function(done) {
const image_file = fs.createReadStream(
Path.resolve(__dirname + '/../files/1pixel.png')
)
const req = this.owner.request.post({
uri: `/user/${this.owner._id}/update/${
this.tpds_project_name
}/1pixel.png`,
auth: {
user: _.keys(Settings.httpAuthUsers)[0],
pass: _.values(Settings.httpAuthUsers)[0],
sendImmediately: true
}
})
image_file.on('error', function(err) {
throw err
})
req.on('error', function(err) {
throw err
})
req.on('response', res => {
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload file ${res.statusCode}`)
}
const {
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(this.tpds_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/1pixel.png')
expect(update.url).to.be.a('string')
expect(version).to.equal(this.project_0.version + 1)
return ProjectGetter.getProject(
this.tpds_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(this.project_0.version + 1)
return done()
}
)
})
return image_file.pipe(req)
})
it('should version replacing a file', function(done) {
const image_file = fs.createReadStream(
Path.resolve(__dirname + '/../files/2pixel.png')
)
const req = this.owner.request.post({
uri: `/user/${this.owner._id}/update/${
this.tpds_project_name
}/1pixel.png`,
auth: {
user: _.keys(Settings.httpAuthUsers)[0],
pass: _.values(Settings.httpAuthUsers)[0],
sendImmediately: true
}
})
image_file.on('error', function(err) {
throw err
})
req.on('error', function(err) {
throw err
})
req.on('response', res => {
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload file ${res.statusCode}`)
}
const {
fileUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(this.tpds_project_id)
expect(updates.length).to.equal(2)
let update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/1pixel.png')
// expect(update.url).to.be.a('string');
update = updates[1]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/1pixel.png')
expect(update.url).to.be.a('string')
expect(version).to.equal(this.project_0.version + 1)
return ProjectGetter.getProject(
this.tpds_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(this.project_0.version + 1)
return done()
}
)
})
return image_file.pipe(req)
})
it('should version deleting a doc', function(done) {
let req
return (req = this.owner.request.delete(
{
uri: `/user/${this.owner._id}/update/${
this.tpds_project_name
}/test.tex`,
auth: {
user: _.keys(Settings.httpAuthUsers)[0],
pass: _.values(Settings.httpAuthUsers)[0],
sendImmediately: true
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to delete doc ${res.statusCode}`)
}
const {
docUpdates: updates,
version
} = MockDocUpdaterApi.getProjectStructureUpdates(this.tpds_project_id)
expect(updates.length).to.equal(1)
const update = updates[0]
expect(update.userId).to.equal(this.owner._id)
expect(update.pathname).to.equal('/test.tex')
expect(update.newPathname).to.equal('')
expect(version).to.equal(this.project_0.version + 1)
return ProjectGetter.getProject(
this.tpds_project_id,
(error, newProject) => {
if (error != null) {
throw error
}
this.project_1 = newProject
// replacing a file should update the project structure
expect(this.project_1.version).to.equal(
this.project_0.version + 1
)
return done()
}
)
}
))
})
})
describe('uploading a document', function() {
beforeEach(function(done) {
MockDocUpdaterApi.clearProjectStructureUpdates()
return ProjectGetter.getProject(example_project_id, (error, project) => {
if (error != null) {
throw error
}
this.root_folder_id = project.rootFolder[0]._id.toString()
this.project_0 = project
return done()
})
})
describe('with an unusual character set', function() {
it('should correctly handle utf16-le data', function(done) {
let req
const document_file = fs.createReadStream(
Path.resolve(
__dirname + '/../files/charsets/test-greek-utf16-le-bom.tex'
)
)
return (req = this.owner.request.post(
{
uri: `project/${example_project_id}/upload`,
qs: {
folder_id: this.root_folder_id
},
formData: {
qqfile: {
value: document_file,
options: {
filename: 'test-greek-utf16-le-bom.tex',
contentType: 'text/x-tex'
}
}
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload file ${res.statusCode}`)
}
example_file_id = JSON.parse(body).entity_id
const {
docUpdates: updates
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
const update = updates[0]
expect(update.pathname).to.equal('/test-greek-utf16-le-bom.tex')
expect(update.docLines).to.contain(
'Η γρήγορη καστανή αλεπού πήδηξε χαλαρά πάνω από το σκυλί.'
)
return done()
}
))
})
it('should correctly handle windows1252/iso-8859-1/latin1 data', function(done) {
let req
const document_file = fs.createReadStream(
Path.resolve(
__dirname + '/../files/charsets/test-german-windows-1252.tex'
)
)
return (req = this.owner.request.post(
{
uri: `project/${example_project_id}/upload`,
qs: {
folder_id: this.root_folder_id
},
formData: {
qqfile: {
value: document_file,
options: {
filename: 'test-german-windows-1252.tex',
contentType: 'text/x-tex'
}
}
}
},
(error, res, body) => {
if (error != null) {
throw error
}
if (res.statusCode < 200 || res.statusCode >= 300) {
throw new Error(`failed to upload file ${res.statusCode}`)
}
example_file_id = JSON.parse(body).entity_id
const {
docUpdates: updates
} = MockDocUpdaterApi.getProjectStructureUpdates(example_project_id)
const update = updates[0]
expect(update.pathname).to.equal('/test-german-windows-1252.tex')
expect(update.docLines).to.contain(
'Der schnelle braune Fuchs sprang träge über den Hund.'
)
return done()
}
))
})
})
})
})