mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-26 18:51:50 +02:00
Promisify tests
GitOrigin-RevId: 6f413f4c5ef8d034b4e94afacdf2d7b43c3a8830
This commit is contained in:
@@ -1283,6 +1283,7 @@ const ProjectEntityUpdateHandler = {
|
||||
upsertFile,
|
||||
upsertFileWithPath,
|
||||
appendToDocWithPath: appendToDoc,
|
||||
setMainBibliographyDoc,
|
||||
},
|
||||
|
||||
async _addDocAndSendToTpds(projectId, folderId, doc, userId) {
|
||||
|
||||
@@ -206,7 +206,7 @@ describe('AuthorizationMiddleware', function () {
|
||||
expectForbidden()
|
||||
})
|
||||
|
||||
describe('for a regular user', function (done) {
|
||||
describe('for a regular user', function () {
|
||||
setupPermission('isRestrictedUserForProject', false)
|
||||
invokeMiddleware('blockRestrictedUserFromProject')
|
||||
expectNext()
|
||||
|
||||
@@ -59,47 +59,34 @@ describe('BrandVariationsHandler', function () {
|
||||
})
|
||||
|
||||
describe('getBrandVariationById', function () {
|
||||
it('should call the callback with an error when the branding variation id is not provided', function (done) {
|
||||
return this.BrandVariationsHandler.getBrandVariationById(
|
||||
null,
|
||||
(err, brandVariationDetails) => {
|
||||
expect(err).to.be.instanceof(Error)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
it('should reject with an error when the branding variation id is not provided', async function () {
|
||||
await expect(
|
||||
this.BrandVariationsHandler.promises.getBrandVariationById(null)
|
||||
).to.be.rejected
|
||||
})
|
||||
|
||||
it('should call the callback with an error when the request errors', function (done) {
|
||||
it('should reject with an error when the request errors', async function () {
|
||||
this.V1Api.request.callsArgWith(1, new Error())
|
||||
return this.BrandVariationsHandler.getBrandVariationById(
|
||||
'12',
|
||||
(err, brandVariationDetails) => {
|
||||
expect(err).to.be.instanceof(Error)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
await expect(
|
||||
this.BrandVariationsHandler.promises.getBrandVariationById('12')
|
||||
).to.be.rejected
|
||||
})
|
||||
|
||||
it('should call the callback with branding details when request succeeds', function (done) {
|
||||
it('should return branding details when request succeeds', async function () {
|
||||
this.V1Api.request.callsArgWith(
|
||||
1,
|
||||
null,
|
||||
{ statusCode: 200 },
|
||||
this.mockedBrandVariationDetails
|
||||
)
|
||||
return this.BrandVariationsHandler.getBrandVariationById(
|
||||
'12',
|
||||
(err, brandVariationDetails) => {
|
||||
expect(err).to.not.exist
|
||||
expect(brandVariationDetails).to.deep.equal(
|
||||
this.mockedBrandVariationDetails
|
||||
)
|
||||
return done()
|
||||
}
|
||||
const brandVariationDetails =
|
||||
await this.BrandVariationsHandler.promises.getBrandVariationById('12')
|
||||
expect(brandVariationDetails).to.deep.equal(
|
||||
this.mockedBrandVariationDetails
|
||||
)
|
||||
})
|
||||
|
||||
it('should transform relative URLs in v1 absolute ones', function (done) {
|
||||
it('should transform relative URLs in v1 absolute ones', async function () {
|
||||
this.mockedBrandVariationDetails.logo_url = '/journal-logo.png'
|
||||
this.V1Api.request.callsArgWith(
|
||||
1,
|
||||
@@ -107,20 +94,16 @@ describe('BrandVariationsHandler', function () {
|
||||
{ statusCode: 200 },
|
||||
this.mockedBrandVariationDetails
|
||||
)
|
||||
return this.BrandVariationsHandler.getBrandVariationById(
|
||||
'12',
|
||||
(err, brandVariationDetails) => {
|
||||
expect(
|
||||
brandVariationDetails.logo_url.startsWith(
|
||||
this.settings.apis.v1.publicUrl
|
||||
)
|
||||
).to.be.true
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const brandVariationDetails =
|
||||
await this.BrandVariationsHandler.promises.getBrandVariationById('12')
|
||||
expect(
|
||||
brandVariationDetails.logo_url.startsWith(
|
||||
this.settings.apis.v1.publicUrl
|
||||
)
|
||||
).to.be.true
|
||||
})
|
||||
|
||||
it("should sanitize 'submit_button_html'", function (done) {
|
||||
it("should sanitize 'submit_button_html'", async function () {
|
||||
this.mockedBrandVariationDetails.submit_button_html =
|
||||
'<br class="break"/><strong style="color:#B39500">AGU Journal</strong><iframe>hello</iframe>'
|
||||
this.V1Api.request.callsArgWith(
|
||||
@@ -129,14 +112,10 @@ describe('BrandVariationsHandler', function () {
|
||||
{ statusCode: 200 },
|
||||
this.mockedBrandVariationDetails
|
||||
)
|
||||
return this.BrandVariationsHandler.getBrandVariationById(
|
||||
'12',
|
||||
(err, brandVariationDetails) => {
|
||||
expect(brandVariationDetails.submit_button_html).to.equal(
|
||||
'<br /><strong style="color:#B39500">AGU Journal</strong>hello'
|
||||
)
|
||||
return done()
|
||||
}
|
||||
const brandVariationDetails =
|
||||
await this.BrandVariationsHandler.promises.getBrandVariationById('12')
|
||||
expect(brandVariationDetails.submit_button_html).to.equal(
|
||||
'<br /><strong style="color:#B39500">AGU Journal</strong>hello'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -47,8 +47,8 @@ describe('ChatManager', function () {
|
||||
}))
|
||||
})
|
||||
|
||||
it('should inject a user object into messaged and resolved data', function (done) {
|
||||
return this.ChatManager.injectUserInfoIntoThreads(
|
||||
it('should inject a user object into messaged and resolved data', async function () {
|
||||
const threads = await this.ChatManager.promises.injectUserInfoIntoThreads(
|
||||
{
|
||||
thread1: {
|
||||
resolved: true,
|
||||
@@ -72,64 +72,56 @@ describe('ChatManager', function () {
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
(error, threads) => {
|
||||
expect(error).to.be.null
|
||||
expect(threads).to.deep.equal({
|
||||
thread1: {
|
||||
resolved: true,
|
||||
resolved_by_user_id: 'user_id_1',
|
||||
resolved_by_user: { formatted: 'user_1' },
|
||||
messages: [
|
||||
{
|
||||
user_id: 'user_id_1',
|
||||
user: { formatted: 'user_1' },
|
||||
content: 'foo',
|
||||
},
|
||||
{
|
||||
user_id: 'user_id_2',
|
||||
user: { formatted: 'user_2' },
|
||||
content: 'bar',
|
||||
},
|
||||
],
|
||||
},
|
||||
thread2: {
|
||||
messages: [
|
||||
{
|
||||
user_id: 'user_id_1',
|
||||
user: { formatted: 'user_1' },
|
||||
content: 'baz',
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
return done()
|
||||
}
|
||||
)
|
||||
|
||||
expect(threads).to.deep.equal({
|
||||
thread1: {
|
||||
resolved: true,
|
||||
resolved_by_user_id: 'user_id_1',
|
||||
resolved_by_user: { formatted: 'user_1' },
|
||||
messages: [
|
||||
{
|
||||
user_id: 'user_id_1',
|
||||
user: { formatted: 'user_1' },
|
||||
content: 'foo',
|
||||
},
|
||||
{
|
||||
user_id: 'user_id_2',
|
||||
user: { formatted: 'user_2' },
|
||||
content: 'bar',
|
||||
},
|
||||
],
|
||||
},
|
||||
thread2: {
|
||||
messages: [
|
||||
{
|
||||
user_id: 'user_id_1',
|
||||
user: { formatted: 'user_1' },
|
||||
content: 'baz',
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('should only need to look up each user once', function (done) {
|
||||
return this.ChatManager.injectUserInfoIntoThreads(
|
||||
[
|
||||
{
|
||||
messages: [
|
||||
{
|
||||
user_id: 'user_id_1',
|
||||
content: 'foo',
|
||||
},
|
||||
{
|
||||
user_id: 'user_id_1',
|
||||
content: 'bar',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
(error, threads) => {
|
||||
expect(error).to.be.null
|
||||
this.UserInfoManager.getPersonalInfo.calledOnce.should.equal(true)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
it('should only need to look up each user once', async function () {
|
||||
await this.ChatManager.promises.injectUserInfoIntoThreads([
|
||||
{
|
||||
messages: [
|
||||
{
|
||||
user_id: 'user_id_1',
|
||||
content: 'foo',
|
||||
},
|
||||
{
|
||||
user_id: 'user_id_1',
|
||||
content: 'bar',
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
this.UserInfoManager.getPersonalInfo.calledOnce.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -47,62 +47,53 @@ describe('ClsiFormatChecker', function () {
|
||||
])
|
||||
})
|
||||
|
||||
it('should call _checkDocsAreUnderSizeLimit and _checkForConflictingPaths', function (done) {
|
||||
it('should call _checkDocsAreUnderSizeLimit and _checkForConflictingPaths', async function () {
|
||||
this.ClsiFormatChecker._checkForConflictingPaths = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null)
|
||||
this.ClsiFormatChecker._checkDocsAreUnderSizeLimit = sinon
|
||||
.stub()
|
||||
.callsArgWith(1)
|
||||
return this.ClsiFormatChecker.checkRecoursesForProblems(
|
||||
this.resources,
|
||||
(err, problems) => {
|
||||
this.ClsiFormatChecker._checkForConflictingPaths.called.should.equal(
|
||||
true
|
||||
)
|
||||
this.ClsiFormatChecker._checkDocsAreUnderSizeLimit.called.should.equal(
|
||||
true
|
||||
)
|
||||
return done()
|
||||
}
|
||||
const problems =
|
||||
await this.ClsiFormatChecker.promises.checkRecoursesForProblems(
|
||||
this.resources
|
||||
)
|
||||
this.ClsiFormatChecker._checkForConflictingPaths.called.should.equal(true)
|
||||
this.ClsiFormatChecker._checkDocsAreUnderSizeLimit.called.should.equal(
|
||||
true
|
||||
)
|
||||
})
|
||||
|
||||
it('should remove undefined errors', function (done) {
|
||||
it('should remove undefined errors', async function () {
|
||||
this.ClsiFormatChecker._checkForConflictingPaths = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, [])
|
||||
this.ClsiFormatChecker._checkDocsAreUnderSizeLimit = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, {})
|
||||
return this.ClsiFormatChecker.checkRecoursesForProblems(
|
||||
this.resources,
|
||||
(err, problems) => {
|
||||
expect(problems).to.not.exist
|
||||
expect(problems).to.not.exist
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const problems =
|
||||
await this.ClsiFormatChecker.promises.checkRecoursesForProblems(
|
||||
this.resources
|
||||
)
|
||||
expect(problems).to.not.exist
|
||||
})
|
||||
|
||||
it('should keep populated arrays', function (done) {
|
||||
it('should keep populated arrays', async function () {
|
||||
this.ClsiFormatChecker._checkForConflictingPaths = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, [{ path: 'somewhere/main.tex' }])
|
||||
this.ClsiFormatChecker._checkDocsAreUnderSizeLimit = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, {})
|
||||
return this.ClsiFormatChecker.checkRecoursesForProblems(
|
||||
this.resources,
|
||||
(err, problems) => {
|
||||
problems.conflictedPaths[0].path.should.equal('somewhere/main.tex')
|
||||
expect(problems.sizeCheck).to.not.exist
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const problems =
|
||||
await this.ClsiFormatChecker.promises.checkRecoursesForProblems(
|
||||
this.resources
|
||||
)
|
||||
problems.conflictedPaths[0].path.should.equal('somewhere/main.tex')
|
||||
expect(problems.sizeCheck).to.not.exist
|
||||
})
|
||||
|
||||
it('should keep populated object', function (done) {
|
||||
it('should keep populated object', async function () {
|
||||
this.ClsiFormatChecker._checkForConflictingPaths = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, [])
|
||||
@@ -112,15 +103,13 @@ describe('ClsiFormatChecker', function () {
|
||||
resources: [{ 'a.tex': 'a.tex' }, { 'b.tex': 'b.tex' }],
|
||||
totalSize: 1000000,
|
||||
})
|
||||
return this.ClsiFormatChecker.checkRecoursesForProblems(
|
||||
this.resources,
|
||||
(err, problems) => {
|
||||
problems.sizeCheck.resources.length.should.equal(2)
|
||||
problems.sizeCheck.totalSize.should.equal(1000000)
|
||||
expect(problems.conflictedPaths).to.not.exist
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const problems =
|
||||
await this.ClsiFormatChecker.promises.checkRecoursesForProblems(
|
||||
this.resources
|
||||
)
|
||||
problems.sizeCheck.resources.length.should.equal(2)
|
||||
problems.sizeCheck.totalSize.should.equal(1000000)
|
||||
expect(problems.conflictedPaths).to.not.exist
|
||||
})
|
||||
|
||||
describe('_checkForConflictingPaths', function () {
|
||||
@@ -136,56 +125,50 @@ describe('ClsiFormatChecker', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('should flag up when a nested file has folder with same subpath as file elsewhere', function (done) {
|
||||
it('should flag up when a nested file has folder with same subpath as file elsewhere', async function () {
|
||||
this.resources.push({
|
||||
path: 'stuff/image',
|
||||
url: 'http://somwhere.com',
|
||||
})
|
||||
|
||||
return this.ClsiFormatChecker._checkForConflictingPaths(
|
||||
this.resources,
|
||||
(err, conflictPathErrors) => {
|
||||
conflictPathErrors.length.should.equal(1)
|
||||
conflictPathErrors[0].path.should.equal('stuff/image')
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const conflictPathErrors =
|
||||
await this.ClsiFormatChecker.promises._checkForConflictingPaths(
|
||||
this.resources
|
||||
)
|
||||
conflictPathErrors.length.should.equal(1)
|
||||
conflictPathErrors[0].path.should.equal('stuff/image')
|
||||
})
|
||||
|
||||
it('should flag up when a root level file has folder with same subpath as file elsewhere', function (done) {
|
||||
it('should flag up when a root level file has folder with same subpath as file elsewhere', async function () {
|
||||
this.resources.push({
|
||||
path: 'stuff',
|
||||
content: 'other stuff',
|
||||
})
|
||||
|
||||
return this.ClsiFormatChecker._checkForConflictingPaths(
|
||||
this.resources,
|
||||
(err, conflictPathErrors) => {
|
||||
conflictPathErrors.length.should.equal(1)
|
||||
conflictPathErrors[0].path.should.equal('stuff')
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const conflictPathErrors =
|
||||
await this.ClsiFormatChecker.promises._checkForConflictingPaths(
|
||||
this.resources
|
||||
)
|
||||
conflictPathErrors.length.should.equal(1)
|
||||
conflictPathErrors[0].path.should.equal('stuff')
|
||||
})
|
||||
|
||||
it('should not flag up when the file is a substring of a path', function (done) {
|
||||
it('should not flag up when the file is a substring of a path', async function () {
|
||||
this.resources.push({
|
||||
path: 'stuf',
|
||||
content: 'other stuff',
|
||||
})
|
||||
|
||||
return this.ClsiFormatChecker._checkForConflictingPaths(
|
||||
this.resources,
|
||||
(err, conflictPathErrors) => {
|
||||
conflictPathErrors.length.should.equal(0)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const conflictPathErrors =
|
||||
await this.ClsiFormatChecker.promises._checkForConflictingPaths(
|
||||
this.resources
|
||||
)
|
||||
conflictPathErrors.length.should.equal(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('_checkDocsAreUnderSizeLimit', function () {
|
||||
it('should error when there is more than 5mb of data', function (done) {
|
||||
it('should error when there is more than 5mb of data', async function () {
|
||||
this.resources.push({
|
||||
path: 'massive.tex',
|
||||
content: 'hello world'.repeat(833333), // over 5mb limit
|
||||
@@ -198,19 +181,17 @@ describe('ClsiFormatChecker', function () {
|
||||
})
|
||||
}
|
||||
|
||||
return this.ClsiFormatChecker._checkDocsAreUnderSizeLimit(
|
||||
this.resources,
|
||||
(err, sizeError) => {
|
||||
sizeError.totalSize.should.equal(16 + 833333 * 11) // 16 is for earlier resources
|
||||
sizeError.resources.length.should.equal(10)
|
||||
sizeError.resources[0].path.should.equal('massive.tex')
|
||||
sizeError.resources[0].size.should.equal(833333 * 11)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const sizeError =
|
||||
await this.ClsiFormatChecker.promises._checkDocsAreUnderSizeLimit(
|
||||
this.resources
|
||||
)
|
||||
sizeError.totalSize.should.equal(16 + 833333 * 11) // 16 is for earlier resources
|
||||
sizeError.resources.length.should.equal(10)
|
||||
sizeError.resources[0].path.should.equal('massive.tex')
|
||||
sizeError.resources[0].size.should.equal(833333 * 11)
|
||||
})
|
||||
|
||||
it('should return nothing when project is correct size', function (done) {
|
||||
it('should return nothing when project is correct size', async function () {
|
||||
this.resources.push({
|
||||
path: 'massive.tex',
|
||||
content: 'x'.repeat(2 * 1000 * 1000),
|
||||
@@ -223,13 +204,11 @@ describe('ClsiFormatChecker', function () {
|
||||
})
|
||||
}
|
||||
|
||||
return this.ClsiFormatChecker._checkDocsAreUnderSizeLimit(
|
||||
this.resources,
|
||||
(err, sizeError) => {
|
||||
expect(sizeError).to.not.exist
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const sizeError =
|
||||
await this.ClsiFormatChecker.promises._checkDocsAreUnderSizeLimit(
|
||||
this.resources
|
||||
)
|
||||
expect(sizeError).to.not.exist
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -139,7 +139,7 @@ describe('CompileManager', function () {
|
||||
})
|
||||
|
||||
describe('when the project has been recently compiled', function () {
|
||||
it('should return', function (done) {
|
||||
it('should return', async function () {
|
||||
this.CompileManager._checkIfAutoCompileLimitHasBeenHit = async (
|
||||
isAutoCompile,
|
||||
compileGroup
|
||||
@@ -147,32 +147,27 @@ describe('CompileManager', function () {
|
||||
this.CompileManager._checkIfRecentlyCompiled = sinon
|
||||
.stub()
|
||||
.resolves(true)
|
||||
this.CompileManager.promises
|
||||
.compile(this.project_id, this.user_id, {})
|
||||
.then(({ status }) => {
|
||||
status.should.equal('too-recently-compiled')
|
||||
done()
|
||||
})
|
||||
.catch(error => {
|
||||
// Catch any errors and fail the test
|
||||
true.should.equal(false)
|
||||
done(error)
|
||||
})
|
||||
const { status } = await this.CompileManager.promises.compile(
|
||||
this.project_id,
|
||||
this.user_id,
|
||||
{}
|
||||
)
|
||||
status.should.equal('too-recently-compiled')
|
||||
})
|
||||
})
|
||||
|
||||
describe('should check the rate limit', function () {
|
||||
it('should return', function (done) {
|
||||
it('should return', async function () {
|
||||
this.CompileManager._checkIfAutoCompileLimitHasBeenHit = sinon
|
||||
.stub()
|
||||
.resolves(false)
|
||||
this.CompileManager.promises
|
||||
.compile(this.project_id, this.user_id, {})
|
||||
.then(({ status }) => {
|
||||
expect(status).to.equal('autocompile-backoff')
|
||||
done()
|
||||
})
|
||||
.catch(err => done(err))
|
||||
const { status } = await this.CompileManager.promises.compile(
|
||||
this.project_id,
|
||||
this.user_id,
|
||||
{}
|
||||
)
|
||||
|
||||
expect(status).to.equal('autocompile-backoff')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -250,15 +245,12 @@ describe('CompileManager', function () {
|
||||
beforeEach(function () {
|
||||
this.features.compileGroup = 'priority'
|
||||
})
|
||||
it('should return the default class', function (done) {
|
||||
this.CompileManager.getProjectCompileLimits(
|
||||
this.project_id,
|
||||
(err, { compileBackendClass }) => {
|
||||
if (err) return done(err)
|
||||
expect(compileBackendClass).to.equal('c2d')
|
||||
done()
|
||||
}
|
||||
)
|
||||
it('should return the default class', async function () {
|
||||
const { compileBackendClass } =
|
||||
await this.CompileManager.promises.getProjectCompileLimits(
|
||||
this.project_id
|
||||
)
|
||||
expect(compileBackendClass).to.equal('c2d')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
/* eslint-disable
|
||||
n/handle-callback-err,
|
||||
max-len,
|
||||
no-return-assign,
|
||||
*/
|
||||
// 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
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const sinon = require('sinon')
|
||||
const { expect } = require('chai')
|
||||
@@ -23,158 +11,143 @@ describe('CooldownManager', function () {
|
||||
this.projectId = 'abcdefg'
|
||||
this.rclient = { set: sinon.stub(), get: sinon.stub() }
|
||||
this.RedisWrapper = { client: () => this.rclient }
|
||||
return (this.CooldownManager = SandboxedModule.require(modulePath, {
|
||||
this.CooldownManager = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'../../infrastructure/RedisWrapper': this.RedisWrapper,
|
||||
},
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
describe('_buildKey', function () {
|
||||
it('should build a properly formatted redis key', function () {
|
||||
return expect(this.CooldownManager._buildKey('ABC')).to.equal(
|
||||
'Cooldown:{ABC}'
|
||||
)
|
||||
expect(this.CooldownManager._buildKey('ABC')).to.equal('Cooldown:{ABC}')
|
||||
})
|
||||
})
|
||||
|
||||
describe('isProjectOnCooldown', function () {
|
||||
beforeEach(function () {
|
||||
return (this.call = cb => {
|
||||
return this.CooldownManager.isProjectOnCooldown(this.projectId, cb)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when project is on cooldown', function () {
|
||||
beforeEach(function () {
|
||||
return (this.rclient.get = sinon.stub().callsArgWith(1, null, '1'))
|
||||
this.rclient.get = sinon.stub().callsArgWith(1, null, '1')
|
||||
})
|
||||
|
||||
it('should fetch key from redis', function (done) {
|
||||
return this.call((err, result) => {
|
||||
this.rclient.get.callCount.should.equal(1)
|
||||
this.rclient.get.calledWith('Cooldown:{abcdefg}').should.equal(true)
|
||||
return done()
|
||||
})
|
||||
it('should fetch key from redis', async function () {
|
||||
await this.CooldownManager.promises.isProjectOnCooldown(this.projectId)
|
||||
this.rclient.get.callCount.should.equal(1)
|
||||
this.rclient.get.calledWith('Cooldown:{abcdefg}').should.equal(true)
|
||||
})
|
||||
|
||||
it('should not produce an error', function (done) {
|
||||
return this.call((err, result) => {
|
||||
expect(err).to.equal(null)
|
||||
return done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should produce a true result', function (done) {
|
||||
return this.call((err, result) => {
|
||||
expect(result).to.equal(true)
|
||||
return done()
|
||||
})
|
||||
it('should produce a true result', async function () {
|
||||
const result = await this.CooldownManager.promises.isProjectOnCooldown(
|
||||
this.projectId
|
||||
)
|
||||
expect(result).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when project is not on cooldown', function () {
|
||||
beforeEach(function () {
|
||||
return (this.rclient.get = sinon.stub().callsArgWith(1, null, null))
|
||||
this.rclient.get = sinon.stub().callsArgWith(1, null, null)
|
||||
})
|
||||
|
||||
it('should fetch key from redis', function (done) {
|
||||
return this.call((err, result) => {
|
||||
this.rclient.get.callCount.should.equal(1)
|
||||
this.rclient.get.calledWith('Cooldown:{abcdefg}').should.equal(true)
|
||||
return done()
|
||||
})
|
||||
it('should fetch key from redis', async function () {
|
||||
await this.CooldownManager.promises.isProjectOnCooldown(this.projectId)
|
||||
this.rclient.get.callCount.should.equal(1)
|
||||
this.rclient.get.calledWith('Cooldown:{abcdefg}').should.equal(true)
|
||||
})
|
||||
|
||||
it('should not produce an error', function (done) {
|
||||
return this.call((err, result) => {
|
||||
expect(err).to.equal(null)
|
||||
return done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should produce a false result', function (done) {
|
||||
return this.call((err, result) => {
|
||||
expect(result).to.equal(false)
|
||||
return done()
|
||||
})
|
||||
it('should produce a false result', async function () {
|
||||
const result = await this.CooldownManager.promises.isProjectOnCooldown(
|
||||
this.projectId
|
||||
)
|
||||
expect(result).to.equal(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when rclient.get produces an error', function () {
|
||||
beforeEach(function () {
|
||||
return (this.rclient.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, new Error('woops')))
|
||||
this.rclient.get = sinon.stub().callsArgWith(1, new Error('woops'))
|
||||
})
|
||||
|
||||
it('should fetch key from redis', function (done) {
|
||||
return this.call((err, result) => {
|
||||
this.rclient.get.callCount.should.equal(1)
|
||||
this.rclient.get.calledWith('Cooldown:{abcdefg}').should.equal(true)
|
||||
return done()
|
||||
})
|
||||
it('should fetch key from redis', async function () {
|
||||
try {
|
||||
await this.CooldownManager.promises.isProjectOnCooldown(
|
||||
this.projectId
|
||||
)
|
||||
} catch {
|
||||
// ignore errors - expected
|
||||
}
|
||||
this.rclient.get.callCount.should.equal(1)
|
||||
this.rclient.get.calledWith('Cooldown:{abcdefg}').should.equal(true)
|
||||
})
|
||||
|
||||
it('should produce an error', function (done) {
|
||||
return this.call((err, result) => {
|
||||
expect(err).to.not.equal(null)
|
||||
expect(err).to.be.instanceof(Error)
|
||||
return done()
|
||||
})
|
||||
it('should produce an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.CooldownManager.promises.isProjectOnCooldown(
|
||||
this.projectId
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('putProjectOnCooldown', function () {
|
||||
beforeEach(function () {
|
||||
return (this.call = cb => {
|
||||
return this.CooldownManager.putProjectOnCooldown(this.projectId, cb)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when rclient.set does not produce an error', function () {
|
||||
beforeEach(function () {
|
||||
return (this.rclient.set = sinon.stub().callsArgWith(4, null))
|
||||
this.rclient.set = sinon.stub().callsArgWith(4, null)
|
||||
})
|
||||
|
||||
it('should set a key in redis', function (done) {
|
||||
return this.call(err => {
|
||||
this.rclient.set.callCount.should.equal(1)
|
||||
this.rclient.set.calledWith('Cooldown:{abcdefg}').should.equal(true)
|
||||
return done()
|
||||
})
|
||||
it('should set a key in redis', async function () {
|
||||
await this.CooldownManager.promises.putProjectOnCooldown(this.projectId)
|
||||
this.rclient.set.callCount.should.equal(1)
|
||||
this.rclient.set.calledWith('Cooldown:{abcdefg}').should.equal(true)
|
||||
})
|
||||
|
||||
it('should not produce an error', function (done) {
|
||||
return this.call(err => {
|
||||
expect(err).to.equal(null)
|
||||
return done()
|
||||
})
|
||||
it('should not produce an error', async function () {
|
||||
let error
|
||||
try {
|
||||
await this.CooldownManager.promises.putProjectOnCooldown(
|
||||
this.projectId
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
expect(error).not.to.exist
|
||||
})
|
||||
})
|
||||
|
||||
describe('when rclient.set produces an error', function () {
|
||||
beforeEach(function () {
|
||||
return (this.rclient.set = sinon
|
||||
.stub()
|
||||
.callsArgWith(4, new Error('woops')))
|
||||
this.rclient.set = sinon.stub().callsArgWith(4, new Error('woops'))
|
||||
})
|
||||
|
||||
it('should set a key in redis', function (done) {
|
||||
return this.call(err => {
|
||||
this.rclient.set.callCount.should.equal(1)
|
||||
this.rclient.set.calledWith('Cooldown:{abcdefg}').should.equal(true)
|
||||
return done()
|
||||
})
|
||||
it('should set a key in redis', async function () {
|
||||
try {
|
||||
await this.CooldownManager.promises.putProjectOnCooldown(
|
||||
this.projectId
|
||||
)
|
||||
} catch {
|
||||
// ignore errors - expected
|
||||
}
|
||||
this.rclient.set.callCount.should.equal(1)
|
||||
this.rclient.set.calledWith('Cooldown:{abcdefg}').should.equal(true)
|
||||
})
|
||||
|
||||
it('produce an error', function (done) {
|
||||
return this.call(err => {
|
||||
expect(err).to.not.equal(null)
|
||||
expect(err).to.be.instanceof(Error)
|
||||
return done()
|
||||
})
|
||||
it('produce an error', async function () {
|
||||
let error
|
||||
try {
|
||||
await this.CooldownManager.promises.putProjectOnCooldown(
|
||||
this.projectId
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const sinon = require('sinon')
|
||||
const modulePath = '../../../../app/src/Features/Docstore/DocstoreManager'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const { expect } = require('chai')
|
||||
const Errors = require('../../../../app/src/Features/Errors/Errors')
|
||||
const tk = require('timekeeper')
|
||||
|
||||
@@ -26,7 +27,6 @@ describe('DocstoreManager', function () {
|
||||
|
||||
this.project_id = 'project-id-123'
|
||||
this.doc_id = 'doc-id-123'
|
||||
this.callback = sinon.stub()
|
||||
})
|
||||
|
||||
describe('deleteDoc', function () {
|
||||
@@ -39,16 +39,15 @@ describe('DocstoreManager', function () {
|
||||
tk.reset()
|
||||
})
|
||||
|
||||
beforeEach(function () {
|
||||
beforeEach(async function () {
|
||||
this.request.patch = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 }, '')
|
||||
this.DocstoreManager.deleteDoc(
|
||||
await this.DocstoreManager.promises.deleteDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
'wombat.tex',
|
||||
new Date(),
|
||||
this.callback
|
||||
new Date()
|
||||
)
|
||||
})
|
||||
|
||||
@@ -61,10 +60,6 @@ describe('DocstoreManager', function () {
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback without an error', function () {
|
||||
this.callback.calledWith(null).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a failed response code', function () {
|
||||
@@ -72,28 +67,27 @@ describe('DocstoreManager', function () {
|
||||
this.request.patch = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
this.DocstoreManager.deleteDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
'main.tex',
|
||||
new Date(),
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
.and(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
)
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.DocstoreManager.promises.deleteDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
'main.tex',
|
||||
new Date()
|
||||
)
|
||||
.should.equal(true)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -102,28 +96,26 @@ describe('DocstoreManager', function () {
|
||||
this.request.patch = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 404 }, '')
|
||||
this.DocstoreManager.deleteDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
'main.tex',
|
||||
new Date(),
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Errors.NotFoundError)
|
||||
.and(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'tried to delete doc not in docstore'
|
||||
)
|
||||
)
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
try {
|
||||
await this.DocstoreManager.promises.deleteDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
'main.tex',
|
||||
new Date()
|
||||
)
|
||||
.should.equal(true)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
'tried to delete doc not in docstore'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -137,8 +129,8 @@ describe('DocstoreManager', function () {
|
||||
this.modified = true
|
||||
})
|
||||
|
||||
describe('with a successful response code', function () {
|
||||
beforeEach(function () {
|
||||
describe('with a successful response code', async function () {
|
||||
beforeEach(async function () {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(
|
||||
@@ -147,13 +139,12 @@ describe('DocstoreManager', function () {
|
||||
{ statusCode: 204 },
|
||||
{ modified: this.modified, rev: this.rev }
|
||||
)
|
||||
this.DocstoreManager.updateDoc(
|
||||
this.updateDocResponse = await this.DocstoreManager.promises.updateDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.lines,
|
||||
this.version,
|
||||
this.ranges,
|
||||
this.callback
|
||||
this.ranges
|
||||
)
|
||||
})
|
||||
|
||||
@@ -171,10 +162,12 @@ describe('DocstoreManager', function () {
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with the modified status and revision', function () {
|
||||
this.callback
|
||||
.calledWith(null, this.modified, this.rev)
|
||||
.should.equal(true)
|
||||
it('should return the modified status and revision', function () {
|
||||
expect(this.updateDocResponse).to.haveOwnProperty(
|
||||
'modified',
|
||||
this.modified
|
||||
)
|
||||
expect(this.updateDocResponse).to.haveOwnProperty('rev', this.rev)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -183,29 +176,28 @@ describe('DocstoreManager', function () {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
this.DocstoreManager.updateDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.lines,
|
||||
this.version,
|
||||
this.ranges,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
.and(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
)
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.DocstoreManager.promises.updateDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
this.lines,
|
||||
this.version,
|
||||
this.ranges
|
||||
)
|
||||
.should.equal(true)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -221,11 +213,14 @@ describe('DocstoreManager', function () {
|
||||
})
|
||||
|
||||
describe('with a successful response code', function () {
|
||||
beforeEach(function () {
|
||||
beforeEach(async function () {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 }, this.doc)
|
||||
this.DocstoreManager.getDoc(this.project_id, this.doc_id, this.callback)
|
||||
this.getDocResponse = await this.DocstoreManager.promises.getDoc(
|
||||
this.project_id,
|
||||
this.doc_id
|
||||
)
|
||||
})
|
||||
|
||||
it('should get the doc from the docstore api', function () {
|
||||
@@ -236,10 +231,13 @@ describe('DocstoreManager', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the callback with the lines, version and rev', function () {
|
||||
this.callback
|
||||
.calledWith(null, this.lines, this.rev, this.version, this.ranges)
|
||||
.should.equal(true)
|
||||
it('should resolve with the lines, version and rev', function () {
|
||||
expect(this.getDocResponse).to.eql({
|
||||
lines: this.lines,
|
||||
rev: this.rev,
|
||||
version: this.version,
|
||||
ranges: this.ranges,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -248,35 +246,37 @@ describe('DocstoreManager', function () {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
this.DocstoreManager.getDoc(this.project_id, this.doc_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
.and(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
)
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.DocstoreManager.promises.getDoc(
|
||||
this.project_id,
|
||||
this.doc_id
|
||||
)
|
||||
.should.equal(true)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with include_deleted=true', function () {
|
||||
beforeEach(function () {
|
||||
beforeEach(async function () {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 }, this.doc)
|
||||
this.DocstoreManager.getDoc(
|
||||
this.getDocResponse = await this.DocstoreManager.promises.getDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
{ include_deleted: true },
|
||||
this.callback
|
||||
{ include_deleted: true }
|
||||
)
|
||||
})
|
||||
|
||||
@@ -289,23 +289,27 @@ describe('DocstoreManager', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the callback with the lines, version and rev', function () {
|
||||
this.callback
|
||||
.calledWith(null, this.lines, this.rev, this.version, this.ranges)
|
||||
.should.equal(true)
|
||||
it('should resolve with the lines, version and rev', function () {
|
||||
expect(this.getDocResponse).to.eql({
|
||||
lines: this.lines,
|
||||
rev: this.rev,
|
||||
version: this.version,
|
||||
ranges: this.ranges,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with peek=true', function () {
|
||||
beforeEach(function () {
|
||||
beforeEach(async function () {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 }, this.doc)
|
||||
this.DocstoreManager.getDoc(
|
||||
await this.DocstoreManager.promises.getDoc(
|
||||
this.project_id,
|
||||
this.doc_id,
|
||||
{ peek: true },
|
||||
this.callback
|
||||
{
|
||||
peek: true,
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
@@ -323,24 +327,30 @@ describe('DocstoreManager', function () {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 404 }, '')
|
||||
this.DocstoreManager.getDoc(this.project_id, this.doc_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Errors.NotFoundError)
|
||||
.and(sinon.match.has('message', 'doc not found in docstore'))
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.DocstoreManager.promises.getDoc(
|
||||
this.project_id,
|
||||
this.doc_id
|
||||
)
|
||||
.should.equal(true)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Errors.NotFoundError)
|
||||
expect(error).to.have.property('message', 'doc not found in docstore')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getAllDocs', function () {
|
||||
describe('with a successful response code', function () {
|
||||
beforeEach(function () {
|
||||
let getAllDocsResult
|
||||
beforeEach(async function () {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(
|
||||
@@ -349,7 +359,9 @@ describe('DocstoreManager', function () {
|
||||
{ statusCode: 204 },
|
||||
(this.docs = [{ _id: 'mock-doc-id' }])
|
||||
)
|
||||
this.DocstoreManager.getAllDocs(this.project_id, this.callback)
|
||||
getAllDocsResult = await this.DocstoreManager.promises.getAllDocs(
|
||||
this.project_id
|
||||
)
|
||||
})
|
||||
|
||||
it('should get all the project docs in the docstore api', function () {
|
||||
@@ -362,8 +374,8 @@ describe('DocstoreManager', function () {
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with the docs', function () {
|
||||
this.callback.calledWith(null, this.docs).should.equal(true)
|
||||
it('should return the docs', function () {
|
||||
expect(getAllDocsResult).to.eql(this.docs)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -372,35 +384,36 @@ describe('DocstoreManager', function () {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
this.DocstoreManager.getAllDocs(this.project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
.and(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
)
|
||||
)
|
||||
.should.equal(true)
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.DocstoreManager.promises.getAllDocs(this.project_id)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getAllDeletedDocs', function () {
|
||||
describe('with a successful response code', function () {
|
||||
beforeEach(function (done) {
|
||||
this.callback.callsFake(done)
|
||||
let getAllDeletedDocsResponse
|
||||
beforeEach(async function () {
|
||||
this.docs = [{ _id: 'mock-doc-id', name: 'foo.tex' }]
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 200 }, this.docs)
|
||||
this.DocstoreManager.getAllDeletedDocs(this.project_id, this.callback)
|
||||
getAllDeletedDocsResponse =
|
||||
await this.DocstoreManager.promises.getAllDeletedDocs(this.project_id)
|
||||
})
|
||||
|
||||
it('should get all the project docs in the docstore api', function () {
|
||||
@@ -411,48 +424,52 @@ describe('DocstoreManager', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the callback with the docs', function () {
|
||||
this.callback.should.have.been.calledWith(null, this.docs)
|
||||
it('should resolve with the docs', function () {
|
||||
expect(getAllDeletedDocsResponse).to.eql(this.docs)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with an error', function () {
|
||||
beforeEach(function (done) {
|
||||
this.callback.callsFake(() => done())
|
||||
beforeEach(async function () {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, new Error('connect failed'))
|
||||
this.DocstoreManager.getAllDocs(this.project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback.should.have.been.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
.and(sinon.match.has('message', 'connect failed'))
|
||||
)
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.DocstoreManager.promises.getAllDocs(this.project_id)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property('message', 'connect failed')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a failed response code', function () {
|
||||
beforeEach(function (done) {
|
||||
this.callback.callsFake(() => done())
|
||||
beforeEach(function () {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 })
|
||||
this.DocstoreManager.getAllDocs(this.project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback.should.have.been.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
.and(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
)
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.DocstoreManager.promises.getAllDocs(this.project_id)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -460,7 +477,8 @@ describe('DocstoreManager', function () {
|
||||
|
||||
describe('getAllRanges', function () {
|
||||
describe('with a successful response code', function () {
|
||||
beforeEach(function () {
|
||||
let getAllRangesResult
|
||||
beforeEach(async function () {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(
|
||||
@@ -469,7 +487,9 @@ describe('DocstoreManager', function () {
|
||||
{ statusCode: 204 },
|
||||
(this.docs = [{ _id: 'mock-doc-id', ranges: 'mock-ranges' }])
|
||||
)
|
||||
this.DocstoreManager.getAllRanges(this.project_id, this.callback)
|
||||
getAllRangesResult = await this.DocstoreManager.promises.getAllRanges(
|
||||
this.project_id
|
||||
)
|
||||
})
|
||||
|
||||
it('should get all the project doc ranges in the docstore api', function () {
|
||||
@@ -482,8 +502,8 @@ describe('DocstoreManager', function () {
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with the docs', function () {
|
||||
this.callback.calledWith(null, this.docs).should.equal(true)
|
||||
it('should return the docs', async function () {
|
||||
expect(getAllRangesResult).to.eql(this.docs)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -492,22 +512,22 @@ describe('DocstoreManager', function () {
|
||||
this.request.get = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
this.DocstoreManager.getAllRanges(this.project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
.and(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
)
|
||||
)
|
||||
.should.equal(true)
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.DocstoreManager.promises.getAllRanges(this.project_id)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -518,11 +538,12 @@ describe('DocstoreManager', function () {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 })
|
||||
this.DocstoreManager.archiveProject(this.project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback', function () {
|
||||
this.callback.called.should.equal(true)
|
||||
it('should resolve', async function () {
|
||||
await expect(
|
||||
this.DocstoreManager.promises.archiveProject(this.project_id)
|
||||
).to.eventually.be.fulfilled
|
||||
})
|
||||
})
|
||||
|
||||
@@ -531,22 +552,22 @@ describe('DocstoreManager', function () {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 })
|
||||
this.DocstoreManager.archiveProject(this.project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
.and(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
)
|
||||
)
|
||||
.should.equal(true)
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.DocstoreManager.promises.archiveProject(this.project_id)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -557,11 +578,12 @@ describe('DocstoreManager', function () {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 })
|
||||
this.DocstoreManager.unarchiveProject(this.project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback', function () {
|
||||
this.callback.called.should.equal(true)
|
||||
it('should resolve', async function () {
|
||||
await expect(
|
||||
this.DocstoreManager.promises.unarchiveProject(this.project_id)
|
||||
).to.eventually.be.fulfilled
|
||||
})
|
||||
})
|
||||
|
||||
@@ -570,22 +592,22 @@ describe('DocstoreManager', function () {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 })
|
||||
this.DocstoreManager.unarchiveProject(this.project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
.and(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
)
|
||||
)
|
||||
.should.equal(true)
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.DocstoreManager.promises.unarchiveProject(this.project_id)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -596,11 +618,12 @@ describe('DocstoreManager', function () {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 })
|
||||
this.DocstoreManager.destroyProject(this.project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback', function () {
|
||||
this.callback.called.should.equal(true)
|
||||
it('should resolve', async function () {
|
||||
await expect(
|
||||
this.DocstoreManager.promises.destroyProject(this.project_id)
|
||||
).to.eventually.be.fulfilled
|
||||
})
|
||||
})
|
||||
|
||||
@@ -609,22 +632,22 @@ describe('DocstoreManager', function () {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 })
|
||||
this.DocstoreManager.destroyProject(this.project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
.and(
|
||||
sinon.match.has(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
)
|
||||
)
|
||||
.should.equal(true)
|
||||
it('should reject with an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.DocstoreManager.promises.destroyProject(this.project_id)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
'docstore api responded with non-success code: 500'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -95,7 +95,7 @@ describe('FileStoreHandler', function () {
|
||||
this.request.returns(this.writeStream)
|
||||
})
|
||||
|
||||
it('should get the project details', function (done) {
|
||||
it('should get the project details', async function () {
|
||||
this.fs.createReadStream.returns({
|
||||
pipe() {},
|
||||
on(type, cb) {
|
||||
@@ -104,20 +104,17 @@ describe('FileStoreHandler', function () {
|
||||
}
|
||||
},
|
||||
})
|
||||
this.handler.uploadFileFromDisk(
|
||||
await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
() => {
|
||||
this.ProjectDetailsHandler.getDetails
|
||||
.calledWith(this.projectId)
|
||||
.should.equal(true)
|
||||
done()
|
||||
}
|
||||
this.fsPath
|
||||
)
|
||||
this.ProjectDetailsHandler.getDetails
|
||||
.calledWith(this.projectId)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should compute the file hash', function (done) {
|
||||
it('should compute the file hash', async function () {
|
||||
this.fs.createReadStream.returns({
|
||||
pipe() {},
|
||||
on(type, cb) {
|
||||
@@ -126,21 +123,18 @@ describe('FileStoreHandler', function () {
|
||||
}
|
||||
},
|
||||
})
|
||||
this.handler.uploadFileFromDisk(
|
||||
await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
() => {
|
||||
this.FileHashManager.computeHash
|
||||
.calledWith(this.fsPath)
|
||||
.should.equal(true)
|
||||
done()
|
||||
}
|
||||
this.fsPath
|
||||
)
|
||||
this.FileHashManager.computeHash
|
||||
.calledWith(this.fsPath)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
describe('when project-history-blobs feature is enabled', function () {
|
||||
it('should upload the file to the history store as a blob', function (done) {
|
||||
it('should upload the file to the history store as a blob', async function () {
|
||||
this.fs.createReadStream.returns({
|
||||
pipe() {},
|
||||
on(type, cb) {
|
||||
@@ -150,26 +144,23 @@ describe('FileStoreHandler', function () {
|
||||
},
|
||||
})
|
||||
this.Features.hasFeature.withArgs('project-history-blobs').returns(true)
|
||||
this.handler.uploadFileFromDisk(
|
||||
await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
() => {
|
||||
this.HistoryManager.uploadBlobFromDisk
|
||||
.calledWith(
|
||||
this.historyId,
|
||||
this.hashValue,
|
||||
this.fileSize,
|
||||
this.fsPath
|
||||
)
|
||||
.should.equal(true)
|
||||
done()
|
||||
}
|
||||
this.fsPath
|
||||
)
|
||||
this.HistoryManager.uploadBlobFromDisk
|
||||
.calledWith(
|
||||
this.historyId,
|
||||
this.hashValue,
|
||||
this.fileSize,
|
||||
this.fsPath
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
describe('when project-history-blobs feature is disabled', function () {
|
||||
it('should not upload the file to the history store as a blob', function (done) {
|
||||
it('should not upload the file to the history store as a blob', async function () {
|
||||
this.fs.createReadStream.returns({
|
||||
pipe() {},
|
||||
on(type, cb) {
|
||||
@@ -178,15 +169,12 @@ describe('FileStoreHandler', function () {
|
||||
}
|
||||
},
|
||||
})
|
||||
this.handler.uploadFileFromDisk(
|
||||
await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
() => {
|
||||
this.HistoryManager.uploadBlobFromDisk.called.should.equal(false)
|
||||
done()
|
||||
}
|
||||
this.fsPath
|
||||
)
|
||||
this.HistoryManager.uploadBlobFromDisk.called.should.equal(false)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -214,71 +202,63 @@ describe('FileStoreHandler', function () {
|
||||
)
|
||||
})
|
||||
|
||||
it('should pipe the read stream to request', function (done) {
|
||||
it('should pipe the read stream to request', function () {
|
||||
this.request.returns(this.writeStream)
|
||||
this.fs.createReadStream.returns({
|
||||
on(type, cb) {
|
||||
if (type === 'open') {
|
||||
cb()
|
||||
}
|
||||
},
|
||||
pipe: o => {
|
||||
this.writeStream.should.equal(o)
|
||||
done()
|
||||
},
|
||||
return new Promise((resolve, reject) => {
|
||||
this.fs.createReadStream.returns({
|
||||
on(type, cb) {
|
||||
if (type === 'open') {
|
||||
cb()
|
||||
}
|
||||
},
|
||||
pipe: o => {
|
||||
this.writeStream.should.equal(o)
|
||||
resolve()
|
||||
},
|
||||
})
|
||||
this.handler.promises
|
||||
.uploadFileFromDisk(this.projectId, this.fileArgs, this.fsPath)
|
||||
.catch(reject)
|
||||
})
|
||||
this.handler.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
() => {}
|
||||
)
|
||||
})
|
||||
|
||||
it('should pass the correct options to request', function (done) {
|
||||
it('should pass the correct options to request', async function () {
|
||||
const fileUrl = this.getFileUrl(this.projectId, this.fileId)
|
||||
this.fs.createReadStream.returns({
|
||||
pipe() {},
|
||||
on(type, cb) {
|
||||
pipe: sinon.stub(),
|
||||
on: sinon.stub((type, cb) => {
|
||||
if (type === 'open') {
|
||||
cb()
|
||||
}
|
||||
},
|
||||
}),
|
||||
})
|
||||
this.handler.uploadFileFromDisk(
|
||||
await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
() => {
|
||||
this.request.args[0][0].method.should.equal('post')
|
||||
this.request.args[0][0].uri.should.equal(fileUrl)
|
||||
done()
|
||||
}
|
||||
this.fsPath
|
||||
)
|
||||
this.request.args[0][0].method.should.equal('post')
|
||||
this.request.args[0][0].uri.should.equal(fileUrl)
|
||||
})
|
||||
|
||||
it('should callback with the url and fileRef', function (done) {
|
||||
it('should resolve with the url and fileRef', async function () {
|
||||
const fileUrl = this.getFileUrl(this.projectId, this.fileId)
|
||||
this.fs.createReadStream.returns({
|
||||
pipe() {},
|
||||
on(type, cb) {
|
||||
pipe: sinon.stub(),
|
||||
on: sinon.stub((type, cb) => {
|
||||
if (type === 'open') {
|
||||
cb()
|
||||
}
|
||||
},
|
||||
}),
|
||||
})
|
||||
this.handler.uploadFileFromDisk(
|
||||
const { url, fileRef } = await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
(err, url, fileRef) => {
|
||||
expect(err).to.not.exist
|
||||
expect(url).to.equal(fileUrl)
|
||||
expect(fileRef._id).to.equal(this.fileId)
|
||||
expect(fileRef.hash).to.equal(this.hashValue)
|
||||
done()
|
||||
}
|
||||
this.fsPath
|
||||
)
|
||||
expect(url).to.equal(fileUrl)
|
||||
expect(fileRef._id).to.equal(this.fileId)
|
||||
expect(fileRef.hash).to.equal(this.hashValue)
|
||||
})
|
||||
describe('when upload to filestore fails', function () {
|
||||
beforeEach(function () {
|
||||
@@ -289,28 +269,32 @@ describe('FileStoreHandler', function () {
|
||||
}
|
||||
})
|
||||
|
||||
it('should callback with an error', function (done) {
|
||||
it('should reject with an error', async function () {
|
||||
this.fs.createReadStream.callCount = 0
|
||||
this.fs.createReadStream.returns({
|
||||
pipe() {},
|
||||
on(type, cb) {
|
||||
pipe: sinon.stub(),
|
||||
on: sinon.stub((type, cb) => {
|
||||
if (type === 'open') {
|
||||
cb()
|
||||
}
|
||||
},
|
||||
}),
|
||||
})
|
||||
this.handler.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
err => {
|
||||
expect(err).to.exist
|
||||
expect(err).to.be.instanceof(Error)
|
||||
expect(this.fs.createReadStream.callCount).to.equal(
|
||||
this.handler.RETRY_ATTEMPTS
|
||||
)
|
||||
done()
|
||||
}
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
|
||||
expect(this.fs.createReadStream.callCount).to.equal(
|
||||
this.handler.RETRY_ATTEMPTS
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -319,49 +303,40 @@ describe('FileStoreHandler', function () {
|
||||
beforeEach(function () {
|
||||
this.Features.hasFeature.withArgs('filestore').returns(false)
|
||||
})
|
||||
it('should not open file handle', function (done) {
|
||||
this.handler.uploadFileFromDisk(
|
||||
it('should not open file handle', async function () {
|
||||
await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
() => {
|
||||
expect(this.fs.createReadStream).to.not.have.been.called
|
||||
done()
|
||||
}
|
||||
this.fsPath
|
||||
)
|
||||
expect(this.fs.createReadStream).to.not.have.been.called
|
||||
})
|
||||
|
||||
it('should not talk to filestore', function (done) {
|
||||
this.handler.uploadFileFromDisk(
|
||||
it('should not talk to filestore', async function () {
|
||||
await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
() => {
|
||||
expect(this.request).to.not.have.been.called
|
||||
done()
|
||||
}
|
||||
this.fsPath
|
||||
)
|
||||
|
||||
expect(this.request).to.not.have.been.called
|
||||
})
|
||||
|
||||
it('should callback with the url and fileRef', function (done) {
|
||||
it('should resolve with the url and fileRef', async function () {
|
||||
const fileUrl = this.getFileUrl(this.projectId, this.fileId)
|
||||
this.handler.uploadFileFromDisk(
|
||||
const { url, fileRef } = await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
(err, url, fileRef) => {
|
||||
expect(err).to.not.exist
|
||||
expect(url).to.equal(fileUrl)
|
||||
expect(fileRef._id).to.equal(this.fileId)
|
||||
expect(fileRef.hash).to.equal(this.hashValue)
|
||||
done()
|
||||
}
|
||||
this.fsPath
|
||||
)
|
||||
expect(url).to.equal(fileUrl)
|
||||
expect(fileRef._id).to.equal(this.fileId)
|
||||
expect(fileRef.hash).to.equal(this.hashValue)
|
||||
})
|
||||
})
|
||||
|
||||
describe('symlink', function () {
|
||||
it('should not read file if it is symlink', function (done) {
|
||||
it('should not read file if it is symlink', async function () {
|
||||
this.fs.lstat = sinon.stub().callsArgWith(1, null, {
|
||||
isFile() {
|
||||
return false
|
||||
@@ -371,28 +346,40 @@ describe('FileStoreHandler', function () {
|
||||
},
|
||||
})
|
||||
|
||||
this.handler.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
() => {
|
||||
this.fs.createReadStream.called.should.equal(false)
|
||||
done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
|
||||
this.fs.createReadStream.called.should.equal(false)
|
||||
})
|
||||
|
||||
it('should not read file stat returns nothing', function (done) {
|
||||
it('should not read file stat returns nothing', async function () {
|
||||
this.fs.lstat = sinon.stub().callsArgWith(1, null, null)
|
||||
this.handler.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath,
|
||||
() => {
|
||||
this.fs.createReadStream.called.should.equal(false)
|
||||
done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.handler.promises.uploadFileFromDisk(
|
||||
this.projectId,
|
||||
this.fileArgs,
|
||||
this.fsPath
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
|
||||
this.fs.createReadStream.called.should.equal(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -410,13 +397,18 @@ describe('FileStoreHandler', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('should return the error if there is one', function (done) {
|
||||
const error = 'my error'
|
||||
this.request.callsArgWith(1, error)
|
||||
this.handler.deleteFile(this.projectId, this.fileId, err => {
|
||||
assert.equal(err, error)
|
||||
done()
|
||||
})
|
||||
it('should reject with the error if there is one', async function () {
|
||||
const expectedError = 'my error'
|
||||
this.request.callsArgWith(1, expectedError)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.handler.promises.deleteFile(this.projectId, this.fileId)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.equal(expectedError)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -425,40 +417,43 @@ describe('FileStoreHandler', function () {
|
||||
beforeEach(function () {
|
||||
this.Features.hasFeature.withArgs('filestore').returns(true)
|
||||
})
|
||||
it('should send a delete request to filestore api', function (done) {
|
||||
it('should send a delete request to filestore api', async function () {
|
||||
const projectUrl = this.getProjectUrl(this.projectId)
|
||||
this.request.callsArgWith(1, null)
|
||||
|
||||
this.handler.deleteProject(this.projectId, err => {
|
||||
assert.equal(err, undefined)
|
||||
this.request.args[0][0].method.should.equal('delete')
|
||||
this.request.args[0][0].uri.should.equal(projectUrl)
|
||||
done()
|
||||
})
|
||||
await this.handler.promises.deleteProject(this.projectId)
|
||||
this.request.args[0][0].method.should.equal('delete')
|
||||
this.request.args[0][0].uri.should.equal(projectUrl)
|
||||
})
|
||||
|
||||
it('should wrap the error if there is one', function (done) {
|
||||
const error = new Error('my error')
|
||||
this.request.callsArgWith(1, error)
|
||||
this.handler.deleteProject(this.projectId, err => {
|
||||
expect(OError.getFullStack(err)).to.match(
|
||||
/something went wrong deleting a project in filestore/
|
||||
)
|
||||
expect(OError.getFullStack(err)).to.match(/my error/)
|
||||
done()
|
||||
})
|
||||
it('should wrap the error if there is one', async function () {
|
||||
const expectedError = new Error('my error')
|
||||
this.request.callsArgWith(1, expectedError)
|
||||
const promise = this.handler.promises.deleteProject(this.projectId)
|
||||
let error
|
||||
|
||||
try {
|
||||
await promise
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
|
||||
expect(OError.getFullStack(error)).to.match(
|
||||
/something went wrong deleting a project in filestore/
|
||||
)
|
||||
expect(OError.getFullStack(error)).to.match(/my error/)
|
||||
})
|
||||
})
|
||||
describe('when filestore is disabled', function () {
|
||||
beforeEach(function () {
|
||||
this.Features.hasFeature.withArgs('filestore').returns(false)
|
||||
})
|
||||
it('should not send a delete request to filestore api', function (done) {
|
||||
this.handler.deleteProject(this.projectId, err => {
|
||||
assert.equal(err, undefined)
|
||||
this.request.called.should.equal(false)
|
||||
done()
|
||||
})
|
||||
it('should not send a delete request to filestore api', async function () {
|
||||
await this.handler.promises.deleteProject(this.projectId)
|
||||
|
||||
this.request.called.should.equal(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -469,18 +464,37 @@ describe('FileStoreHandler', function () {
|
||||
this.Features.hasFeature.withArgs('filestore').returns(false)
|
||||
})
|
||||
|
||||
it('should callback with a NotFoundError', function (done) {
|
||||
this.handler.getFileStream(this.projectId, this.fileId, {}, err => {
|
||||
expect(err).to.be.instanceof(Errors.NotFoundError)
|
||||
done()
|
||||
})
|
||||
it('should callback with a NotFoundError', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.handler.promises.getFileStream(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
{}
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Errors.NotFoundError)
|
||||
})
|
||||
|
||||
it('should not call request', function (done) {
|
||||
this.handler.getFileStream(this.projectId, this.fileId, {}, () => {
|
||||
this.request.called.should.equal(false)
|
||||
done()
|
||||
})
|
||||
it('should not call request', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.handler.promises.getFileStream(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
{}
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
this.request.called.should.equal(false)
|
||||
})
|
||||
})
|
||||
describe('when filestore is enabled', function () {
|
||||
@@ -490,53 +504,36 @@ describe('FileStoreHandler', function () {
|
||||
this.Features.hasFeature.withArgs('filestore').returns(true)
|
||||
})
|
||||
|
||||
it('should get the stream with the correct params', function (done) {
|
||||
it('should get the stream with the correct params', async function () {
|
||||
const fileUrl = this.getFileUrl(this.projectId, this.fileId)
|
||||
this.handler.getFileStream(
|
||||
await this.handler.promises.getFileStream(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
this.query,
|
||||
(err, stream) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
this.request.args[0][0].method.should.equal('get')
|
||||
this.request.args[0][0].uri.should.equal(
|
||||
fileUrl + '?from=getFileStream'
|
||||
)
|
||||
done()
|
||||
}
|
||||
this.query
|
||||
)
|
||||
this.request.args[0][0].method.should.equal('get')
|
||||
this.request.args[0][0].uri.should.equal(
|
||||
fileUrl + '?from=getFileStream'
|
||||
)
|
||||
})
|
||||
|
||||
it('should get stream from request', function (done) {
|
||||
this.handler.getFileStream(
|
||||
it('should get stream from request', async function () {
|
||||
const stream = await this.handler.promises.getFileStream(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
this.query,
|
||||
(err, stream) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
stream.should.equal(this.readStream)
|
||||
done()
|
||||
}
|
||||
this.query
|
||||
)
|
||||
|
||||
stream.should.equal(this.readStream)
|
||||
})
|
||||
|
||||
it('should add an error handler', function (done) {
|
||||
this.handler.getFileStream(
|
||||
it('should add an error handler', async function () {
|
||||
const stream = await this.handler.promises.getFileStream(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
this.query,
|
||||
(err, stream) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
stream.on.calledWith('error').should.equal(true)
|
||||
done()
|
||||
}
|
||||
this.query
|
||||
)
|
||||
stream.on.calledWith('error').should.equal(true)
|
||||
})
|
||||
|
||||
describe('when range is specified in query', function () {
|
||||
@@ -544,22 +541,17 @@ describe('FileStoreHandler', function () {
|
||||
this.query = { range: '0-10' }
|
||||
})
|
||||
|
||||
it('should add a range header', function (done) {
|
||||
this.handler.getFileStream(
|
||||
it('should add a range header', async function () {
|
||||
await this.handler.promises.getFileStream(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
this.query,
|
||||
(err, stream) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
this.request.callCount.should.equal(1)
|
||||
const { headers } = this.request.firstCall.args[0]
|
||||
expect(headers).to.have.keys('range')
|
||||
expect(headers.range).to.equal('bytes=0-10')
|
||||
done()
|
||||
}
|
||||
this.query
|
||||
)
|
||||
|
||||
this.request.callCount.should.equal(1)
|
||||
const { headers } = this.request.firstCall.args[0]
|
||||
expect(headers).to.have.keys('range')
|
||||
expect(headers.range).to.equal('bytes=0-10')
|
||||
})
|
||||
|
||||
describe('when range is invalid', function () {
|
||||
@@ -568,21 +560,15 @@ describe('FileStoreHandler', function () {
|
||||
this.query = { range: `${r}` }
|
||||
})
|
||||
|
||||
it(`should not add a range header for '${r}'`, function (done) {
|
||||
this.handler.getFileStream(
|
||||
it(`should not add a range header for '${r}'`, async function () {
|
||||
await this.handler.promises.getFileStream(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
this.query,
|
||||
(err, stream) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
this.request.callCount.should.equal(1)
|
||||
const { headers } = this.request.firstCall.args[0]
|
||||
expect(headers).to.not.have.keys('range')
|
||||
done()
|
||||
}
|
||||
this.query
|
||||
)
|
||||
this.request.callCount.should.equal(1)
|
||||
const { headers } = this.request.firstCall.args[0]
|
||||
expect(headers).to.not.have.keys('range')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -591,7 +577,7 @@ describe('FileStoreHandler', function () {
|
||||
})
|
||||
|
||||
describe('getFileSize', function () {
|
||||
it('returns the file size reported by filestore', function (done) {
|
||||
it('returns the file size reported by filestore', async function () {
|
||||
const expectedFileSize = 32432
|
||||
const fileUrl =
|
||||
this.getFileUrl(this.projectId, this.fileId) + '?from=getFileSize'
|
||||
@@ -605,40 +591,54 @@ describe('FileStoreHandler', function () {
|
||||
},
|
||||
})
|
||||
|
||||
this.handler.getFileSize(this.projectId, this.fileId, (err, fileSize) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
expect(fileSize).to.equal(expectedFileSize)
|
||||
done()
|
||||
})
|
||||
const fileSize = await this.handler.promises.getFileSize(
|
||||
this.projectId,
|
||||
this.fileId
|
||||
)
|
||||
expect(fileSize).to.equal(expectedFileSize)
|
||||
})
|
||||
|
||||
it('throws a NotFoundError on a 404 from filestore', function (done) {
|
||||
it('throws a NotFoundError on a 404 from filestore', async function () {
|
||||
this.request.head.yields(null, { statusCode: 404 })
|
||||
|
||||
this.handler.getFileSize(this.projectId, this.fileId, err => {
|
||||
expect(err).to.be.instanceof(Errors.NotFoundError)
|
||||
done()
|
||||
})
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.handler.promises.getFileSize(this.projectId, this.fileId)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Errors.NotFoundError)
|
||||
})
|
||||
|
||||
it('throws an error on a non-200 from filestore', function (done) {
|
||||
it('throws an error on a non-200 from filestore', async function () {
|
||||
this.request.head.yields(null, { statusCode: 500 })
|
||||
|
||||
this.handler.getFileSize(this.projectId, this.fileId, err => {
|
||||
expect(err).to.be.instanceof(Error)
|
||||
done()
|
||||
})
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.handler.promises.getFileSize(this.projectId, this.fileId)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
})
|
||||
|
||||
it('rethrows errors from filestore', function (done) {
|
||||
this.request.head.yields(new Error())
|
||||
it('rethrows errors from filestore', async function () {
|
||||
const expectedError = new Error('from filestore')
|
||||
this.request.head.yields(expectedError)
|
||||
|
||||
this.handler.getFileSize(this.projectId, this.fileId, err => {
|
||||
expect(err).to.be.instanceof(Error)
|
||||
done()
|
||||
})
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.handler.promises.getFileSize(this.projectId, this.fileId)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.equal(expectedError)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -648,74 +648,75 @@ describe('FileStoreHandler', function () {
|
||||
this.newFileId = 'new file id'
|
||||
})
|
||||
|
||||
it('should post json', function (done) {
|
||||
it('should post json', async function () {
|
||||
const newFileUrl = this.getFileUrl(this.newProjectId, this.newFileId)
|
||||
this.request.callsArgWith(1, null, { statusCode: 200 })
|
||||
|
||||
this.handler.copyFile(
|
||||
await this.handler.promises.copyFile(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
this.newProjectId,
|
||||
this.newFileId,
|
||||
() => {
|
||||
this.request.args[0][0].method.should.equal('put')
|
||||
this.request.args[0][0].uri.should.equal(newFileUrl)
|
||||
this.request.args[0][0].json.source.project_id.should.equal(
|
||||
this.projectId
|
||||
)
|
||||
this.request.args[0][0].json.source.file_id.should.equal(this.fileId)
|
||||
done()
|
||||
}
|
||||
this.newFileId
|
||||
)
|
||||
this.request.args[0][0].method.should.equal('put')
|
||||
this.request.args[0][0].uri.should.equal(newFileUrl)
|
||||
this.request.args[0][0].json.source.project_id.should.equal(
|
||||
this.projectId
|
||||
)
|
||||
this.request.args[0][0].json.source.file_id.should.equal(this.fileId)
|
||||
})
|
||||
|
||||
it('returns the url', function (done) {
|
||||
it('returns the url', async function () {
|
||||
const expectedUrl = this.getFileUrl(this.newProjectId, this.newFileId)
|
||||
this.request.callsArgWith(1, null, { statusCode: 200 })
|
||||
this.handler.copyFile(
|
||||
const url = await this.handler.promises.copyFile(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
this.newProjectId,
|
||||
this.newFileId,
|
||||
(err, url) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
url.should.equal(expectedUrl)
|
||||
done()
|
||||
}
|
||||
this.newFileId
|
||||
)
|
||||
|
||||
url.should.equal(expectedUrl)
|
||||
})
|
||||
|
||||
it('should return the err', function (done) {
|
||||
const error = new Error('error')
|
||||
this.request.callsArgWith(1, error)
|
||||
this.handler.copyFile(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
this.newProjectId,
|
||||
this.newFileId,
|
||||
err => {
|
||||
err.should.equal(error)
|
||||
done()
|
||||
}
|
||||
)
|
||||
it('should return the err', async function () {
|
||||
const expectedError = new Error('error')
|
||||
this.request.callsArgWith(1, expectedError)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.handler.promises.copyFile(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
this.newProjectId,
|
||||
this.newFileId
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.equal(expectedError)
|
||||
})
|
||||
|
||||
it('should return an error for a non-success statusCode', function (done) {
|
||||
it('should return an error for a non-success statusCode', async function () {
|
||||
this.request.callsArgWith(1, null, { statusCode: 500 })
|
||||
this.handler.copyFile(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
this.newProjectId,
|
||||
this.newFileId,
|
||||
err => {
|
||||
err.should.be.an('error')
|
||||
err.message.should.equal(
|
||||
'non-ok response from filestore for copyFile: 500'
|
||||
)
|
||||
done()
|
||||
}
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.handler.promises.copyFile(
|
||||
this.projectId,
|
||||
this.fileId,
|
||||
this.newProjectId,
|
||||
this.newFileId
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
'non-ok response from filestore for copyFile: 500'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -45,48 +45,43 @@ describe('InstitutionsAPI', function () {
|
||||
})
|
||||
|
||||
describe('getInstitutionAffiliations', function () {
|
||||
it('get affiliations', function (done) {
|
||||
it('get affiliations', async function () {
|
||||
this.institutionId = 123
|
||||
const responseBody = ['123abc', '456def']
|
||||
this.request.yields(null, { statusCode: 200 }, responseBody)
|
||||
this.InstitutionsAPI.getInstitutionAffiliations(
|
||||
this.institutionId,
|
||||
(err, body) => {
|
||||
expect(err).not.to.exist
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
const expectedUrl = `v1.url/api/v2/institutions/${this.institutionId}/affiliations`
|
||||
requestOptions.url.should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('GET')
|
||||
requestOptions.maxAttempts.should.exist
|
||||
requestOptions.maxAttempts.should.not.equal(0)
|
||||
requestOptions.retryDelay.should.exist
|
||||
expect(requestOptions.body).not.to.exist
|
||||
body.should.equal(responseBody)
|
||||
done()
|
||||
}
|
||||
)
|
||||
const body =
|
||||
await this.InstitutionsAPI.promises.getInstitutionAffiliations(
|
||||
this.institutionId
|
||||
)
|
||||
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
const expectedUrl = `v1.url/api/v2/institutions/${this.institutionId}/affiliations`
|
||||
requestOptions.url.should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('GET')
|
||||
requestOptions.maxAttempts.should.exist
|
||||
requestOptions.maxAttempts.should.not.equal(0)
|
||||
requestOptions.retryDelay.should.exist
|
||||
expect(requestOptions.body).not.to.exist
|
||||
body.should.equal(responseBody)
|
||||
})
|
||||
|
||||
it('handle empty response', function (done) {
|
||||
it('handle empty response', async function () {
|
||||
this.settings.apis.v1.url = ''
|
||||
|
||||
this.InstitutionsAPI.getInstitutionAffiliations(
|
||||
this.institutionId,
|
||||
(err, body) => {
|
||||
expect(err).not.to.exist
|
||||
expect(body).to.be.a('Array')
|
||||
body.length.should.equal(0)
|
||||
done()
|
||||
}
|
||||
)
|
||||
const body =
|
||||
await this.InstitutionsAPI.promises.getInstitutionAffiliations(
|
||||
this.institutionId
|
||||
)
|
||||
expect(body).to.be.a('Array')
|
||||
body.length.should.equal(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getLicencesForAnalytics', function () {
|
||||
const lag = 'daily'
|
||||
const queryDate = '2017-01-07:00:00.000Z'
|
||||
it('should send the request to v1', function (done) {
|
||||
it('should send the request to v1', async function () {
|
||||
const v1Result = {
|
||||
lag: 'daily',
|
||||
date: queryDate,
|
||||
@@ -96,100 +91,91 @@ describe('InstitutionsAPI', function () {
|
||||
},
|
||||
}
|
||||
this.request.callsArgWith(1, null, { statusCode: 201 }, v1Result)
|
||||
this.InstitutionsAPI.getLicencesForAnalytics(
|
||||
await this.InstitutionsAPI.promises.getLicencesForAnalytics(
|
||||
lag,
|
||||
queryDate,
|
||||
(error, result) => {
|
||||
expect(error).not.to.exist
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
expect(requestOptions.body.query_date).to.equal(queryDate)
|
||||
expect(requestOptions.body.lag).to.equal(lag)
|
||||
requestOptions.method.should.equal('GET')
|
||||
done()
|
||||
}
|
||||
queryDate
|
||||
)
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
expect(requestOptions.body.query_date).to.equal(queryDate)
|
||||
expect(requestOptions.body.lag).to.equal(lag)
|
||||
requestOptions.method.should.equal('GET')
|
||||
})
|
||||
it('should handle errors', function (done) {
|
||||
it('should handle errors', async function () {
|
||||
this.request.callsArgWith(1, null, { statusCode: 500 })
|
||||
this.InstitutionsAPI.getLicencesForAnalytics(
|
||||
lag,
|
||||
queryDate,
|
||||
(error, result) => {
|
||||
expect(error).to.be.instanceof(Errors.V1ConnectionError)
|
||||
done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.InstitutionsAPI.promises.getLicencesForAnalytics(
|
||||
lag,
|
||||
queryDate
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Errors.V1ConnectionError)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getUserAffiliations', function () {
|
||||
it('get affiliations', function (done) {
|
||||
it('get affiliations', async function () {
|
||||
const responseBody = [{ foo: 'bar' }]
|
||||
this.request.callsArgWith(1, null, { statusCode: 201 }, responseBody)
|
||||
this.InstitutionsAPI.getUserAffiliations(
|
||||
this.stubbedUser._id,
|
||||
(err, body) => {
|
||||
expect(err).not.to.exist
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
const expectedUrl = `v1.url/api/v2/users/${this.stubbedUser._id}/affiliations`
|
||||
requestOptions.url.should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('GET')
|
||||
requestOptions.maxAttempts.should.equal(3)
|
||||
expect(requestOptions.body).not.to.exist
|
||||
body.should.equal(responseBody)
|
||||
done()
|
||||
}
|
||||
const body = await this.InstitutionsAPI.promises.getUserAffiliations(
|
||||
this.stubbedUser._id
|
||||
)
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
const expectedUrl = `v1.url/api/v2/users/${this.stubbedUser._id}/affiliations`
|
||||
requestOptions.url.should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('GET')
|
||||
requestOptions.maxAttempts.should.equal(3)
|
||||
expect(requestOptions.body).not.to.exist
|
||||
body.should.equal(responseBody)
|
||||
})
|
||||
|
||||
it('handle error', function (done) {
|
||||
it('handle error', async function () {
|
||||
const body = { errors: 'affiliation error message' }
|
||||
this.request.callsArgWith(1, null, { statusCode: 503 }, body)
|
||||
this.InstitutionsAPI.getUserAffiliations(this.stubbedUser._id, err => {
|
||||
expect(err).to.be.instanceof(Errors.V1ConnectionError)
|
||||
done()
|
||||
})
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.InstitutionsAPI.promises.getUserAffiliations(
|
||||
this.stubbedUser._id
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Errors.V1ConnectionError)
|
||||
})
|
||||
|
||||
it('handle empty response', function (done) {
|
||||
it('handle empty response', async function () {
|
||||
this.settings.apis.v1.url = ''
|
||||
this.InstitutionsAPI.getUserAffiliations(
|
||||
this.stubbedUser._id,
|
||||
(err, body) => {
|
||||
expect(err).not.to.exist
|
||||
expect(body).to.be.a('Array')
|
||||
body.length.should.equal(0)
|
||||
done()
|
||||
}
|
||||
const body = await this.InstitutionsAPI.promises.getUserAffiliations(
|
||||
this.stubbedUser._id
|
||||
)
|
||||
expect(body).to.be.a('Array')
|
||||
body.length.should.equal(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getUsersNeedingReconfirmationsLapsedProcessed', function () {
|
||||
it('get the list of users', function (done) {
|
||||
it('get the list of users', async function () {
|
||||
this.fetchJson.resolves({ statusCode: 200 })
|
||||
this.InstitutionsAPI.getUsersNeedingReconfirmationsLapsedProcessed(
|
||||
error => {
|
||||
expect(error).not.to.exist
|
||||
this.fetchJson.calledOnce.should.equal(true)
|
||||
const requestOptions = this.fetchJson.lastCall.args[1]
|
||||
const expectedUrl = `v1.url/api/v2/institutions/need_reconfirmation_lapsed_processed`
|
||||
this.fetchJson.lastCall.args[0].should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('GET')
|
||||
done()
|
||||
}
|
||||
)
|
||||
await this.InstitutionsAPI.promises.getUsersNeedingReconfirmationsLapsedProcessed()
|
||||
this.fetchJson.calledOnce.should.equal(true)
|
||||
const requestOptions = this.fetchJson.lastCall.args[1]
|
||||
const expectedUrl = `v1.url/api/v2/institutions/need_reconfirmation_lapsed_processed`
|
||||
this.fetchJson.lastCall.args[0].should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('GET')
|
||||
})
|
||||
|
||||
it('handle error', function (done) {
|
||||
it('handle error', async function () {
|
||||
this.fetchJson.throws({ info: { statusCode: 500 } })
|
||||
this.InstitutionsAPI.getUsersNeedingReconfirmationsLapsedProcessed(
|
||||
error => {
|
||||
expect(error).to.exist
|
||||
done()
|
||||
}
|
||||
)
|
||||
await expect(
|
||||
this.InstitutionsAPI.promises.getUsersNeedingReconfirmationsLapsedProcessed()
|
||||
).to.be.rejected
|
||||
})
|
||||
})
|
||||
|
||||
@@ -198,7 +184,7 @@ describe('InstitutionsAPI', function () {
|
||||
this.fetchNothing.resolves({ status: 201 })
|
||||
})
|
||||
|
||||
it('add affiliation', function (done) {
|
||||
it('add affiliation', async function () {
|
||||
const affiliationOptions = {
|
||||
university: { id: 1 },
|
||||
department: 'Math',
|
||||
@@ -206,95 +192,104 @@ describe('InstitutionsAPI', function () {
|
||||
confirmedAt: new Date(),
|
||||
entitlement: true,
|
||||
}
|
||||
this.InstitutionsAPI.addAffiliation(
|
||||
await this.InstitutionsAPI.promises.addAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail,
|
||||
affiliationOptions,
|
||||
err => {
|
||||
expect(err).not.to.exist
|
||||
this.fetchNothing.calledOnce.should.equal(true)
|
||||
const requestOptions = this.fetchNothing.lastCall.args[1]
|
||||
const expectedUrl = `v1.url/api/v2/users/${this.stubbedUser._id}/affiliations`
|
||||
expect(this.fetchNothing.lastCall.args[0]).to.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('POST')
|
||||
|
||||
const { json } = requestOptions
|
||||
Object.keys(json).length.should.equal(7)
|
||||
expect(json).to.deep.equal(
|
||||
Object.assign(
|
||||
{ email: this.newEmail, rejectIfBlocklisted: undefined },
|
||||
affiliationOptions
|
||||
)
|
||||
)
|
||||
this.markAsReadIpMatcher.calledOnce.should.equal(true)
|
||||
done()
|
||||
}
|
||||
affiliationOptions
|
||||
)
|
||||
this.fetchNothing.calledOnce.should.equal(true)
|
||||
const requestOptions = this.fetchNothing.lastCall.args[1]
|
||||
const expectedUrl = `v1.url/api/v2/users/${this.stubbedUser._id}/affiliations`
|
||||
expect(this.fetchNothing.lastCall.args[0]).to.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('POST')
|
||||
|
||||
const { json } = requestOptions
|
||||
Object.keys(json).length.should.equal(7)
|
||||
expect(json).to.deep.equal(
|
||||
Object.assign(
|
||||
{ email: this.newEmail, rejectIfBlocklisted: undefined },
|
||||
affiliationOptions
|
||||
)
|
||||
)
|
||||
this.markAsReadIpMatcher.calledOnce.should.equal(true)
|
||||
})
|
||||
|
||||
it('handles 422 error', function (done) {
|
||||
it('handles 422 error', async function () {
|
||||
const messageFromApi = 'affiliation error message'
|
||||
const body = JSON.stringify({ errors: messageFromApi })
|
||||
this.fetchNothing.throws({ response: { status: 422 }, body })
|
||||
this.InstitutionsAPI.addAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail,
|
||||
{},
|
||||
err => {
|
||||
expect(err).to.exist
|
||||
expect(err).to.be.instanceOf(Errors.InvalidInstitutionalEmailError)
|
||||
err.message.should.have.string(422)
|
||||
err.message.should.have.string(messageFromApi)
|
||||
done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.InstitutionsAPI.promises.addAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail,
|
||||
{}
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Errors.InvalidInstitutionalEmailError)
|
||||
expect(error).to.have.property('message', `422: ${messageFromApi}`)
|
||||
})
|
||||
|
||||
it('handles 500 error', function (done) {
|
||||
it('handles 500 error', async function () {
|
||||
const body = { errors: 'affiliation error message' }
|
||||
this.fetchNothing.throws({ response: { status: 500 }, body })
|
||||
this.InstitutionsAPI.addAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail,
|
||||
{},
|
||||
err => {
|
||||
expect(err).to.be.instanceOf(Errors.V1ConnectionError)
|
||||
expect(err.message).to.equal('error getting affiliations from v1')
|
||||
expect(err.info).to.deep.equal({ status: 500, body })
|
||||
done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.InstitutionsAPI.promises.addAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail,
|
||||
{}
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Errors.V1ConnectionError)
|
||||
expect(error.message).to.equal('error getting affiliations from v1')
|
||||
expect(error.info).to.eql({
|
||||
status: 500,
|
||||
body: { errors: 'affiliation error message' },
|
||||
})
|
||||
})
|
||||
|
||||
it('uses default error message when no error body in response', function (done) {
|
||||
it('uses default error message when no error body in response', async function () {
|
||||
this.fetchNothing.throws({ response: { status: 429 } })
|
||||
this.InstitutionsAPI.addAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail,
|
||||
{},
|
||||
err => {
|
||||
expect(err).to.exist
|
||||
expect(err.message).to.equal("Couldn't create affiliation: 429")
|
||||
done()
|
||||
}
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.InstitutionsAPI.promises.addAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail,
|
||||
{}
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Error)
|
||||
expect(error).to.have.property(
|
||||
'message',
|
||||
"Couldn't create affiliation: 429"
|
||||
)
|
||||
})
|
||||
|
||||
it('does not try to mark IP matcher notifications as read if no university passed', function (done) {
|
||||
it('does not try to mark IP matcher notifications as read if no university passed', async function () {
|
||||
const affiliationOptions = {
|
||||
confirmedAt: new Date(),
|
||||
}
|
||||
|
||||
this.InstitutionsAPI.addAffiliation(
|
||||
await this.InstitutionsAPI.promises.addAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail,
|
||||
affiliationOptions,
|
||||
err => {
|
||||
expect(err).not.to.exist
|
||||
expect(this.markAsReadIpMatcher.callCount).to.equal(0)
|
||||
done()
|
||||
}
|
||||
affiliationOptions
|
||||
)
|
||||
|
||||
expect(this.markAsReadIpMatcher.callCount).to.equal(0)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -303,58 +298,64 @@ describe('InstitutionsAPI', function () {
|
||||
this.fetchNothing.throws({ response: { status: 404 } })
|
||||
})
|
||||
|
||||
it('remove affiliation', function (done) {
|
||||
this.InstitutionsAPI.removeAffiliation(
|
||||
it('remove affiliation', async function () {
|
||||
await this.InstitutionsAPI.promises.removeAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail,
|
||||
err => {
|
||||
expect(err).not.to.exist
|
||||
this.fetchNothing.calledOnce.should.equal(true)
|
||||
const requestOptions = this.fetchNothing.lastCall.args[1]
|
||||
const expectedUrl = `v1.url/api/v2/users/${this.stubbedUser._id}/affiliations/remove`
|
||||
this.fetchNothing.lastCall.args[0].should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('POST')
|
||||
expect(requestOptions.json).to.deep.equal({ email: this.newEmail })
|
||||
done()
|
||||
}
|
||||
this.newEmail
|
||||
)
|
||||
this.fetchNothing.calledOnce.should.equal(true)
|
||||
const requestOptions = this.fetchNothing.lastCall.args[1]
|
||||
const expectedUrl = `v1.url/api/v2/users/${this.stubbedUser._id}/affiliations/remove`
|
||||
this.fetchNothing.lastCall.args[0].should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('POST')
|
||||
expect(requestOptions.json).to.deep.equal({ email: this.newEmail })
|
||||
})
|
||||
|
||||
it('handle error', function (done) {
|
||||
it('handle error', async function () {
|
||||
this.fetchNothing.throws({ response: { status: 500 } })
|
||||
this.InstitutionsAPI.removeAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail,
|
||||
err => {
|
||||
expect(err).to.exist
|
||||
err.message.should.exist
|
||||
done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.InstitutionsAPI.promises.removeAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
expect(error).to.have.property('message')
|
||||
})
|
||||
})
|
||||
|
||||
describe('deleteAffiliations', function () {
|
||||
it('delete affiliations', function (done) {
|
||||
it('delete affiliations', async function () {
|
||||
this.request.callsArgWith(1, null, { statusCode: 200 })
|
||||
this.InstitutionsAPI.deleteAffiliations(this.stubbedUser._id, err => {
|
||||
expect(err).not.to.exist
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
const expectedUrl = `v1.url/api/v2/users/${this.stubbedUser._id}/affiliations`
|
||||
requestOptions.url.should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('DELETE')
|
||||
done()
|
||||
})
|
||||
await this.InstitutionsAPI.promises.deleteAffiliations(
|
||||
this.stubbedUser._id
|
||||
)
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
const expectedUrl = `v1.url/api/v2/users/${this.stubbedUser._id}/affiliations`
|
||||
requestOptions.url.should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('DELETE')
|
||||
})
|
||||
|
||||
it('handle error', function (done) {
|
||||
it('handle error', async function () {
|
||||
const body = { errors: 'affiliation error message' }
|
||||
this.request.callsArgWith(1, null, { statusCode: 518 }, body)
|
||||
this.InstitutionsAPI.deleteAffiliations(this.stubbedUser._id, err => {
|
||||
expect(err).to.be.instanceof(Errors.V1ConnectionError)
|
||||
done()
|
||||
})
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.InstitutionsAPI.promises.deleteAffiliations(
|
||||
this.stubbedUser._id
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Errors.V1ConnectionError)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -363,61 +364,57 @@ describe('InstitutionsAPI', function () {
|
||||
this.request.callsArgWith(1, null, { statusCode: 204 })
|
||||
})
|
||||
|
||||
it('endorse affiliation', function (done) {
|
||||
this.InstitutionsAPI.endorseAffiliation(
|
||||
it('endorse affiliation', async function () {
|
||||
await this.InstitutionsAPI.promises.endorseAffiliation(
|
||||
this.stubbedUser._id,
|
||||
this.newEmail,
|
||||
'Student',
|
||||
'Physics',
|
||||
err => {
|
||||
expect(err).not.to.exist
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
const expectedUrl = `v1.url/api/v2/users/${this.stubbedUser._id}/affiliations/endorse`
|
||||
requestOptions.url.should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('POST')
|
||||
|
||||
const { body } = requestOptions
|
||||
Object.keys(body).length.should.equal(3)
|
||||
body.email.should.equal(this.newEmail)
|
||||
body.role.should.equal('Student')
|
||||
body.department.should.equal('Physics')
|
||||
done()
|
||||
}
|
||||
'Physics'
|
||||
)
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
const expectedUrl = `v1.url/api/v2/users/${this.stubbedUser._id}/affiliations/endorse`
|
||||
requestOptions.url.should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('POST')
|
||||
|
||||
const { body } = requestOptions
|
||||
Object.keys(body).length.should.equal(3)
|
||||
body.email.should.equal(this.newEmail)
|
||||
body.role.should.equal('Student')
|
||||
body.department.should.equal('Physics')
|
||||
})
|
||||
})
|
||||
|
||||
describe('sendUsersWithReconfirmationsLapsedProcessed', function () {
|
||||
const users = ['abc123', 'def456']
|
||||
|
||||
it('sends the list of users', function (done) {
|
||||
it('sends the list of users', async function () {
|
||||
this.request.callsArgWith(1, null, { statusCode: 200 })
|
||||
this.InstitutionsAPI.sendUsersWithReconfirmationsLapsedProcessed(
|
||||
users,
|
||||
error => {
|
||||
expect(error).not.to.exist
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
const expectedUrl =
|
||||
'v1.url/api/v2/institutions/reconfirmation_lapsed_processed'
|
||||
requestOptions.url.should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('POST')
|
||||
expect(requestOptions.body).to.deep.equal({ users })
|
||||
done()
|
||||
}
|
||||
await this.InstitutionsAPI.promises.sendUsersWithReconfirmationsLapsedProcessed(
|
||||
users
|
||||
)
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const requestOptions = this.request.lastCall.args[0]
|
||||
const expectedUrl =
|
||||
'v1.url/api/v2/institutions/reconfirmation_lapsed_processed'
|
||||
requestOptions.url.should.equal(expectedUrl)
|
||||
requestOptions.method.should.equal('POST')
|
||||
expect(requestOptions.body).to.deep.equal({ users })
|
||||
})
|
||||
|
||||
it('handle error', function (done) {
|
||||
it('handle error', async function () {
|
||||
this.request.callsArgWith(1, null, { statusCode: 500 })
|
||||
this.InstitutionsAPI.sendUsersWithReconfirmationsLapsedProcessed(
|
||||
users,
|
||||
error => {
|
||||
expect(error).to.exist
|
||||
done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.InstitutionsAPI.promises.sendUsersWithReconfirmationsLapsedProcessed(
|
||||
users
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,17 +1,4 @@
|
||||
/* eslint-disable
|
||||
max-len,
|
||||
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
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const assert = require('assert')
|
||||
const { expect } = require('chai')
|
||||
const sinon = require('sinon')
|
||||
const modulePath = require('path').join(
|
||||
@@ -41,45 +28,39 @@ describe('InstitutionsFeatures', function () {
|
||||
})
|
||||
|
||||
describe('hasLicence', function () {
|
||||
it('should handle error', function (done) {
|
||||
it('should handle error', async function () {
|
||||
this.UserGetter.promises.getUserFullEmails.rejects(new Error('Nope'))
|
||||
return this.InstitutionsFeatures.hasLicence(
|
||||
this.userId,
|
||||
(error, hasLicence) => {
|
||||
expect(error).to.exist
|
||||
return done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.InstitutionsFeatures.promises.hasLicence(this.userId)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
})
|
||||
|
||||
it('should return false if user has no paid affiliations', function (done) {
|
||||
it('should return false if user has no paid affiliations', async function () {
|
||||
this.UserGetter.promises.getUserFullEmails.resolves(
|
||||
this.emailDataWithoutLicense
|
||||
)
|
||||
return this.InstitutionsFeatures.hasLicence(
|
||||
this.userId,
|
||||
(error, hasLicence) => {
|
||||
expect(error).to.not.exist
|
||||
expect(hasLicence).to.be.false
|
||||
return done()
|
||||
}
|
||||
const hasLicence = await this.InstitutionsFeatures.promises.hasLicence(
|
||||
this.userId
|
||||
)
|
||||
expect(hasLicence).to.be.false
|
||||
})
|
||||
|
||||
it('should return true if user has confirmed paid affiliation', function (done) {
|
||||
it('should return true if user has confirmed paid affiliation', async function () {
|
||||
const emailData = [
|
||||
{ emailHasInstitutionLicence: true },
|
||||
{ emailHasInstitutionLicence: false },
|
||||
]
|
||||
this.UserGetter.promises.getUserFullEmails.resolves(emailData)
|
||||
return this.InstitutionsFeatures.hasLicence(
|
||||
this.userId,
|
||||
(error, hasLicence) => {
|
||||
expect(error).to.not.exist
|
||||
expect(hasLicence).to.be.true
|
||||
return done()
|
||||
}
|
||||
const hasLicence = await this.InstitutionsFeatures.promises.hasLicence(
|
||||
this.userId
|
||||
)
|
||||
expect(hasLicence).to.be.true
|
||||
})
|
||||
})
|
||||
|
||||
@@ -91,84 +72,62 @@ describe('InstitutionsFeatures', function () {
|
||||
.returns(this.testFeatures)
|
||||
})
|
||||
|
||||
it('should handle error', function (done) {
|
||||
it('should handle error', async function () {
|
||||
this.UserGetter.promises.getUserFullEmails.rejects(new Error('Nope'))
|
||||
return this.InstitutionsFeatures.getInstitutionsFeatures(
|
||||
this.userId,
|
||||
(error, features) => {
|
||||
expect(error).to.exist
|
||||
return done()
|
||||
}
|
||||
)
|
||||
await expect(
|
||||
this.InstitutionsFeatures.promises.getInstitutionsFeatures(this.userId)
|
||||
).to.be.rejected
|
||||
})
|
||||
|
||||
it('should return no feaures if user has no plan code', function (done) {
|
||||
it('should return no feaures if user has no plan code', async function () {
|
||||
this.UserGetter.promises.getUserFullEmails.resolves(
|
||||
this.emailDataWithoutLicense
|
||||
)
|
||||
return this.InstitutionsFeatures.getInstitutionsFeatures(
|
||||
this.userId,
|
||||
(error, features) => {
|
||||
expect(error).to.not.exist
|
||||
expect(features).to.deep.equal({})
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const features =
|
||||
await this.InstitutionsFeatures.promises.getInstitutionsFeatures(
|
||||
this.userId
|
||||
)
|
||||
expect(features).to.deep.equal({})
|
||||
})
|
||||
|
||||
it('should return feaures if user has affiliations plan code', function (done) {
|
||||
it('should return feaures if user has affiliations plan code', async function () {
|
||||
this.UserGetter.promises.getUserFullEmails.resolves(
|
||||
this.emailDataWithLicense
|
||||
)
|
||||
return this.InstitutionsFeatures.getInstitutionsFeatures(
|
||||
this.userId,
|
||||
(error, features) => {
|
||||
expect(error).to.not.exist
|
||||
expect(features).to.deep.equal(this.testFeatures.features)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const features =
|
||||
await this.InstitutionsFeatures.promises.getInstitutionsFeatures(
|
||||
this.userId
|
||||
)
|
||||
expect(features).to.deep.equal(this.testFeatures.features)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getInstitutionsPlan', function () {
|
||||
it('should handle error', function (done) {
|
||||
it('should handle error', async function () {
|
||||
this.UserGetter.promises.getUserFullEmails.rejects(new Error('Nope'))
|
||||
return this.InstitutionsFeatures.getInstitutionsPlan(
|
||||
this.userId,
|
||||
error => {
|
||||
expect(error).to.exist
|
||||
return done()
|
||||
}
|
||||
)
|
||||
await expect(
|
||||
this.InstitutionsFeatures.promises.getInstitutionsPlan(this.userId)
|
||||
).to.be.rejected
|
||||
})
|
||||
|
||||
it('should return no plan if user has no licence', function (done) {
|
||||
it('should return no plan if user has no licence', async function () {
|
||||
this.UserGetter.promises.getUserFullEmails.resolves(
|
||||
this.emailDataWithoutLicense
|
||||
)
|
||||
return this.InstitutionsFeatures.getInstitutionsPlan(
|
||||
this.userId,
|
||||
(error, plan) => {
|
||||
expect(error).to.not.exist
|
||||
expect(plan).to.equal(null)
|
||||
return done()
|
||||
}
|
||||
const plan = await this.InstitutionsFeatures.promises.getInstitutionsPlan(
|
||||
this.userId
|
||||
)
|
||||
expect(plan).to.equal(null)
|
||||
})
|
||||
|
||||
it('should return plan if user has licence', function (done) {
|
||||
it('should return plan if user has licence', async function () {
|
||||
this.UserGetter.promises.getUserFullEmails.resolves(
|
||||
this.emailDataWithLicense
|
||||
)
|
||||
return this.InstitutionsFeatures.getInstitutionsPlan(
|
||||
this.userId,
|
||||
(error, plan) => {
|
||||
expect(error).to.not.exist
|
||||
expect(plan).to.equal(this.institutionPlanCode)
|
||||
return done()
|
||||
}
|
||||
const plan = await this.InstitutionsFeatures.promises.getInstitutionsPlan(
|
||||
this.userId
|
||||
)
|
||||
expect(plan).to.equal(this.institutionPlanCode)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -22,22 +22,19 @@ describe('NotificationsBuilder', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('dropboxUnlinkedDueToLapsedReconfirmation', function (done) {
|
||||
it('should create the notification', function (done) {
|
||||
this.controller
|
||||
describe('dropboxUnlinkedDueToLapsedReconfirmation', function () {
|
||||
it('should create the notification', async function () {
|
||||
await this.controller.promises
|
||||
.dropboxUnlinkedDueToLapsedReconfirmation(userId)
|
||||
.create(error => {
|
||||
expect(error).to.not.exist
|
||||
expect(this.handler.createNotification).to.have.been.calledWith(
|
||||
userId,
|
||||
'drobox-unlinked-due-to-lapsed-reconfirmation',
|
||||
'notification_dropbox_unlinked_due_to_lapsed_reconfirmation',
|
||||
{},
|
||||
null,
|
||||
true
|
||||
)
|
||||
done()
|
||||
})
|
||||
.create()
|
||||
expect(this.handler.createNotification).to.have.been.calledWith(
|
||||
userId,
|
||||
'drobox-unlinked-due-to-lapsed-reconfirmation',
|
||||
'notification_dropbox_unlinked_due_to_lapsed_reconfirmation',
|
||||
{},
|
||||
null,
|
||||
true
|
||||
)
|
||||
})
|
||||
describe('NotificationsHandler error', function () {
|
||||
let anError
|
||||
@@ -45,19 +42,23 @@ describe('NotificationsBuilder', function () {
|
||||
anError = new Error('oops')
|
||||
this.handler.createNotification.yields(anError)
|
||||
})
|
||||
it('should return errors from NotificationsHandler', function (done) {
|
||||
this.controller
|
||||
.dropboxUnlinkedDueToLapsedReconfirmation(userId)
|
||||
.create(error => {
|
||||
expect(error).to.exist
|
||||
expect(error).to.deep.equal(anError)
|
||||
done()
|
||||
})
|
||||
it('should return errors from NotificationsHandler', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.controller.promises
|
||||
.dropboxUnlinkedDueToLapsedReconfirmation(userId)
|
||||
.create()
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.equal(anError)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('groupInvitation', function (done) {
|
||||
describe('groupInvitation', function () {
|
||||
const subscriptionId = '123123bcabca'
|
||||
beforeEach(function () {
|
||||
this.invite = {
|
||||
@@ -67,29 +68,26 @@ describe('NotificationsBuilder', function () {
|
||||
}
|
||||
})
|
||||
|
||||
it('should create the notification', function (done) {
|
||||
this.controller
|
||||
it('should create the notification', async function () {
|
||||
await this.controller.promises
|
||||
.groupInvitation(
|
||||
userId,
|
||||
subscriptionId,
|
||||
this.invite.managedUsersEnabled
|
||||
)
|
||||
.create(this.invite, error => {
|
||||
expect(error).to.not.exist
|
||||
expect(this.handler.createNotification).to.have.been.calledWith(
|
||||
userId,
|
||||
`groupInvitation-${subscriptionId}-${userId}`,
|
||||
'notification_group_invitation',
|
||||
{
|
||||
token: this.invite.token,
|
||||
inviterName: this.invite.inviterName,
|
||||
managedUsersEnabled: this.invite.managedUsersEnabled,
|
||||
},
|
||||
null,
|
||||
true
|
||||
)
|
||||
done()
|
||||
})
|
||||
.create(this.invite)
|
||||
expect(this.handler.createNotification).to.have.been.calledWith(
|
||||
userId,
|
||||
`groupInvitation-${subscriptionId}-${userId}`,
|
||||
'notification_group_invitation',
|
||||
{
|
||||
token: this.invite.token,
|
||||
inviterName: this.invite.inviterName,
|
||||
managedUsersEnabled: this.invite.managedUsersEnabled,
|
||||
},
|
||||
null,
|
||||
true
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -107,27 +105,25 @@ describe('NotificationsBuilder', function () {
|
||||
this.request.callsArgWith(1, null, { statusCode: 200 }, this.body)
|
||||
})
|
||||
|
||||
it('should call v1 and create affiliation notifications', function (done) {
|
||||
it('should call v1 and create affiliation notifications', async function () {
|
||||
const ip = '192.168.0.1'
|
||||
this.controller.ipMatcherAffiliation(userId).create(ip, callback => {
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const expectedOpts = {
|
||||
institutionId: this.body.id,
|
||||
university_name: this.body.name,
|
||||
content: this.body.enrolment_ad_html,
|
||||
ssoEnabled: false,
|
||||
portalPath: undefined,
|
||||
}
|
||||
this.handler.createNotification
|
||||
.calledWith(
|
||||
userId,
|
||||
`ip-matched-affiliation-${this.body.id}`,
|
||||
'notification_ip_matched_affiliation',
|
||||
expectedOpts
|
||||
)
|
||||
.should.equal(true)
|
||||
done()
|
||||
})
|
||||
await this.controller.promises.ipMatcherAffiliation(userId).create(ip)
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const expectedOpts = {
|
||||
institutionId: this.body.id,
|
||||
university_name: this.body.name,
|
||||
content: this.body.enrolment_ad_html,
|
||||
ssoEnabled: false,
|
||||
portalPath: undefined,
|
||||
}
|
||||
this.handler.createNotification
|
||||
.calledWith(
|
||||
userId,
|
||||
`ip-matched-affiliation-${this.body.id}`,
|
||||
'notification_ip_matched_affiliation',
|
||||
expectedOpts
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
describe('without portal and without SSO', function () {
|
||||
@@ -143,27 +139,25 @@ describe('NotificationsBuilder', function () {
|
||||
this.request.callsArgWith(1, null, { statusCode: 200 }, this.body)
|
||||
})
|
||||
|
||||
it('should call v1 and create affiliation notifications', function (done) {
|
||||
it('should call v1 and create affiliation notifications', async function () {
|
||||
const ip = '192.168.0.1'
|
||||
this.controller.ipMatcherAffiliation(userId).create(ip, callback => {
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const expectedOpts = {
|
||||
institutionId: this.body.id,
|
||||
university_name: this.body.name,
|
||||
content: this.body.enrolment_ad_html,
|
||||
ssoEnabled: true,
|
||||
portalPath: '/edu/stanford',
|
||||
}
|
||||
this.handler.createNotification
|
||||
.calledWith(
|
||||
userId,
|
||||
`ip-matched-affiliation-${this.body.id}`,
|
||||
'notification_ip_matched_affiliation',
|
||||
expectedOpts
|
||||
)
|
||||
.should.equal(true)
|
||||
done()
|
||||
})
|
||||
await this.controller.promises.ipMatcherAffiliation(userId).create(ip)
|
||||
this.request.calledOnce.should.equal(true)
|
||||
const expectedOpts = {
|
||||
institutionId: this.body.id,
|
||||
university_name: this.body.name,
|
||||
content: this.body.enrolment_ad_html,
|
||||
ssoEnabled: true,
|
||||
portalPath: '/edu/stanford',
|
||||
}
|
||||
this.handler.createNotification
|
||||
.calledWith(
|
||||
userId,
|
||||
`ip-matched-affiliation-${this.body.id}`,
|
||||
'notification_ip_matched_affiliation',
|
||||
expectedOpts
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,16 +1,3 @@
|
||||
/* eslint-disable
|
||||
n/handle-callback-err,
|
||||
max-len,
|
||||
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
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const { assert } = require('chai')
|
||||
const sinon = require('sinon')
|
||||
@@ -18,7 +5,6 @@ const modulePath = require('path').join(
|
||||
__dirname,
|
||||
'../../../../app/src/Features/Notifications/NotificationsHandler.js'
|
||||
)
|
||||
const _ = require('lodash')
|
||||
|
||||
describe('NotificationsHandler', function () {
|
||||
const userId = '123nd3ijdks'
|
||||
@@ -27,18 +13,18 @@ describe('NotificationsHandler', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
this.request = sinon.stub().callsArgWith(1)
|
||||
return (this.handler = SandboxedModule.require(modulePath, {
|
||||
this.handler = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'@overleaf/settings': {
|
||||
apis: { notifications: { url: notificationUrl } },
|
||||
},
|
||||
request: this.request,
|
||||
},
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
describe('getUserNotifications', function () {
|
||||
it('should get unread notifications', function (done) {
|
||||
it('should get unread notifications', async function () {
|
||||
const stubbedNotifications = [{ _id: notificationId, user_id: userId }]
|
||||
this.request.callsArgWith(
|
||||
1,
|
||||
@@ -46,51 +32,42 @@ describe('NotificationsHandler', function () {
|
||||
{ statusCode: 200 },
|
||||
stubbedNotifications
|
||||
)
|
||||
return this.handler.getUserNotifications(
|
||||
userId,
|
||||
(err, unreadNotifications) => {
|
||||
stubbedNotifications.should.deep.equal(unreadNotifications)
|
||||
const getOpts = {
|
||||
uri: `${notificationUrl}/user/${userId}`,
|
||||
json: true,
|
||||
timeout: 1000,
|
||||
method: 'GET',
|
||||
}
|
||||
this.request.calledWith(getOpts).should.equal(true)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const unreadNotifications =
|
||||
await this.handler.promises.getUserNotifications(userId)
|
||||
stubbedNotifications.should.deep.equal(unreadNotifications)
|
||||
const getOpts = {
|
||||
uri: `${notificationUrl}/user/${userId}`,
|
||||
json: true,
|
||||
timeout: 1000,
|
||||
method: 'GET',
|
||||
}
|
||||
this.request.calledWith(getOpts).should.equal(true)
|
||||
})
|
||||
|
||||
it('should return empty arrays if there are no notifications', function () {
|
||||
it('should return empty arrays if there are no notifications', async function () {
|
||||
this.request.callsArgWith(1, null, { statusCode: 200 }, null)
|
||||
return this.handler.getUserNotifications(
|
||||
userId,
|
||||
(err, unreadNotifications) => {
|
||||
return unreadNotifications.length.should.equal(0)
|
||||
}
|
||||
)
|
||||
const unreadNotifications =
|
||||
await this.handler.promises.getUserNotifications(userId)
|
||||
unreadNotifications.length.should.equal(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('markAsRead', function () {
|
||||
beforeEach(function () {
|
||||
return (this.key = 'some key here')
|
||||
this.key = 'some key here'
|
||||
})
|
||||
|
||||
it('should send a delete request when a delete has been received to mark a notification', function (done) {
|
||||
return this.handler.markAsReadWithKey(userId, this.key, () => {
|
||||
const opts = {
|
||||
uri: `${notificationUrl}/user/${userId}`,
|
||||
json: {
|
||||
key: this.key,
|
||||
},
|
||||
timeout: 1000,
|
||||
method: 'DELETE',
|
||||
}
|
||||
this.request.calledWith(opts).should.equal(true)
|
||||
return done()
|
||||
})
|
||||
it('should send a delete request when a delete has been received to mark a notification', async function () {
|
||||
await this.handler.promises.markAsReadWithKey(userId, this.key)
|
||||
const opts = {
|
||||
uri: `${notificationUrl}/user/${userId}`,
|
||||
json: {
|
||||
key: this.key,
|
||||
},
|
||||
timeout: 1000,
|
||||
method: 'DELETE',
|
||||
}
|
||||
this.request.calledWith(opts).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -99,30 +76,27 @@ describe('NotificationsHandler', function () {
|
||||
this.key = 'some key here'
|
||||
this.messageOpts = { value: 12344 }
|
||||
this.templateKey = 'renderThisHtml'
|
||||
return (this.expiry = null)
|
||||
this.expiry = null
|
||||
})
|
||||
|
||||
it('should post the message over', function (done) {
|
||||
return this.handler.createNotification(
|
||||
it('should post the message over', async function () {
|
||||
await this.handler.promises.createNotification(
|
||||
userId,
|
||||
this.key,
|
||||
this.templateKey,
|
||||
this.messageOpts,
|
||||
this.expiry,
|
||||
() => {
|
||||
const args = this.request.args[0][0]
|
||||
args.uri.should.equal(`${notificationUrl}/user/${userId}`)
|
||||
args.timeout.should.equal(1000)
|
||||
const expectedJson = {
|
||||
key: this.key,
|
||||
templateKey: this.templateKey,
|
||||
messageOpts: this.messageOpts,
|
||||
forceCreate: true,
|
||||
}
|
||||
assert.deepEqual(args.json, expectedJson)
|
||||
return done()
|
||||
}
|
||||
this.expiry
|
||||
)
|
||||
const args = this.request.args[0][0]
|
||||
args.uri.should.equal(`${notificationUrl}/user/${userId}`)
|
||||
args.timeout.should.equal(1000)
|
||||
const expectedJson = {
|
||||
key: this.key,
|
||||
templateKey: this.templateKey,
|
||||
messageOpts: this.messageOpts,
|
||||
forceCreate: true,
|
||||
}
|
||||
assert.deepEqual(args.json, expectedJson)
|
||||
})
|
||||
|
||||
describe('when expiry date is supplied', function () {
|
||||
@@ -130,50 +104,46 @@ describe('NotificationsHandler', function () {
|
||||
this.key = 'some key here'
|
||||
this.messageOpts = { value: 12344 }
|
||||
this.templateKey = 'renderThisHtml'
|
||||
return (this.expiry = new Date())
|
||||
this.expiry = new Date()
|
||||
})
|
||||
|
||||
it('should post the message over with expiry field', function (done) {
|
||||
return this.handler.createNotification(
|
||||
it('should post the message over with expiry field', async function () {
|
||||
await this.handler.promises.createNotification(
|
||||
userId,
|
||||
this.key,
|
||||
this.templateKey,
|
||||
this.messageOpts,
|
||||
this.expiry,
|
||||
() => {
|
||||
const args = this.request.args[0][0]
|
||||
args.uri.should.equal(`${notificationUrl}/user/${userId}`)
|
||||
args.timeout.should.equal(1000)
|
||||
const expectedJson = {
|
||||
key: this.key,
|
||||
templateKey: this.templateKey,
|
||||
messageOpts: this.messageOpts,
|
||||
expires: this.expiry,
|
||||
forceCreate: true,
|
||||
}
|
||||
assert.deepEqual(args.json, expectedJson)
|
||||
return done()
|
||||
}
|
||||
this.expiry
|
||||
)
|
||||
|
||||
const args = this.request.args[0][0]
|
||||
args.uri.should.equal(`${notificationUrl}/user/${userId}`)
|
||||
args.timeout.should.equal(1000)
|
||||
const expectedJson = {
|
||||
key: this.key,
|
||||
templateKey: this.templateKey,
|
||||
messageOpts: this.messageOpts,
|
||||
expires: this.expiry,
|
||||
forceCreate: true,
|
||||
}
|
||||
assert.deepEqual(args.json, expectedJson)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('markAsReadByKeyOnly', function () {
|
||||
beforeEach(function () {
|
||||
return (this.key = 'some key here')
|
||||
this.key = 'some key here'
|
||||
})
|
||||
|
||||
it('should send a delete request when a delete has been received to mark a notification', function (done) {
|
||||
return this.handler.markAsReadByKeyOnly(this.key, () => {
|
||||
const opts = {
|
||||
uri: `${notificationUrl}/key/${this.key}`,
|
||||
timeout: 1000,
|
||||
method: 'DELETE',
|
||||
}
|
||||
this.request.calledWith(opts).should.equal(true)
|
||||
return done()
|
||||
})
|
||||
it('should send a delete request when a delete has been received to mark a notification', async function () {
|
||||
await this.handler.promises.markAsReadByKeyOnly(this.key)
|
||||
const opts = {
|
||||
uri: `${notificationUrl}/key/${this.key}`,
|
||||
timeout: 1000,
|
||||
method: 'DELETE',
|
||||
}
|
||||
this.request.calledWith(opts).should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -430,14 +430,15 @@ describe('ProjectEntityHandler', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the callback with the lines, version and rev', function (done) {
|
||||
this.ProjectEntityHandler.getDoc(projectId, docId, doc => {
|
||||
this.DocstoreManager.promises.getDoc
|
||||
.calledWith(projectId, docId)
|
||||
.should.equal(true)
|
||||
expect(doc).to.exist
|
||||
done()
|
||||
})
|
||||
it('should call the callback with the lines, version and rev', async function () {
|
||||
const doc = await this.ProjectEntityHandler.promises.getDoc(
|
||||
projectId,
|
||||
docId
|
||||
)
|
||||
this.DocstoreManager.promises.getDoc
|
||||
.calledWith(projectId, docId)
|
||||
.should.equal(true)
|
||||
expect(doc).to.exist
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,6 @@ const sinon = require('sinon')
|
||||
const Errors = require('../../../../app/src/Features/Errors/Errors')
|
||||
|
||||
const project = { _id: '1234566', rootFolder: [] }
|
||||
class Project {}
|
||||
const rootDoc = { name: 'rootDoc', _id: 'das239djd' }
|
||||
const doc1 = { name: 'otherDoc.txt', _id: 'dsad2ddd' }
|
||||
const doc2 = { name: 'docname.txt', _id: 'dsad2ddddd' }
|
||||
@@ -40,9 +39,6 @@ project.rootDoc_id = rootDoc._id
|
||||
|
||||
describe('ProjectLocator', function () {
|
||||
beforeEach(function () {
|
||||
Project.findById = (projectId, callback) => {
|
||||
callback(null, project)
|
||||
}
|
||||
this.ProjectGetter = {
|
||||
getProject: sinon.stub().callsArgWith(2, null, project),
|
||||
}
|
||||
@@ -53,7 +49,6 @@ describe('ProjectLocator', function () {
|
||||
}
|
||||
this.locator = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'../../models/Project': { Project },
|
||||
'../../models/User': { User: this.User },
|
||||
'./ProjectGetter': this.ProjectGetter,
|
||||
'./ProjectHelper': this.ProjectHelper,
|
||||
@@ -62,170 +57,152 @@ describe('ProjectLocator', function () {
|
||||
})
|
||||
|
||||
describe('finding a doc', function () {
|
||||
it('finds one at the root level', function (done) {
|
||||
this.locator.findElement(
|
||||
{ project_id: project._id, element_id: doc2._id, type: 'docs' },
|
||||
(err, foundElement, path, parentFolder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
foundElement._id.should.equal(doc2._id)
|
||||
path.fileSystem.should.equal(`/${doc2.name}`)
|
||||
parentFolder._id.should.equal(project.rootFolder[0]._id)
|
||||
path.mongo.should.equal('rootFolder.0.docs.1')
|
||||
done()
|
||||
it('finds one at the root level', async function () {
|
||||
const { element, path, folder } = await this.locator.promises.findElement(
|
||||
{
|
||||
project_id: project._id,
|
||||
element_id: doc2._id,
|
||||
type: 'docs',
|
||||
}
|
||||
)
|
||||
element._id.should.equal(doc2._id)
|
||||
path.fileSystem.should.equal(`/${doc2.name}`)
|
||||
folder._id.should.equal(project.rootFolder[0]._id)
|
||||
path.mongo.should.equal('rootFolder.0.docs.1')
|
||||
})
|
||||
|
||||
it('when it is nested', function (done) {
|
||||
this.locator.findElement(
|
||||
{ project_id: project._id, element_id: subSubDoc._id, type: 'doc' },
|
||||
(err, foundElement, path, parentFolder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
expect(foundElement._id).to.equal(subSubDoc._id)
|
||||
path.fileSystem.should.equal(
|
||||
`/${subFolder.name}/${secondSubFolder.name}/${subSubDoc.name}`
|
||||
)
|
||||
parentFolder._id.should.equal(secondSubFolder._id)
|
||||
path.mongo.should.equal('rootFolder.0.folders.1.folders.0.docs.0')
|
||||
done()
|
||||
it('when it is nested', async function () {
|
||||
const { element, path, folder } = await this.locator.promises.findElement(
|
||||
{
|
||||
project_id: project._id,
|
||||
element_id: subSubDoc._id,
|
||||
type: 'doc',
|
||||
}
|
||||
)
|
||||
expect(element._id).to.equal(subSubDoc._id)
|
||||
path.fileSystem.should.equal(
|
||||
`/${subFolder.name}/${secondSubFolder.name}/${subSubDoc.name}`
|
||||
)
|
||||
folder._id.should.equal(secondSubFolder._id)
|
||||
path.mongo.should.equal('rootFolder.0.folders.1.folders.0.docs.0')
|
||||
})
|
||||
|
||||
it('should give error if element could not be found', function (done) {
|
||||
this.locator.findElement(
|
||||
{ project_id: project._id, element_id: 'ddsd432nj42', type: 'docs' },
|
||||
(err, foundElement, path, parentFolder) => {
|
||||
expect(err).to.be.instanceOf(Errors.NotFoundError)
|
||||
expect(err).to.have.property('message', 'entity not found')
|
||||
done()
|
||||
}
|
||||
it('should give error if element could not be found', async function () {
|
||||
await expect(
|
||||
this.locator.promises.findElement({
|
||||
project_id: project._id,
|
||||
element_id: 'ddsd432nj42',
|
||||
type: 'docs',
|
||||
})
|
||||
)
|
||||
.to.eventually.be.rejectedWith(Errors.NotFoundError)
|
||||
.and.eventually.have.property('message', 'entity not found')
|
||||
})
|
||||
})
|
||||
|
||||
describe('finding a folder', function () {
|
||||
it('should return root folder when looking for root folder', function (done) {
|
||||
this.locator.findElement(
|
||||
{ project_id: project._id, element_id: rootFolder._id, type: 'folder' },
|
||||
(err, foundElement, path, parentFolder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
foundElement._id.should.equal(rootFolder._id)
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it('when at root', function (done) {
|
||||
this.locator.findElement(
|
||||
{ project_id: project._id, element_id: subFolder._id, type: 'folder' },
|
||||
(err, foundElement, path, parentFolder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
foundElement._id.should.equal(subFolder._id)
|
||||
path.fileSystem.should.equal(`/${subFolder.name}`)
|
||||
parentFolder._id.should.equal(rootFolder._id)
|
||||
path.mongo.should.equal('rootFolder.0.folders.1')
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it('when deeply nested', function (done) {
|
||||
this.locator.findElement(
|
||||
it('should return root folder when looking for root folder', async function () {
|
||||
const { element: foundElement } = await this.locator.promises.findElement(
|
||||
{
|
||||
project_id: project._id,
|
||||
element_id: secondSubFolder._id,
|
||||
element_id: rootFolder._id,
|
||||
type: 'folder',
|
||||
},
|
||||
(err, foundElement, path, parentFolder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
foundElement._id.should.equal(secondSubFolder._id)
|
||||
path.fileSystem.should.equal(
|
||||
`/${subFolder.name}/${secondSubFolder.name}`
|
||||
)
|
||||
parentFolder._id.should.equal(subFolder._id)
|
||||
path.mongo.should.equal('rootFolder.0.folders.1.folders.0')
|
||||
done()
|
||||
}
|
||||
)
|
||||
foundElement._id.should.equal(rootFolder._id)
|
||||
})
|
||||
|
||||
it('when at root', async function () {
|
||||
const {
|
||||
element: foundElement,
|
||||
path,
|
||||
folder: parentFolder,
|
||||
} = await this.locator.promises.findElement({
|
||||
project_id: project._id,
|
||||
element_id: subFolder._id,
|
||||
type: 'folder',
|
||||
})
|
||||
foundElement._id.should.equal(subFolder._id)
|
||||
path.fileSystem.should.equal(`/${subFolder.name}`)
|
||||
parentFolder._id.should.equal(rootFolder._id)
|
||||
path.mongo.should.equal('rootFolder.0.folders.1')
|
||||
})
|
||||
|
||||
it('when deeply nested', async function () {
|
||||
const {
|
||||
element: foundElement,
|
||||
path,
|
||||
folder: parentFolder,
|
||||
} = await this.locator.promises.findElement({
|
||||
project_id: project._id,
|
||||
element_id: secondSubFolder._id,
|
||||
type: 'folder',
|
||||
})
|
||||
|
||||
foundElement._id.should.equal(secondSubFolder._id)
|
||||
path.fileSystem.should.equal(`/${subFolder.name}/${secondSubFolder.name}`)
|
||||
parentFolder._id.should.equal(subFolder._id)
|
||||
path.mongo.should.equal('rootFolder.0.folders.1.folders.0')
|
||||
})
|
||||
})
|
||||
|
||||
describe('finding a file', function () {
|
||||
it('when at root', function (done) {
|
||||
this.locator.findElement(
|
||||
{ project_id: project._id, element_id: file1._id, type: 'fileRefs' },
|
||||
(err, foundElement, path, parentFolder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
foundElement._id.should.equal(file1._id)
|
||||
path.fileSystem.should.equal(`/${file1.name}`)
|
||||
parentFolder._id.should.equal(rootFolder._id)
|
||||
path.mongo.should.equal('rootFolder.0.fileRefs.0')
|
||||
done()
|
||||
}
|
||||
)
|
||||
it('when at root', async function () {
|
||||
const {
|
||||
element: foundElement,
|
||||
path,
|
||||
folder: parentFolder,
|
||||
} = await this.locator.promises.findElement({
|
||||
project_id: project._id,
|
||||
element_id: file1._id,
|
||||
type: 'fileRefs',
|
||||
})
|
||||
foundElement._id.should.equal(file1._id)
|
||||
path.fileSystem.should.equal(`/${file1.name}`)
|
||||
parentFolder._id.should.equal(rootFolder._id)
|
||||
path.mongo.should.equal('rootFolder.0.fileRefs.0')
|
||||
})
|
||||
|
||||
it('when deeply nested', function (done) {
|
||||
this.locator.findElement(
|
||||
{
|
||||
project_id: project._id,
|
||||
element_id: subSubFile._id,
|
||||
type: 'fileRefs',
|
||||
},
|
||||
(err, foundElement, path, parentFolder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
foundElement._id.should.equal(subSubFile._id)
|
||||
path.fileSystem.should.equal(
|
||||
`/${subFolder.name}/${secondSubFolder.name}/${subSubFile.name}`
|
||||
)
|
||||
parentFolder._id.should.equal(secondSubFolder._id)
|
||||
path.mongo.should.equal('rootFolder.0.folders.1.folders.0.fileRefs.0')
|
||||
done()
|
||||
}
|
||||
it('when deeply nested', async function () {
|
||||
const {
|
||||
element: foundElement,
|
||||
path,
|
||||
folder: parentFolder,
|
||||
} = await this.locator.promises.findElement({
|
||||
project_id: project._id,
|
||||
element_id: subSubFile._id,
|
||||
type: 'fileRefs',
|
||||
})
|
||||
foundElement._id.should.equal(subSubFile._id)
|
||||
path.fileSystem.should.equal(
|
||||
`/${subFolder.name}/${secondSubFolder.name}/${subSubFile.name}`
|
||||
)
|
||||
parentFolder._id.should.equal(secondSubFolder._id)
|
||||
path.mongo.should.equal('rootFolder.0.folders.1.folders.0.fileRefs.0')
|
||||
})
|
||||
})
|
||||
|
||||
describe('finding an element with wrong element type', function () {
|
||||
it('should add an s onto the element type', function (done) {
|
||||
this.locator.findElement(
|
||||
{ project_id: project._id, element_id: subSubDoc._id, type: 'doc' },
|
||||
(err, foundElement, path, parentFolder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
foundElement._id.should.equal(subSubDoc._id)
|
||||
done()
|
||||
it('should add an s onto the element type', async function () {
|
||||
const { element: foundElement } = await this.locator.promises.findElement(
|
||||
{
|
||||
project_id: project._id,
|
||||
element_id: subSubDoc._id,
|
||||
type: 'doc',
|
||||
}
|
||||
)
|
||||
foundElement._id.should.equal(subSubDoc._id)
|
||||
})
|
||||
|
||||
it('should convert file to fileRefs', function (done) {
|
||||
this.locator.findElement(
|
||||
{ project_id: project._id, element_id: file1._id, type: 'fileRefs' },
|
||||
(err, foundElement, path, parentFolder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
foundElement._id.should.equal(file1._id)
|
||||
done()
|
||||
it('should convert file to fileRefs', async function () {
|
||||
const { element: foundElement } = await this.locator.promises.findElement(
|
||||
{
|
||||
project_id: project._id,
|
||||
element_id: file1._id,
|
||||
type: 'fileRefs',
|
||||
}
|
||||
)
|
||||
foundElement._id.should.equal(file1._id)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -242,233 +219,173 @@ describe('ProjectLocator', function () {
|
||||
_id: '1234566',
|
||||
rootFolder: [rootFolder2],
|
||||
}
|
||||
it('should find doc in project', function (done) {
|
||||
this.locator.findElement(
|
||||
{ project: project2, element_id: doc3._id, type: 'docs' },
|
||||
(err, foundElement, path, parentFolder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
foundElement._id.should.equal(doc3._id)
|
||||
path.fileSystem.should.equal(`/${doc3.name}`)
|
||||
parentFolder._id.should.equal(project2.rootFolder[0]._id)
|
||||
path.mongo.should.equal('rootFolder.0.docs.0')
|
||||
done()
|
||||
}
|
||||
)
|
||||
it('should find doc in project', async function () {
|
||||
const {
|
||||
element: foundElement,
|
||||
path,
|
||||
folder: parentFolder,
|
||||
} = await this.locator.promises.findElement({
|
||||
project: project2,
|
||||
element_id: doc3._id,
|
||||
type: 'docs',
|
||||
})
|
||||
foundElement._id.should.equal(doc3._id)
|
||||
path.fileSystem.should.equal(`/${doc3.name}`)
|
||||
parentFolder._id.should.equal(project2.rootFolder[0]._id)
|
||||
path.mongo.should.equal('rootFolder.0.docs.0')
|
||||
})
|
||||
})
|
||||
|
||||
describe('finding root doc', function () {
|
||||
it('should return root doc when passed project', function (done) {
|
||||
this.locator.findRootDoc(project, (err, doc) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
doc._id.should.equal(rootDoc._id)
|
||||
done()
|
||||
})
|
||||
it('should return root doc when passed project', async function () {
|
||||
const { element: doc } = await this.locator.promises.findRootDoc(project)
|
||||
doc._id.should.equal(rootDoc._id)
|
||||
})
|
||||
|
||||
it('should return root doc when passed project_id', function (done) {
|
||||
this.locator.findRootDoc(project._id, (err, doc) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
doc._id.should.equal(rootDoc._id)
|
||||
done()
|
||||
})
|
||||
it('should return root doc when passed project_id', async function () {
|
||||
const { element: doc } = await this.locator.promises.findRootDoc(
|
||||
project._id
|
||||
)
|
||||
doc._id.should.equal(rootDoc._id)
|
||||
})
|
||||
|
||||
it('should return null when the project has no rootDoc', function (done) {
|
||||
it('should return null when the project has no rootDoc', async function () {
|
||||
project.rootDoc_id = null
|
||||
this.locator.findRootDoc(project, (err, doc) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
expect(doc).to.equal(null)
|
||||
done()
|
||||
})
|
||||
const { element: rootDoc } =
|
||||
await this.locator.promises.findRootDoc(project)
|
||||
expect(rootDoc).to.equal(null)
|
||||
})
|
||||
|
||||
it('should return null when the rootDoc_id no longer exists', function (done) {
|
||||
it('should return null when the rootDoc_id no longer exists', async function () {
|
||||
project.rootDoc_id = 'doesntexist'
|
||||
this.locator.findRootDoc(project, (err, doc) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
expect(doc).to.equal(null)
|
||||
done()
|
||||
})
|
||||
const { element: rootDoc } =
|
||||
await this.locator.promises.findRootDoc(project)
|
||||
expect(rootDoc).to.equal(null)
|
||||
})
|
||||
})
|
||||
|
||||
describe('findElementByPath', function () {
|
||||
it('should take a doc path and return the element for a root level document', function (done) {
|
||||
it('should take a doc path and return the element for a root level document', async function () {
|
||||
const path = `${doc1.name}`
|
||||
this.locator.findElementByPath(
|
||||
{ project, path },
|
||||
(err, element, type, folder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
element.should.deep.equal(doc1)
|
||||
expect(type).to.equal('doc')
|
||||
expect(folder).to.equal(rootFolder)
|
||||
done()
|
||||
}
|
||||
)
|
||||
const { element, type, folder } =
|
||||
await this.locator.promises.findElementByPath({
|
||||
project,
|
||||
path,
|
||||
})
|
||||
element.should.deep.equal(doc1)
|
||||
expect(type).to.equal('doc')
|
||||
expect(folder).to.equal(rootFolder)
|
||||
})
|
||||
|
||||
it('should take a doc path and return the element for a root level document with a starting slash', function (done) {
|
||||
it('should take a doc path and return the element for a root level document with a starting slash', async function () {
|
||||
const path = `/${doc1.name}`
|
||||
this.locator.findElementByPath(
|
||||
{ project, path },
|
||||
(err, element, type, folder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
element.should.deep.equal(doc1)
|
||||
expect(type).to.equal('doc')
|
||||
expect(folder).to.equal(rootFolder)
|
||||
done()
|
||||
}
|
||||
)
|
||||
const { element, type, folder } =
|
||||
await this.locator.promises.findElementByPath({
|
||||
project,
|
||||
path,
|
||||
})
|
||||
element.should.deep.equal(doc1)
|
||||
expect(type).to.equal('doc')
|
||||
expect(folder).to.equal(rootFolder)
|
||||
})
|
||||
|
||||
it('should take a doc path and return the element for a nested document', function (done) {
|
||||
it('should take a doc path and return the element for a nested document', async function () {
|
||||
const path = `${subFolder.name}/${secondSubFolder.name}/${subSubDoc.name}`
|
||||
this.locator.findElementByPath(
|
||||
{ project, path },
|
||||
(err, element, type, folder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
element.should.deep.equal(subSubDoc)
|
||||
expect(type).to.equal('doc')
|
||||
expect(folder).to.equal(secondSubFolder)
|
||||
done()
|
||||
}
|
||||
)
|
||||
const { element, type, folder } =
|
||||
await this.locator.promises.findElementByPath({
|
||||
project,
|
||||
path,
|
||||
})
|
||||
element.should.deep.equal(subSubDoc)
|
||||
expect(type).to.equal('doc')
|
||||
expect(folder).to.equal(secondSubFolder)
|
||||
})
|
||||
|
||||
it('should take a file path and return the element for a root level document', function (done) {
|
||||
it('should take a file path and return the element for a root level document', async function () {
|
||||
const path = `${file1.name}`
|
||||
this.locator.findElementByPath(
|
||||
{ project, path },
|
||||
(err, element, type, folder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
element.should.deep.equal(file1)
|
||||
expect(type).to.equal('file')
|
||||
expect(folder).to.equal(rootFolder)
|
||||
done()
|
||||
}
|
||||
)
|
||||
const { element, type, folder } =
|
||||
await this.locator.promises.findElementByPath({
|
||||
project,
|
||||
path,
|
||||
})
|
||||
element.should.deep.equal(file1)
|
||||
expect(type).to.equal('file')
|
||||
expect(folder).to.equal(rootFolder)
|
||||
})
|
||||
|
||||
it('should take a file path and return the element for a nested document', function (done) {
|
||||
it('should take a file path and return the element for a nested document', async function () {
|
||||
const path = `${subFolder.name}/${secondSubFolder.name}/${subSubFile.name}`
|
||||
this.locator.findElementByPath(
|
||||
{ project, path },
|
||||
(err, element, type, folder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
element.should.deep.equal(subSubFile)
|
||||
expect(type).to.equal('file')
|
||||
expect(folder).to.equal(secondSubFolder)
|
||||
done()
|
||||
}
|
||||
)
|
||||
const { element, type, folder } =
|
||||
await this.locator.promises.findElementByPath({
|
||||
project,
|
||||
path,
|
||||
})
|
||||
element.should.deep.equal(subSubFile)
|
||||
expect(type).to.equal('file')
|
||||
expect(folder).to.equal(secondSubFolder)
|
||||
})
|
||||
|
||||
it('should take a file path and return the element for a nested document case insenstive', function (done) {
|
||||
it('should take a file path and return the element for a nested document case insenstive', async function () {
|
||||
const path = `${subFolder.name.toUpperCase()}/${secondSubFolder.name.toUpperCase()}/${subSubFile.name.toUpperCase()}`
|
||||
this.locator.findElementByPath(
|
||||
{ project, path },
|
||||
(err, element, type, folder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
element.should.deep.equal(subSubFile)
|
||||
expect(type).to.equal('file')
|
||||
expect(folder).to.equal(secondSubFolder)
|
||||
done()
|
||||
}
|
||||
)
|
||||
const { element, type, folder } =
|
||||
await this.locator.promises.findElementByPath({
|
||||
project,
|
||||
path,
|
||||
})
|
||||
element.should.deep.equal(subSubFile)
|
||||
expect(type).to.equal('file')
|
||||
expect(folder).to.equal(secondSubFolder)
|
||||
})
|
||||
|
||||
it('should not return elements with a case-insensitive match when exactCaseMatch is true', function (done) {
|
||||
it('should not return elements with a case-insensitive match when exactCaseMatch is true', async function () {
|
||||
const path = `${subFolder.name.toUpperCase()}/${secondSubFolder.name.toUpperCase()}/${subSubFile.name.toUpperCase()}`
|
||||
this.locator.findElementByPath(
|
||||
{ project, path, exactCaseMatch: true },
|
||||
(err, element, type, folder) => {
|
||||
err.should.not.equal(undefined)
|
||||
expect(element).to.be.undefined
|
||||
expect(type).to.be.undefined
|
||||
done()
|
||||
}
|
||||
)
|
||||
await expect(
|
||||
this.locator.promises.findElementByPath({
|
||||
project,
|
||||
path,
|
||||
exactCaseMatch: true,
|
||||
})
|
||||
).to.eventually.be.rejected
|
||||
})
|
||||
|
||||
it('should take a file path and return the element for a nested folder', function (done) {
|
||||
it('should take a file path and return the element for a nested folder', async function () {
|
||||
const path = `${subFolder.name}/${secondSubFolder.name}`
|
||||
this.locator.findElementByPath(
|
||||
{ project, path },
|
||||
(err, element, type, folder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
element.should.deep.equal(secondSubFolder)
|
||||
expect(type).to.equal('folder')
|
||||
expect(folder).to.equal(subFolder)
|
||||
done()
|
||||
}
|
||||
)
|
||||
const { element, type, folder } =
|
||||
await this.locator.promises.findElementByPath({
|
||||
project,
|
||||
path,
|
||||
})
|
||||
element.should.deep.equal(secondSubFolder)
|
||||
expect(type).to.equal('folder')
|
||||
expect(folder).to.equal(subFolder)
|
||||
})
|
||||
|
||||
it('should take a file path and return the root folder', function (done) {
|
||||
it('should take a file path and return the root folder', async function () {
|
||||
const path = '/'
|
||||
this.locator.findElementByPath(
|
||||
{ project, path },
|
||||
(err, element, type, folder) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
element.should.deep.equal(rootFolder)
|
||||
expect(type).to.equal('folder')
|
||||
expect(folder).to.equal(null)
|
||||
done()
|
||||
}
|
||||
)
|
||||
const { element, type, folder } =
|
||||
await this.locator.promises.findElementByPath({
|
||||
project,
|
||||
path,
|
||||
})
|
||||
element.should.deep.equal(rootFolder)
|
||||
expect(type).to.equal('folder')
|
||||
expect(folder).to.equal(null)
|
||||
})
|
||||
|
||||
it('should return an error if the file can not be found inside know folder', function (done) {
|
||||
it('should return an error if the file can not be found inside know folder', async function () {
|
||||
const path = `${subFolder.name}/${secondSubFolder.name}/exist.txt`
|
||||
this.locator.findElementByPath(
|
||||
{ project, path },
|
||||
(err, element, type) => {
|
||||
err.should.not.equal(undefined)
|
||||
expect(element).to.be.undefined
|
||||
expect(type).to.be.undefined
|
||||
done()
|
||||
}
|
||||
)
|
||||
await expect(this.locator.promises.findElementByPath({ project, path }))
|
||||
.to.eventually.be.rejected
|
||||
})
|
||||
|
||||
it('should return an error if the file can not be found inside unknown folder', function (done) {
|
||||
it('should return an error if the file can not be found inside unknown folder', async function () {
|
||||
const path = 'this/does/not/exist.txt'
|
||||
this.locator.findElementByPath(
|
||||
{ project, path },
|
||||
(err, element, type) => {
|
||||
err.should.not.equal(undefined)
|
||||
expect(element).to.be.undefined
|
||||
expect(type).to.be.undefined
|
||||
done()
|
||||
}
|
||||
)
|
||||
await expect(
|
||||
this.locator.promises.findElementByPath({
|
||||
project,
|
||||
path,
|
||||
})
|
||||
).to.eventually.be.rejected
|
||||
})
|
||||
|
||||
describe('where duplicate folder exists', function () {
|
||||
@@ -498,18 +415,20 @@ describe('ProjectLocator', function () {
|
||||
}
|
||||
})
|
||||
|
||||
it('should not call the callback more than once', function (done) {
|
||||
it('should not call the callback more than once', async function () {
|
||||
const path = `${this.duplicateFolder.name}/${this.doc.name}`
|
||||
this.locator.findElementByPath({ project: this.project, path }, () =>
|
||||
done()
|
||||
)
|
||||
await this.locator.promises.findElementByPath({
|
||||
project: this.project,
|
||||
path,
|
||||
})
|
||||
}) // mocha will throw exception if done called multiple times
|
||||
|
||||
it('should not call the callback more than once when the path is longer than 1 level below the duplicate level', function (done) {
|
||||
it('should not call the callback more than once when the path is longer than 1 level below the duplicate level', async function () {
|
||||
const path = `${this.duplicateFolder.name}/1/main.tex`
|
||||
this.locator.findElementByPath({ project: this.project, path }, () =>
|
||||
done()
|
||||
)
|
||||
await this.locator.promises.findElementByPath({
|
||||
project: this.project,
|
||||
path,
|
||||
})
|
||||
})
|
||||
}) // mocha will throw exception if done called multiple times
|
||||
|
||||
@@ -526,18 +445,13 @@ describe('ProjectLocator', function () {
|
||||
}
|
||||
})
|
||||
|
||||
it('should not crash with a null', function (done) {
|
||||
it('should not crash with a null', async function () {
|
||||
const path = '/other.tex'
|
||||
this.locator.findElementByPath(
|
||||
{ project: this.project, path },
|
||||
(err, element) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
element.name.should.equal('other.tex')
|
||||
done()
|
||||
}
|
||||
)
|
||||
const { element } = await this.locator.promises.findElementByPath({
|
||||
project: this.project,
|
||||
path,
|
||||
})
|
||||
element.name.should.equal('other.tex')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -546,35 +460,31 @@ describe('ProjectLocator', function () {
|
||||
this.ProjectGetter = { getProject: sinon.stub().callsArg(2) }
|
||||
})
|
||||
|
||||
it('should not crash with a null', function (done) {
|
||||
it('should not crash with a null', async function () {
|
||||
const path = '/other.tex'
|
||||
this.locator.findElementByPath(
|
||||
{ project_id: project._id, path },
|
||||
(err, element) => {
|
||||
expect(err).to.exist
|
||||
done()
|
||||
}
|
||||
)
|
||||
await expect(
|
||||
this.locator.promises.findElementByPath({
|
||||
project_id: project._id,
|
||||
path,
|
||||
})
|
||||
).to.be.rejected
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a project_id', function () {
|
||||
it('should take a doc path and return the element for a root level document', function (done) {
|
||||
it('should take a doc path and return the element for a root level document', async function () {
|
||||
const path = `${doc1.name}`
|
||||
this.locator.findElementByPath(
|
||||
{ project_id: project._id, path },
|
||||
(err, element, type) => {
|
||||
if (err != null) {
|
||||
return done(err)
|
||||
}
|
||||
this.ProjectGetter.getProject
|
||||
.calledWith(project._id, { rootFolder: true, rootDoc_id: true })
|
||||
.should.equal(true)
|
||||
element.should.deep.equal(doc1)
|
||||
expect(type).to.equal('doc')
|
||||
done()
|
||||
const { element, type } = await this.locator.promises.findElementByPath(
|
||||
{
|
||||
project_id: project._id,
|
||||
path,
|
||||
}
|
||||
)
|
||||
this.ProjectGetter.getProject
|
||||
.calledWith(project._id, { rootFolder: true, rootDoc_id: true })
|
||||
.should.equal(true)
|
||||
element.should.deep.equal(doc1)
|
||||
expect(type).to.equal('doc')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,16 +1,3 @@
|
||||
/* eslint-disable
|
||||
max-len,
|
||||
no-return-assign,
|
||||
no-unused-vars,
|
||||
no-useless-escape,
|
||||
*/
|
||||
// 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
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const { expect } = require('chai')
|
||||
const { ObjectId } = require('mongodb-legacy')
|
||||
const sinon = require('sinon')
|
||||
@@ -33,16 +20,13 @@ describe('ProjectRootDocManager', function () {
|
||||
this.sl_req_id = 'sl-req-id-123'
|
||||
this.callback = sinon.stub()
|
||||
this.globbyFiles = ['a.tex', 'b.tex', 'main.tex']
|
||||
this.globby = sinon.stub().returns(
|
||||
new Promise(resolve => {
|
||||
return resolve(this.globbyFiles)
|
||||
})
|
||||
)
|
||||
this.globby = sinon.stub().resolves(this.globbyFiles)
|
||||
|
||||
this.fs = {
|
||||
readFile: sinon.stub().callsArgWith(2, new Error('file not found')),
|
||||
stat: sinon.stub().callsArgWith(1, null, { size: 100 }),
|
||||
}
|
||||
return (this.ProjectRootDocManager = SandboxedModule.require(modulePath, {
|
||||
this.ProjectRootDocManager = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'./ProjectEntityHandler': (this.ProjectEntityHandler = {}),
|
||||
'./ProjectEntityUpdateHandler': (this.ProjectEntityUpdateHandler = {}),
|
||||
@@ -56,7 +40,7 @@ describe('ProjectRootDocManager', function () {
|
||||
globby: this.globby,
|
||||
fs: this.fs,
|
||||
},
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
describe('setRootDocAutomatically', function () {
|
||||
@@ -67,7 +51,7 @@ describe('ProjectRootDocManager', function () {
|
||||
.returns(true)
|
||||
})
|
||||
describe('when there is a suitable root doc', function () {
|
||||
beforeEach(function (done) {
|
||||
beforeEach(async function () {
|
||||
this.docs = {
|
||||
'/chapter1.tex': {
|
||||
_id: this.docId1,
|
||||
@@ -98,27 +82,26 @@ describe('ProjectRootDocManager', function () {
|
||||
this.ProjectEntityHandler.getAllDocs = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docs)
|
||||
this.ProjectRootDocManager.setRootDocAutomatically(
|
||||
this.project_id,
|
||||
done
|
||||
await this.ProjectRootDocManager.promises.setRootDocAutomatically(
|
||||
this.project_id
|
||||
)
|
||||
})
|
||||
|
||||
it('should check the docs of the project', function () {
|
||||
return this.ProjectEntityHandler.getAllDocs
|
||||
this.ProjectEntityHandler.getAllDocs
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should set the root doc to the doc containing a documentclass', function () {
|
||||
return this.ProjectEntityUpdateHandler.setRootDoc
|
||||
this.ProjectEntityUpdateHandler.setRootDoc
|
||||
.calledWith(this.project_id, this.docId2)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the root doc is an Rtex file', function () {
|
||||
beforeEach(function (done) {
|
||||
beforeEach(async function () {
|
||||
this.docs = {
|
||||
'/chapter1.tex': {
|
||||
_id: this.docId1,
|
||||
@@ -132,21 +115,20 @@ describe('ProjectRootDocManager', function () {
|
||||
this.ProjectEntityHandler.getAllDocs = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docs)
|
||||
return this.ProjectRootDocManager.setRootDocAutomatically(
|
||||
this.project_id,
|
||||
done
|
||||
await this.ProjectRootDocManager.promises.setRootDocAutomatically(
|
||||
this.project_id
|
||||
)
|
||||
})
|
||||
|
||||
it('should set the root doc to the doc containing a documentclass', function () {
|
||||
return this.ProjectEntityUpdateHandler.setRootDoc
|
||||
this.ProjectEntityUpdateHandler.setRootDoc
|
||||
.calledWith(this.project_id, this.docId2)
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when there is no suitable root doc', function () {
|
||||
beforeEach(function (done) {
|
||||
beforeEach(async function () {
|
||||
this.docs = {
|
||||
'/chapter1.tex': {
|
||||
_id: this.docId1,
|
||||
@@ -160,16 +142,13 @@ describe('ProjectRootDocManager', function () {
|
||||
this.ProjectEntityHandler.getAllDocs = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docs)
|
||||
return this.ProjectRootDocManager.setRootDocAutomatically(
|
||||
this.project_id,
|
||||
done
|
||||
await this.ProjectRootDocManager.promises.setRootDocAutomatically(
|
||||
this.project_id
|
||||
)
|
||||
})
|
||||
|
||||
it('should not set the root doc to the doc containing a documentclass', function () {
|
||||
return this.ProjectEntityUpdateHandler.setRootDoc.called.should.equal(
|
||||
false
|
||||
)
|
||||
this.ProjectEntityUpdateHandler.setRootDoc.called.should.equal(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -191,13 +170,13 @@ describe('ProjectRootDocManager', function () {
|
||||
this.fs.readFile
|
||||
.withArgs('/foo/a/a.tex')
|
||||
.callsArgWith(2, null, 'Potato? Potahto. Potootee!')
|
||||
return (this.documentclassContent = '% test\n\\documentclass\n% test')
|
||||
this.documentclassContent = '% test\n\\documentclass\n% test'
|
||||
})
|
||||
|
||||
describe('when there is a file in a subfolder', function () {
|
||||
beforeEach(function () {
|
||||
// have to splice globbyFiles weirdly because of the way the stubbed globby method handles references
|
||||
return this.globbyFiles.splice(
|
||||
this.globbyFiles.splice(
|
||||
0,
|
||||
this.globbyFiles.length,
|
||||
'c.tex',
|
||||
@@ -207,70 +186,56 @@ describe('ProjectRootDocManager', function () {
|
||||
)
|
||||
})
|
||||
|
||||
it('processes the root folder files first, and then the subfolder, in alphabetical order', function (done) {
|
||||
return this.ProjectRootDocManager.findRootDocFileFromDirectory(
|
||||
'/foo',
|
||||
(error, path) => {
|
||||
expect(error).not.to.exist
|
||||
expect(path).to.equal('a.tex')
|
||||
sinon.assert.callOrder(
|
||||
this.fs.readFile.withArgs('/foo/a.tex'),
|
||||
this.fs.readFile.withArgs('/foo/b.tex'),
|
||||
this.fs.readFile.withArgs('/foo/c.tex'),
|
||||
this.fs.readFile.withArgs('/foo/a/a.tex')
|
||||
)
|
||||
return done()
|
||||
}
|
||||
it('processes the root folder files first, and then the subfolder, in alphabetical order', async function () {
|
||||
const { path } =
|
||||
await this.ProjectRootDocManager.promises.findRootDocFileFromDirectory(
|
||||
'/foo'
|
||||
)
|
||||
expect(path).to.equal('a.tex')
|
||||
sinon.assert.callOrder(
|
||||
this.fs.readFile.withArgs('/foo/a.tex'),
|
||||
this.fs.readFile.withArgs('/foo/b.tex'),
|
||||
this.fs.readFile.withArgs('/foo/c.tex'),
|
||||
this.fs.readFile.withArgs('/foo/a/a.tex')
|
||||
)
|
||||
})
|
||||
|
||||
it('processes smaller files first', function (done) {
|
||||
it('processes smaller files first', async function () {
|
||||
this.fs.stat.withArgs('/foo/c.tex').callsArgWith(1, null, { size: 1 })
|
||||
return this.ProjectRootDocManager.findRootDocFileFromDirectory(
|
||||
'/foo',
|
||||
(error, path) => {
|
||||
expect(error).not.to.exist
|
||||
expect(path).to.equal('c.tex')
|
||||
sinon.assert.callOrder(
|
||||
this.fs.readFile.withArgs('/foo/c.tex'),
|
||||
this.fs.readFile.withArgs('/foo/a.tex'),
|
||||
this.fs.readFile.withArgs('/foo/b.tex'),
|
||||
this.fs.readFile.withArgs('/foo/a/a.tex')
|
||||
)
|
||||
return done()
|
||||
}
|
||||
const { path } =
|
||||
await this.ProjectRootDocManager.promises.findRootDocFileFromDirectory(
|
||||
'/foo'
|
||||
)
|
||||
expect(path).to.equal('c.tex')
|
||||
sinon.assert.callOrder(
|
||||
this.fs.readFile.withArgs('/foo/c.tex'),
|
||||
this.fs.readFile.withArgs('/foo/a.tex'),
|
||||
this.fs.readFile.withArgs('/foo/b.tex'),
|
||||
this.fs.readFile.withArgs('/foo/a/a.tex')
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when main.tex contains a documentclass', function () {
|
||||
beforeEach(function () {
|
||||
return this.fs.readFile
|
||||
this.fs.readFile
|
||||
.withArgs('/foo/main.tex')
|
||||
.callsArgWith(2, null, this.documentclassContent)
|
||||
})
|
||||
|
||||
it('returns main.tex', function (done) {
|
||||
return this.ProjectRootDocManager.findRootDocFileFromDirectory(
|
||||
'/foo',
|
||||
(error, path, content) => {
|
||||
expect(error).not.to.exist
|
||||
expect(path).to.equal('main.tex')
|
||||
expect(content).to.equal(this.documentclassContent)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
it('returns main.tex', async function () {
|
||||
const { path, content } =
|
||||
await this.ProjectRootDocManager.promises.findRootDocFileFromDirectory(
|
||||
'/foo'
|
||||
)
|
||||
expect(path).to.equal('main.tex')
|
||||
expect(content).to.equal(this.documentclassContent)
|
||||
})
|
||||
|
||||
it('processes main.text first and stops processing when it finds the content', function (done) {
|
||||
return this.ProjectRootDocManager.findRootDocFileFromDirectory(
|
||||
'/foo',
|
||||
() => {
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/main.tex')
|
||||
expect(this.fs.readFile).not.to.be.calledWith('/foo/a.tex')
|
||||
return done()
|
||||
}
|
||||
)
|
||||
it('processes main.text first and stops processing when it finds the content', async function () {
|
||||
await this.ProjectRootDocManager.findRootDocFileFromDirectory('/foo')
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/main.tex')
|
||||
expect(this.fs.readFile).not.to.be.calledWith('/foo/a.tex')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -284,7 +249,7 @@ describe('ProjectRootDocManager', function () {
|
||||
.callsArgWith(2, null, 'foo')
|
||||
})
|
||||
|
||||
it('returns the first .tex file from the root folder', function (done) {
|
||||
it('returns the first .tex file from the root folder', async function () {
|
||||
this.globbyFiles.splice(
|
||||
0,
|
||||
this.globbyFiles.length,
|
||||
@@ -293,18 +258,15 @@ describe('ProjectRootDocManager', function () {
|
||||
'nested/chapter1a.tex'
|
||||
)
|
||||
|
||||
this.ProjectRootDocManager.findRootDocFileFromDirectory(
|
||||
'/foo',
|
||||
(error, path, content) => {
|
||||
expect(error).not.to.exist
|
||||
expect(path).to.equal('a.tex')
|
||||
expect(content).to.equal('foo')
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const { path, content } =
|
||||
await this.ProjectRootDocManager.promises.findRootDocFileFromDirectory(
|
||||
'/foo'
|
||||
)
|
||||
expect(path).to.equal('a.tex')
|
||||
expect(content).to.equal('foo')
|
||||
})
|
||||
|
||||
it('returns main.tex file from the root folder', function (done) {
|
||||
it('returns main.tex file from the root folder', async function () {
|
||||
this.globbyFiles.splice(
|
||||
0,
|
||||
this.globbyFiles.length,
|
||||
@@ -314,227 +276,206 @@ describe('ProjectRootDocManager', function () {
|
||||
'nested/chapter1a.tex'
|
||||
)
|
||||
|
||||
this.ProjectRootDocManager.findRootDocFileFromDirectory(
|
||||
'/foo',
|
||||
(error, path, content) => {
|
||||
expect(error).not.to.exist
|
||||
expect(path).to.equal('main.tex')
|
||||
expect(content).to.equal('foo')
|
||||
return done()
|
||||
}
|
||||
)
|
||||
const { path, content } =
|
||||
await this.ProjectRootDocManager.promises.findRootDocFileFromDirectory(
|
||||
'/foo'
|
||||
)
|
||||
expect(path).to.equal('main.tex')
|
||||
expect(content).to.equal('foo')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when a.tex contains a documentclass', function () {
|
||||
beforeEach(function () {
|
||||
return this.fs.readFile
|
||||
this.fs.readFile
|
||||
.withArgs('/foo/a.tex')
|
||||
.callsArgWith(2, null, this.documentclassContent)
|
||||
})
|
||||
|
||||
it('returns a.tex', function (done) {
|
||||
return this.ProjectRootDocManager.findRootDocFileFromDirectory(
|
||||
'/foo',
|
||||
(error, path, content) => {
|
||||
expect(error).not.to.exist
|
||||
expect(path).to.equal('a.tex')
|
||||
expect(content).to.equal(this.documentclassContent)
|
||||
return done()
|
||||
}
|
||||
)
|
||||
it('returns a.tex', async function () {
|
||||
const { path, content } =
|
||||
await this.ProjectRootDocManager.promises.findRootDocFileFromDirectory(
|
||||
'/foo'
|
||||
)
|
||||
expect(path).to.equal('a.tex')
|
||||
expect(content).to.equal(this.documentclassContent)
|
||||
})
|
||||
|
||||
it('processes main.text first and stops processing when it finds the content', function (done) {
|
||||
return this.ProjectRootDocManager.findRootDocFileFromDirectory(
|
||||
'/foo',
|
||||
() => {
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/main.tex')
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/a.tex')
|
||||
expect(this.fs.readFile).not.to.be.calledWith('/foo/b.tex')
|
||||
return done()
|
||||
}
|
||||
it('processes main.text first and stops processing when it finds the content', async function () {
|
||||
await this.ProjectRootDocManager.promises.findRootDocFileFromDirectory(
|
||||
'/foo'
|
||||
)
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/main.tex')
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/a.tex')
|
||||
expect(this.fs.readFile).not.to.be.calledWith('/foo/b.tex')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when there is no documentclass', function () {
|
||||
it('returns with no error', function (done) {
|
||||
return this.ProjectRootDocManager.findRootDocFileFromDirectory(
|
||||
'/foo',
|
||||
error => {
|
||||
expect(error).not.to.exist
|
||||
return done()
|
||||
}
|
||||
it('returns with no error', async function () {
|
||||
await this.ProjectRootDocManager.promises.findRootDocFileFromDirectory(
|
||||
'/foo'
|
||||
)
|
||||
})
|
||||
|
||||
it('processes all the files', function (done) {
|
||||
return this.ProjectRootDocManager.findRootDocFileFromDirectory(
|
||||
'/foo',
|
||||
() => {
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/main.tex')
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/a.tex')
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/b.tex')
|
||||
return done()
|
||||
}
|
||||
it('processes all the files', async function () {
|
||||
await this.ProjectRootDocManager.promises.findRootDocFileFromDirectory(
|
||||
'/foo'
|
||||
)
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/main.tex')
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/a.tex')
|
||||
expect(this.fs.readFile).to.be.calledWith('/foo/b.tex')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when there is an error reading a file', function () {
|
||||
beforeEach(function () {
|
||||
return this.fs.readFile
|
||||
this.fs.readFile
|
||||
.withArgs('/foo/a.tex')
|
||||
.callsArgWith(2, new Error('something went wrong'))
|
||||
})
|
||||
|
||||
it('returns an error', function (done) {
|
||||
return this.ProjectRootDocManager.findRootDocFileFromDirectory(
|
||||
'/foo',
|
||||
(error, path, content) => {
|
||||
expect(error).to.exist
|
||||
expect(path).not.to.exist
|
||||
expect(content).not.to.exist
|
||||
return done()
|
||||
}
|
||||
)
|
||||
it('returns an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.ProjectRootDocManager.promises.findRootDocFileFromDirectory(
|
||||
'/foo'
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('setRootDocFromName', function () {
|
||||
describe('when there is a suitable root doc', function () {
|
||||
beforeEach(function (done) {
|
||||
beforeEach(async function () {
|
||||
this.ProjectEntityHandler.getAllDocPathsFromProjectById = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docPaths)
|
||||
this.ProjectEntityUpdateHandler.setRootDoc = sinon
|
||||
.stub()
|
||||
.callsArgWith(2)
|
||||
return this.ProjectRootDocManager.setRootDocFromName(
|
||||
await this.ProjectRootDocManager.promises.setRootDocFromName(
|
||||
this.project_id,
|
||||
'/main.tex',
|
||||
done
|
||||
'/main.tex'
|
||||
)
|
||||
})
|
||||
|
||||
it('should check the docs of the project', function () {
|
||||
return this.ProjectEntityHandler.getAllDocPathsFromProjectById
|
||||
this.ProjectEntityHandler.getAllDocPathsFromProjectById
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should set the root doc to main.tex', function () {
|
||||
return this.ProjectEntityUpdateHandler.setRootDoc
|
||||
this.ProjectEntityUpdateHandler.setRootDoc
|
||||
.calledWith(this.project_id, this.docId2.toString())
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when there is a suitable root doc but the leading slash is missing', function () {
|
||||
beforeEach(function (done) {
|
||||
beforeEach(async function () {
|
||||
this.ProjectEntityHandler.getAllDocPathsFromProjectById = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docPaths)
|
||||
this.ProjectEntityUpdateHandler.setRootDoc = sinon
|
||||
.stub()
|
||||
.callsArgWith(2)
|
||||
return this.ProjectRootDocManager.setRootDocFromName(
|
||||
await this.ProjectRootDocManager.promises.setRootDocFromName(
|
||||
this.project_id,
|
||||
'main.tex',
|
||||
done
|
||||
'main.tex'
|
||||
)
|
||||
})
|
||||
|
||||
it('should check the docs of the project', function () {
|
||||
return this.ProjectEntityHandler.getAllDocPathsFromProjectById
|
||||
this.ProjectEntityHandler.getAllDocPathsFromProjectById
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should set the root doc to main.tex', function () {
|
||||
return this.ProjectEntityUpdateHandler.setRootDoc
|
||||
this.ProjectEntityUpdateHandler.setRootDoc
|
||||
.calledWith(this.project_id, this.docId2.toString())
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when there is a suitable root doc with a basename match', function () {
|
||||
beforeEach(function (done) {
|
||||
beforeEach(async function () {
|
||||
this.ProjectEntityHandler.getAllDocPathsFromProjectById = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docPaths)
|
||||
this.ProjectEntityUpdateHandler.setRootDoc = sinon
|
||||
.stub()
|
||||
.callsArgWith(2)
|
||||
return this.ProjectRootDocManager.setRootDocFromName(
|
||||
await this.ProjectRootDocManager.promises.setRootDocFromName(
|
||||
this.project_id,
|
||||
'chapter1a.tex',
|
||||
done
|
||||
'chapter1a.tex'
|
||||
)
|
||||
})
|
||||
|
||||
it('should check the docs of the project', function () {
|
||||
return this.ProjectEntityHandler.getAllDocPathsFromProjectById
|
||||
this.ProjectEntityHandler.getAllDocPathsFromProjectById
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should set the root doc using the basename', function () {
|
||||
return this.ProjectEntityUpdateHandler.setRootDoc
|
||||
this.ProjectEntityUpdateHandler.setRootDoc
|
||||
.calledWith(this.project_id, this.docId3.toString())
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when there is a suitable root doc but the filename is in quotes', function () {
|
||||
beforeEach(function (done) {
|
||||
beforeEach(async function () {
|
||||
this.ProjectEntityHandler.getAllDocPathsFromProjectById = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docPaths)
|
||||
this.ProjectEntityUpdateHandler.setRootDoc = sinon
|
||||
.stub()
|
||||
.callsArgWith(2)
|
||||
return this.ProjectRootDocManager.setRootDocFromName(
|
||||
await this.ProjectRootDocManager.promises.setRootDocFromName(
|
||||
this.project_id,
|
||||
"'main.tex'",
|
||||
done
|
||||
"'main.tex'"
|
||||
)
|
||||
})
|
||||
|
||||
it('should check the docs of the project', function () {
|
||||
return this.ProjectEntityHandler.getAllDocPathsFromProjectById
|
||||
this.ProjectEntityHandler.getAllDocPathsFromProjectById
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should set the root doc to main.tex', function () {
|
||||
return this.ProjectEntityUpdateHandler.setRootDoc
|
||||
this.ProjectEntityUpdateHandler.setRootDoc
|
||||
.calledWith(this.project_id, this.docId2.toString())
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when there is no suitable root doc', function () {
|
||||
beforeEach(function (done) {
|
||||
beforeEach(async function () {
|
||||
this.ProjectEntityHandler.getAllDocPathsFromProjectById = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docPaths)
|
||||
this.ProjectEntityUpdateHandler.setRootDoc = sinon
|
||||
.stub()
|
||||
.callsArgWith(2)
|
||||
return this.ProjectRootDocManager.setRootDocFromName(
|
||||
await this.ProjectRootDocManager.promises.setRootDocFromName(
|
||||
this.project_id,
|
||||
'other.tex',
|
||||
done
|
||||
'other.tex'
|
||||
)
|
||||
})
|
||||
|
||||
it('should not set the root doc', function () {
|
||||
return this.ProjectEntityUpdateHandler.setRootDoc.called.should.equal(
|
||||
false
|
||||
)
|
||||
this.ProjectEntityUpdateHandler.setRootDoc.called.should.equal(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -545,73 +486,73 @@ describe('ProjectRootDocManager', function () {
|
||||
this.ProjectGetter.getProject = sinon
|
||||
.stub()
|
||||
.callsArgWith(2, null, this.project)
|
||||
return (this.ProjectRootDocManager.setRootDocAutomatically = sinon
|
||||
this.ProjectRootDocManager.setRootDocAutomatically = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null))
|
||||
.callsArgWith(1, null)
|
||||
})
|
||||
|
||||
describe('when the root doc is set', function () {
|
||||
beforeEach(function () {
|
||||
this.project.rootDoc_id = this.docId2
|
||||
return this.ProjectRootDocManager.ensureRootDocumentIsSet(
|
||||
this.ProjectRootDocManager.ensureRootDocumentIsSet(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should find the project fetching only the rootDoc_id field', function () {
|
||||
return this.ProjectGetter.getProject
|
||||
this.ProjectGetter.getProject
|
||||
.calledWith(this.project_id, { rootDoc_id: 1 })
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should not try to update the project rootDoc_id', function () {
|
||||
return this.ProjectRootDocManager.setRootDocAutomatically.called.should.equal(
|
||||
this.ProjectRootDocManager.setRootDocAutomatically.called.should.equal(
|
||||
false
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback', function () {
|
||||
return this.callback.called.should.equal(true)
|
||||
this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the root doc is not set', function () {
|
||||
beforeEach(function () {
|
||||
return this.ProjectRootDocManager.ensureRootDocumentIsSet(
|
||||
this.ProjectRootDocManager.ensureRootDocumentIsSet(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should find the project with only the rootDoc_id field', function () {
|
||||
return this.ProjectGetter.getProject
|
||||
this.ProjectGetter.getProject
|
||||
.calledWith(this.project_id, { rootDoc_id: 1 })
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should update the project rootDoc_id', function () {
|
||||
return this.ProjectRootDocManager.setRootDocAutomatically
|
||||
this.ProjectRootDocManager.setRootDocAutomatically
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback', function () {
|
||||
return this.callback.called.should.equal(true)
|
||||
this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the project does not exist', function () {
|
||||
beforeEach(function () {
|
||||
this.ProjectGetter.getProject = sinon.stub().callsArgWith(2, null, null)
|
||||
return this.ProjectRootDocManager.ensureRootDocumentIsSet(
|
||||
this.ProjectRootDocManager.ensureRootDocumentIsSet(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
return this.callback
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
@@ -645,26 +586,26 @@ describe('ProjectRootDocManager', function () {
|
||||
this.ProjectEntityHandler.getDocPathFromProjectByDocId = sinon
|
||||
.stub()
|
||||
.callsArgWith(2, null, this.docPaths[this.docId2])
|
||||
return this.ProjectRootDocManager.ensureRootDocumentIsValid(
|
||||
this.ProjectRootDocManager.ensureRootDocumentIsValid(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should find the project without doc lines', function () {
|
||||
return this.ProjectGetter.getProjectWithoutDocLines
|
||||
this.ProjectGetter.getProjectWithoutDocLines
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should not try to update the project rootDoc_id', function () {
|
||||
return this.ProjectRootDocManager.setRootDocAutomatically.called.should.equal(
|
||||
this.ProjectRootDocManager.setRootDocAutomatically.called.should.equal(
|
||||
false
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback', function () {
|
||||
return this.callback.called.should.equal(true)
|
||||
this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -674,58 +615,58 @@ describe('ProjectRootDocManager', function () {
|
||||
this.ProjectEntityHandler.getDocPathFromProjectByDocId = sinon
|
||||
.stub()
|
||||
.callsArgWith(2, null, null)
|
||||
return this.ProjectRootDocManager.ensureRootDocumentIsValid(
|
||||
this.ProjectRootDocManager.ensureRootDocumentIsValid(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should find the project without doc lines', function () {
|
||||
return this.ProjectGetter.getProjectWithoutDocLines
|
||||
this.ProjectGetter.getProjectWithoutDocLines
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should unset the root doc', function () {
|
||||
return this.ProjectEntityUpdateHandler.unsetRootDoc
|
||||
this.ProjectEntityUpdateHandler.unsetRootDoc
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should try to find a new rootDoc', function () {
|
||||
return this.ProjectRootDocManager.setRootDocAutomatically.called.should.equal(
|
||||
this.ProjectRootDocManager.setRootDocAutomatically.called.should.equal(
|
||||
true
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback', function () {
|
||||
return this.callback.called.should.equal(true)
|
||||
this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the root doc is not set', function () {
|
||||
beforeEach(function () {
|
||||
return this.ProjectRootDocManager.ensureRootDocumentIsValid(
|
||||
this.ProjectRootDocManager.ensureRootDocumentIsValid(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should find the project without doc lines', function () {
|
||||
return this.ProjectGetter.getProjectWithoutDocLines
|
||||
this.ProjectGetter.getProjectWithoutDocLines
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should update the project rootDoc_id', function () {
|
||||
return this.ProjectRootDocManager.setRootDocAutomatically
|
||||
this.ProjectRootDocManager.setRootDocAutomatically
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback', function () {
|
||||
return this.callback.called.should.equal(true)
|
||||
this.callback.called.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -734,14 +675,14 @@ describe('ProjectRootDocManager', function () {
|
||||
this.ProjectGetter.getProjectWithoutDocLines = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, null)
|
||||
return this.ProjectRootDocManager.ensureRootDocumentIsValid(
|
||||
this.ProjectRootDocManager.ensureRootDocumentIsValid(
|
||||
this.project_id,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback with an error', function () {
|
||||
return this.callback
|
||||
this.callback
|
||||
.calledWith(
|
||||
sinon.match
|
||||
.instanceOf(Error)
|
||||
|
||||
@@ -42,15 +42,10 @@ describe('PublishersGetter', function () {
|
||||
})
|
||||
|
||||
describe('getManagedPublishers', function () {
|
||||
it('fetches v1 data before returning publisher list', function (done) {
|
||||
this.PublishersGetter.getManagedPublishers(
|
||||
this.userId,
|
||||
(error, publishers) => {
|
||||
expect(error).to.be.null
|
||||
publishers.length.should.equal(1)
|
||||
done()
|
||||
}
|
||||
)
|
||||
it('fetches v1 data before returning publisher list', async function () {
|
||||
const publishers =
|
||||
await this.PublishersGetter.promises.getManagedPublishers(this.userId)
|
||||
expect(publishers.length).to.equal(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -25,23 +25,17 @@ describe('LoginRateLimiter', function () {
|
||||
})
|
||||
|
||||
describe('processLoginRequest', function () {
|
||||
it('should consume points', function (done) {
|
||||
this.LoginRateLimiter.processLoginRequest(this.email, (err, allow) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
expect(this.rateLimiter.consume).to.have.been.calledWith(this.email)
|
||||
done()
|
||||
})
|
||||
it('should consume points', async function () {
|
||||
await this.LoginRateLimiter.promises.processLoginRequest(this.email)
|
||||
expect(this.rateLimiter.consume).to.have.been.calledWith(this.email)
|
||||
})
|
||||
|
||||
describe('when login is allowed', function () {
|
||||
it('should call pass allow=true', function (done) {
|
||||
this.LoginRateLimiter.processLoginRequest(this.email, (err, allow) => {
|
||||
expect(err).to.equal(null)
|
||||
expect(allow).to.equal(true)
|
||||
done()
|
||||
})
|
||||
it('should call pass allow=true', async function () {
|
||||
const allow = await this.LoginRateLimiter.promises.processLoginRequest(
|
||||
this.email
|
||||
)
|
||||
expect(allow).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -50,12 +44,11 @@ describe('LoginRateLimiter', function () {
|
||||
this.rateLimiter.consume.rejects({ remainingPoints: 0 })
|
||||
})
|
||||
|
||||
it('should call pass allow=false', function (done) {
|
||||
this.LoginRateLimiter.processLoginRequest(this.email, (err, allow) => {
|
||||
expect(err).to.equal(null)
|
||||
expect(allow).to.equal(false)
|
||||
done()
|
||||
})
|
||||
it('should call pass allow=false', async function () {
|
||||
const allow = await this.LoginRateLimiter.promises.processLoginRequest(
|
||||
this.email
|
||||
)
|
||||
expect(allow).to.equal(false)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -64,22 +57,24 @@ describe('LoginRateLimiter', function () {
|
||||
this.rateLimiter.consume.rejects(new Error('woops'))
|
||||
})
|
||||
|
||||
it('should produce an error', function (done) {
|
||||
this.LoginRateLimiter.processLoginRequest(this.email, (err, allow) => {
|
||||
expect(err).to.not.equal(null)
|
||||
expect(err).to.be.instanceof(Error)
|
||||
done()
|
||||
})
|
||||
it('should produce an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.LoginRateLimiter.promises.processLoginRequest(this.email)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('recordSuccessfulLogin', function () {
|
||||
it('should clear the rate limit', function (done) {
|
||||
this.LoginRateLimiter.recordSuccessfulLogin(this.email, () => {
|
||||
expect(this.rateLimiter.delete).to.have.been.calledWith(this.email)
|
||||
done()
|
||||
})
|
||||
it('should clear the rate limit', async function () {
|
||||
await this.LoginRateLimiter.promises.recordSuccessfulLogin(this.email)
|
||||
expect(this.rateLimiter.delete).to.have.been.calledWith(this.email)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -294,7 +294,7 @@ describe('RecurlyWrapper', function () {
|
||||
})
|
||||
|
||||
describe('updateAccountEmailAddress, with invalid XML', function () {
|
||||
beforeEach(async function (done) {
|
||||
beforeEach(async function () {
|
||||
this.recurlyAccountId = 'account-id-123'
|
||||
this.newEmail = '\uD800@example.com'
|
||||
this.apiRequest = sinon
|
||||
@@ -307,22 +307,24 @@ describe('RecurlyWrapper', function () {
|
||||
body: fixtures['accounts/104'],
|
||||
}
|
||||
})
|
||||
done()
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
this.RecurlyWrapper.promises.apiRequest.restore()
|
||||
})
|
||||
|
||||
it('should produce an error', function (done) {
|
||||
this.RecurlyWrapper.promises
|
||||
.updateAccountEmailAddress(this.recurlyAccountId, this.newEmail)
|
||||
.catch(error => {
|
||||
expect(error).to.exist
|
||||
expect(error.message.startsWith('Invalid character')).to.equal(true)
|
||||
expect(this.apiRequest.called).to.equal(false)
|
||||
done()
|
||||
})
|
||||
it('should produce an error', async function () {
|
||||
try {
|
||||
await this.RecurlyWrapper.promises.updateAccountEmailAddress(
|
||||
this.recurlyAccountId,
|
||||
this.newEmail
|
||||
)
|
||||
expect(false).to.equal(true) // Fail if we don't have an error
|
||||
} catch (error) {
|
||||
expect(error).to.have.property('message')
|
||||
expect(error.message.startsWith('Invalid character')).to.be.true
|
||||
expect(this.apiRequest.called).to.equal(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -702,19 +704,27 @@ describe('RecurlyWrapper', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('should produce an error', function (done) {
|
||||
this.call().catch(err => {
|
||||
expect(err).to.be.instanceof(
|
||||
SubscriptionErrors.RecurlyTransactionError
|
||||
)
|
||||
expect(err.info.public.message).to.be.equal(
|
||||
'Your card must be authenticated with 3D Secure before continuing.'
|
||||
)
|
||||
expect(err.info.public.threeDSecureActionTokenId).to.be.equal(
|
||||
'mock_three_d_secure_action_token'
|
||||
)
|
||||
done()
|
||||
})
|
||||
it('should produce an error', async function () {
|
||||
const promise = this.call()
|
||||
let error
|
||||
|
||||
try {
|
||||
await promise
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(
|
||||
SubscriptionErrors.RecurlyTransactionError
|
||||
)
|
||||
expect(error).to.have.nested.property(
|
||||
'info.public.message',
|
||||
'Your card must be authenticated with 3D Secure before continuing.'
|
||||
)
|
||||
expect(error).to.have.nested.property(
|
||||
'info.public.threeDSecureActionTokenId',
|
||||
'mock_three_d_secure_action_token'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -131,174 +131,149 @@ describe('TeamInvitesHandler', function () {
|
||||
})
|
||||
|
||||
describe('getInvite', function () {
|
||||
it("returns the invite if there's one", function (done) {
|
||||
this.TeamInvitesHandler.getInvite(
|
||||
this.token,
|
||||
(err, invite, subscription) => {
|
||||
expect(err).to.eq(null)
|
||||
expect(invite).to.deep.eq(this.teamInvite)
|
||||
expect(subscription).to.deep.eq(this.subscription)
|
||||
done()
|
||||
}
|
||||
)
|
||||
it("returns the invite if there's one", async function () {
|
||||
const { invite, subscription } =
|
||||
await this.TeamInvitesHandler.promises.getInvite(this.token)
|
||||
|
||||
expect(invite).to.deep.eq(this.teamInvite)
|
||||
expect(subscription).to.deep.eq(this.subscription)
|
||||
})
|
||||
|
||||
it("returns teamNotFound if there's none", function (done) {
|
||||
it("returns teamNotFound if there's none", async function () {
|
||||
this.Subscription.findOne = sinon.stub().resolves(null)
|
||||
|
||||
this.TeamInvitesHandler.getInvite(
|
||||
this.token,
|
||||
(err, invite, subscription) => {
|
||||
expect(err).to.be.instanceof(Errors.NotFoundError)
|
||||
done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
try {
|
||||
await this.TeamInvitesHandler.promises.getInvite(this.token)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(Errors.NotFoundError)
|
||||
})
|
||||
})
|
||||
|
||||
describe('createInvite', function () {
|
||||
it('adds the team invite to the subscription', function (done) {
|
||||
this.TeamInvitesHandler.createInvite(
|
||||
it('adds the team invite to the subscription', async function () {
|
||||
const invite = await this.TeamInvitesHandler.promises.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
'John.Snow@example.com',
|
||||
(err, invite) => {
|
||||
expect(err).to.eq(null)
|
||||
expect(invite.token).to.eq(this.newToken)
|
||||
expect(invite.email).to.eq('john.snow@example.com')
|
||||
expect(invite.inviterName).to.eq(
|
||||
'Daenerys Targaryen (daenerys@example.com)'
|
||||
)
|
||||
expect(invite.invite).to.be.true
|
||||
expect(this.subscription.teamInvites).to.deep.include(invite)
|
||||
done()
|
||||
}
|
||||
'John.Snow@example.com'
|
||||
)
|
||||
expect(invite.token).to.eq(this.newToken)
|
||||
expect(invite.email).to.eq('john.snow@example.com')
|
||||
expect(invite.inviterName).to.eq(
|
||||
'Daenerys Targaryen (daenerys@example.com)'
|
||||
)
|
||||
expect(invite.invite).to.be.true
|
||||
expect(this.subscription.teamInvites).to.deep.include(invite)
|
||||
})
|
||||
|
||||
it('sends an email', function (done) {
|
||||
this.TeamInvitesHandler.createInvite(
|
||||
it('sends an email', async function () {
|
||||
await this.TeamInvitesHandler.promises.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
'John.Snow@example.com',
|
||||
(err, invite) => {
|
||||
this.EmailHandler.promises.sendEmail
|
||||
.calledWith(
|
||||
'verifyEmailToJoinTeam',
|
||||
sinon.match({
|
||||
to: 'john.snow@example.com',
|
||||
inviter: this.manager,
|
||||
acceptInviteUrl: `http://example.com/subscription/invites/${this.newToken}/`,
|
||||
})
|
||||
)
|
||||
.should.equal(true)
|
||||
done(err)
|
||||
}
|
||||
'John.Snow@example.com'
|
||||
)
|
||||
|
||||
this.EmailHandler.promises.sendEmail
|
||||
.calledWith(
|
||||
'verifyEmailToJoinTeam',
|
||||
sinon.match({
|
||||
to: 'john.snow@example.com',
|
||||
inviter: this.manager,
|
||||
acceptInviteUrl: `http://example.com/subscription/invites/${this.newToken}/`,
|
||||
})
|
||||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('refreshes the existing invite if the email has already been invited', function (done) {
|
||||
it('refreshes the existing invite if the email has already been invited', async function () {
|
||||
const originalInvite = Object.assign({}, this.teamInvite)
|
||||
|
||||
this.TeamInvitesHandler.createInvite(
|
||||
const invite = await this.TeamInvitesHandler.promises.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
originalInvite.email,
|
||||
(err, invite) => {
|
||||
expect(err).to.eq(null)
|
||||
expect(invite).to.exist
|
||||
|
||||
expect(this.subscription.teamInvites.length).to.eq(1)
|
||||
expect(this.subscription.teamInvites).to.deep.include(invite)
|
||||
|
||||
expect(invite.email).to.eq(originalInvite.email)
|
||||
|
||||
this.subscription.save.calledOnce.should.eq(true)
|
||||
|
||||
done()
|
||||
}
|
||||
originalInvite.email
|
||||
)
|
||||
expect(invite).to.exist
|
||||
|
||||
expect(this.subscription.teamInvites.length).to.eq(1)
|
||||
expect(this.subscription.teamInvites).to.deep.include(invite)
|
||||
|
||||
expect(invite.email).to.eq(originalInvite.email)
|
||||
|
||||
this.subscription.save.calledOnce.should.eq(true)
|
||||
})
|
||||
|
||||
it('removes any legacy invite from the subscription', function (done) {
|
||||
this.TeamInvitesHandler.createInvite(
|
||||
it('removes any legacy invite from the subscription', async function () {
|
||||
await this.TeamInvitesHandler.promises.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
'John.Snow@example.com',
|
||||
(err, invite) => {
|
||||
this.Subscription.updateOne
|
||||
.calledWith(
|
||||
{ _id: new ObjectId('55153a8014829a865bbf700d') },
|
||||
{ $pull: { invited_emails: 'john.snow@example.com' } }
|
||||
)
|
||||
.should.eq(true)
|
||||
done(err)
|
||||
}
|
||||
'John.Snow@example.com'
|
||||
)
|
||||
|
||||
this.Subscription.updateOne
|
||||
.calledWith(
|
||||
{ _id: new ObjectId('55153a8014829a865bbf700d') },
|
||||
{ $pull: { invited_emails: 'john.snow@example.com' } }
|
||||
)
|
||||
.should.eq(true)
|
||||
})
|
||||
|
||||
it('add user to subscription if inviting self', function (done) {
|
||||
this.TeamInvitesHandler.createInvite(
|
||||
it('add user to subscription if inviting self', async function () {
|
||||
const invite = await this.TeamInvitesHandler.promises.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
this.manager.email,
|
||||
(err, invite) => {
|
||||
sinon.assert.calledWith(
|
||||
this.SubscriptionUpdater.promises.addUserToGroup,
|
||||
this.subscription._id,
|
||||
this.manager._id
|
||||
)
|
||||
sinon.assert.notCalled(this.subscription.save)
|
||||
expect(invite.token).to.not.exist
|
||||
expect(invite.email).to.eq(this.manager.email)
|
||||
expect(invite.first_name).to.eq(this.manager.first_name)
|
||||
expect(invite.last_name).to.eq(this.manager.last_name)
|
||||
expect(invite.invite).to.be.false
|
||||
done(err)
|
||||
}
|
||||
this.manager.email
|
||||
)
|
||||
sinon.assert.calledWith(
|
||||
this.SubscriptionUpdater.promises.addUserToGroup,
|
||||
this.subscription._id,
|
||||
this.manager._id
|
||||
)
|
||||
sinon.assert.notCalled(this.subscription.save)
|
||||
expect(invite.token).to.not.exist
|
||||
expect(invite.email).to.eq(this.manager.email)
|
||||
expect(invite.first_name).to.eq(this.manager.first_name)
|
||||
expect(invite.last_name).to.eq(this.manager.last_name)
|
||||
expect(invite.invite).to.be.false
|
||||
})
|
||||
|
||||
it('sends an SSO invite if SSO is enabled and inviting self', function (done) {
|
||||
it('sends an SSO invite if SSO is enabled and inviting self', async function () {
|
||||
this.subscription.ssoConfig = new ObjectId('abc123abc123abc123abc123')
|
||||
this.SSOConfig.findById
|
||||
.withArgs(this.subscription.ssoConfig)
|
||||
.resolves({ enabled: true })
|
||||
|
||||
this.TeamInvitesHandler.createInvite(
|
||||
await this.TeamInvitesHandler.promises.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
this.manager.email,
|
||||
(err, invite) => {
|
||||
sinon.assert.calledWith(
|
||||
this.Modules.promises.hooks.fire,
|
||||
'sendGroupSSOReminder',
|
||||
this.manager._id,
|
||||
this.subscription._id
|
||||
)
|
||||
done(err)
|
||||
}
|
||||
this.manager.email
|
||||
)
|
||||
sinon.assert.calledWith(
|
||||
this.Modules.promises.hooks.fire,
|
||||
'sendGroupSSOReminder',
|
||||
this.manager._id,
|
||||
this.subscription._id
|
||||
)
|
||||
})
|
||||
|
||||
it('does not send an SSO invite if SSO is disabled and inviting self', function (done) {
|
||||
it('does not send an SSO invite if SSO is disabled and inviting self', async function () {
|
||||
this.subscription.ssoConfig = new ObjectId('abc123abc123abc123abc123')
|
||||
this.SSOConfig.findById
|
||||
.withArgs(this.subscription.ssoConfig)
|
||||
.resolves({ enabled: false })
|
||||
|
||||
this.TeamInvitesHandler.createInvite(
|
||||
await this.TeamInvitesHandler.promises.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
this.manager.email,
|
||||
(err, invite) => {
|
||||
sinon.assert.notCalled(this.Modules.promises.hooks.fire)
|
||||
done(err)
|
||||
}
|
||||
this.manager.email
|
||||
)
|
||||
sinon.assert.notCalled(this.Modules.promises.hooks.fire)
|
||||
})
|
||||
|
||||
it('sends a notification if inviting registered user', function (done) {
|
||||
it('sends a notification if inviting registered user', async function () {
|
||||
const id = new ObjectId('6a6b3a8014829a865bbf700d')
|
||||
const managedUsersEnabled = false
|
||||
|
||||
@@ -308,22 +283,19 @@ describe('TeamInvitesHandler', function () {
|
||||
_id: id,
|
||||
})
|
||||
|
||||
this.TeamInvitesHandler.createInvite(
|
||||
const invite = await this.TeamInvitesHandler.promises.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
'John.Snow@example.com',
|
||||
(err, invite) => {
|
||||
this.NotificationsBuilder.promises
|
||||
.groupInvitation(
|
||||
id.toString(),
|
||||
this.subscription._id,
|
||||
managedUsersEnabled
|
||||
)
|
||||
.create.calledWith(invite)
|
||||
.should.eq(true)
|
||||
done(err)
|
||||
}
|
||||
'John.Snow@example.com'
|
||||
)
|
||||
this.NotificationsBuilder.promises
|
||||
.groupInvitation(
|
||||
id.toString(),
|
||||
this.subscription._id,
|
||||
managedUsersEnabled
|
||||
)
|
||||
.create.calledWith(invite)
|
||||
.should.eq(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -375,112 +347,115 @@ describe('TeamInvitesHandler', function () {
|
||||
})
|
||||
|
||||
describe('with standard group', function () {
|
||||
it('adds the user to the team', function (done) {
|
||||
this.TeamInvitesHandler.acceptInvite('dddddddd', this.user.id, () => {
|
||||
this.SubscriptionUpdater.promises.addUserToGroup
|
||||
.calledWith(this.subscription._id, this.user.id)
|
||||
.should.eq(true)
|
||||
done()
|
||||
})
|
||||
it('adds the user to the team', async function () {
|
||||
await this.TeamInvitesHandler.promises.acceptInvite(
|
||||
'dddddddd',
|
||||
this.user.id
|
||||
)
|
||||
this.SubscriptionUpdater.promises.addUserToGroup
|
||||
.calledWith(this.subscription._id, this.user.id)
|
||||
.should.eq(true)
|
||||
})
|
||||
|
||||
it('removes the invite from the subscription', function (done) {
|
||||
this.TeamInvitesHandler.acceptInvite('dddddddd', this.user.id, () => {
|
||||
this.Subscription.updateOne
|
||||
.calledWith(
|
||||
{ _id: new ObjectId('55153a8014829a865bbf700d') },
|
||||
{ $pull: { teamInvites: { email: 'john.snow@example.com' } } }
|
||||
)
|
||||
.should.eq(true)
|
||||
done()
|
||||
})
|
||||
it('removes the invite from the subscription', async function () {
|
||||
await this.TeamInvitesHandler.promises.acceptInvite(
|
||||
'dddddddd',
|
||||
this.user.id
|
||||
)
|
||||
this.Subscription.updateOne
|
||||
.calledWith(
|
||||
{ _id: new ObjectId('55153a8014829a865bbf700d') },
|
||||
{ $pull: { teamInvites: { email: 'john.snow@example.com' } } }
|
||||
)
|
||||
.should.eq(true)
|
||||
})
|
||||
|
||||
it('removes dashboard notification after they accepted group invitation', function (done) {
|
||||
it('removes dashboard notification after they accepted group invitation', async function () {
|
||||
const managedUsersEnabled = false
|
||||
|
||||
this.TeamInvitesHandler.acceptInvite('dddddddd', this.user.id, () => {
|
||||
sinon.assert.called(
|
||||
this.NotificationsBuilder.promises.groupInvitation(
|
||||
this.user.id,
|
||||
this.subscription._id,
|
||||
managedUsersEnabled
|
||||
).read
|
||||
)
|
||||
done()
|
||||
})
|
||||
await this.TeamInvitesHandler.promises.acceptInvite(
|
||||
'dddddddd',
|
||||
this.user.id
|
||||
)
|
||||
sinon.assert.called(
|
||||
this.NotificationsBuilder.promises.groupInvitation(
|
||||
this.user.id,
|
||||
this.subscription._id,
|
||||
managedUsersEnabled
|
||||
).read
|
||||
)
|
||||
})
|
||||
|
||||
it('should not schedule an SSO invite reminder', function (done) {
|
||||
this.TeamInvitesHandler.acceptInvite('dddddddd', this.user.id, () => {
|
||||
sinon.assert.notCalled(this.Modules.promises.hooks.fire)
|
||||
done()
|
||||
})
|
||||
it('should not schedule an SSO invite reminder', async function () {
|
||||
await this.TeamInvitesHandler.promises.acceptInvite(
|
||||
'dddddddd',
|
||||
this.user.id
|
||||
)
|
||||
sinon.assert.notCalled(this.Modules.promises.hooks.fire)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with managed group', function () {
|
||||
it('should enroll the group member', function (done) {
|
||||
it('should enroll the group member', async function () {
|
||||
this.subscription.managedUsersEnabled = true
|
||||
|
||||
this.TeamInvitesHandler.acceptInvite('dddddddd', this.user.id, () => {
|
||||
sinon.assert.calledWith(
|
||||
this.Modules.promises.hooks.fire,
|
||||
'enrollInManagedSubscription',
|
||||
this.user.id,
|
||||
this.subscription
|
||||
)
|
||||
done()
|
||||
})
|
||||
await this.TeamInvitesHandler.promises.acceptInvite(
|
||||
'dddddddd',
|
||||
this.user.id
|
||||
)
|
||||
sinon.assert.calledWith(
|
||||
this.Modules.promises.hooks.fire,
|
||||
'enrollInManagedSubscription',
|
||||
this.user.id,
|
||||
this.subscription
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with group SSO enabled', function () {
|
||||
it('should schedule an SSO invite reminder', function (done) {
|
||||
it('should schedule an SSO invite reminder', async function () {
|
||||
this.subscription.ssoConfig = 'ssoconfig1'
|
||||
this.SSOConfig.findById
|
||||
.withArgs('ssoconfig1')
|
||||
.resolves({ enabled: true })
|
||||
|
||||
this.TeamInvitesHandler.acceptInvite('dddddddd', this.user.id, () => {
|
||||
sinon.assert.calledWith(
|
||||
this.Modules.promises.hooks.fire,
|
||||
'scheduleGroupSSOReminder',
|
||||
this.user.id,
|
||||
this.subscription._id
|
||||
)
|
||||
done()
|
||||
})
|
||||
await this.TeamInvitesHandler.promises.acceptInvite(
|
||||
'dddddddd',
|
||||
this.user.id
|
||||
)
|
||||
sinon.assert.calledWith(
|
||||
this.Modules.promises.hooks.fire,
|
||||
'scheduleGroupSSOReminder',
|
||||
this.user.id,
|
||||
this.subscription._id
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('revokeInvite', function () {
|
||||
it('removes the team invite from the subscription', function (done) {
|
||||
this.TeamInvitesHandler.revokeInvite(
|
||||
it('removes the team invite from the subscription', async function () {
|
||||
await this.TeamInvitesHandler.promises.revokeInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
'jorah@example.com',
|
||||
() => {
|
||||
this.Subscription.updateOne
|
||||
.calledWith(
|
||||
{ _id: new ObjectId('55153a8014829a865bbf700d') },
|
||||
{ $pull: { teamInvites: { email: 'jorah@example.com' } } }
|
||||
)
|
||||
.should.eq(true)
|
||||
|
||||
this.Subscription.updateOne
|
||||
.calledWith(
|
||||
{ _id: new ObjectId('55153a8014829a865bbf700d') },
|
||||
{ $pull: { invited_emails: 'jorah@example.com' } }
|
||||
)
|
||||
.should.eq(true)
|
||||
done()
|
||||
}
|
||||
'jorah@example.com'
|
||||
)
|
||||
this.Subscription.updateOne
|
||||
.calledWith(
|
||||
{ _id: new ObjectId('55153a8014829a865bbf700d') },
|
||||
{ $pull: { teamInvites: { email: 'jorah@example.com' } } }
|
||||
)
|
||||
.should.eq(true)
|
||||
|
||||
this.Subscription.updateOne
|
||||
.calledWith(
|
||||
{ _id: new ObjectId('55153a8014829a865bbf700d') },
|
||||
{ $pull: { invited_emails: 'jorah@example.com' } }
|
||||
)
|
||||
.should.eq(true)
|
||||
})
|
||||
|
||||
it('removes dashboard notification for pending group invitation', function (done) {
|
||||
it('removes dashboard notification for pending group invitation', async function () {
|
||||
const managedUsersEnabled = false
|
||||
|
||||
const pendingUser = {
|
||||
@@ -492,26 +467,23 @@ describe('TeamInvitesHandler', function () {
|
||||
.withArgs(pendingUser.email)
|
||||
.resolves(pendingUser)
|
||||
|
||||
this.TeamInvitesHandler.revokeInvite(
|
||||
await this.TeamInvitesHandler.promises.revokeInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
pendingUser.email,
|
||||
() => {
|
||||
sinon.assert.called(
|
||||
this.NotificationsBuilder.promises.groupInvitation(
|
||||
pendingUser.id,
|
||||
this.subscription._id,
|
||||
managedUsersEnabled
|
||||
).read
|
||||
)
|
||||
pendingUser.email
|
||||
)
|
||||
|
||||
done()
|
||||
}
|
||||
sinon.assert.called(
|
||||
this.NotificationsBuilder.promises.groupInvitation(
|
||||
pendingUser.id,
|
||||
this.subscription._id,
|
||||
managedUsersEnabled
|
||||
).read
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('createTeamInvitesForLegacyInvitedEmail', function (done) {
|
||||
describe('createTeamInvitesForLegacyInvitedEmail', function () {
|
||||
beforeEach(function () {
|
||||
this.subscription.invited_emails = [
|
||||
'eddard@example.com',
|
||||
@@ -523,58 +495,71 @@ describe('TeamInvitesHandler', function () {
|
||||
.resolves([this.subscription])
|
||||
})
|
||||
|
||||
it('sends an invitation email to addresses in the legacy invited_emails field', function (done) {
|
||||
this.TeamInvitesHandler.createTeamInvitesForLegacyInvitedEmail(
|
||||
'eddard@example.com',
|
||||
(err, invites) => {
|
||||
expect(err).not.to.exist
|
||||
expect(invites.length).to.eq(1)
|
||||
it('sends an invitation email to addresses in the legacy invited_emails field', async function () {
|
||||
const invites =
|
||||
await this.TeamInvitesHandler.promises.createTeamInvitesForLegacyInvitedEmail(
|
||||
'eddard@example.com'
|
||||
)
|
||||
|
||||
const [invite] = invites
|
||||
expect(invite.token).to.eq(this.newToken)
|
||||
expect(invite.email).to.eq('eddard@example.com')
|
||||
expect(invite.inviterName).to.eq(
|
||||
'Daenerys Targaryen (daenerys@example.com)'
|
||||
)
|
||||
expect(invite.invite).to.be.true
|
||||
expect(this.subscription.teamInvites).to.deep.include(invite)
|
||||
expect(invites.length).to.eq(1)
|
||||
|
||||
done()
|
||||
}
|
||||
const [invite] = invites
|
||||
expect(invite.token).to.eq(this.newToken)
|
||||
expect(invite.email).to.eq('eddard@example.com')
|
||||
expect(invite.inviterName).to.eq(
|
||||
'Daenerys Targaryen (daenerys@example.com)'
|
||||
)
|
||||
expect(invite.invite).to.be.true
|
||||
expect(this.subscription.teamInvites).to.deep.include(invite)
|
||||
})
|
||||
})
|
||||
|
||||
describe('validation', function () {
|
||||
it("doesn't create an invite if the team limit has been reached", function (done) {
|
||||
it("doesn't create an invite if the team limit has been reached", async function () {
|
||||
this.LimitationsManager.teamHasReachedMemberLimit = sinon
|
||||
.stub()
|
||||
.returns(true)
|
||||
this.TeamInvitesHandler.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
'John.Snow@example.com',
|
||||
(err, invite) => {
|
||||
expect(err).to.deep.equal({ limitReached: true })
|
||||
done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.TeamInvitesHandler.promises.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
'John.Snow@example.com'
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
|
||||
expect(error).to.deep.equal({
|
||||
limitReached: true,
|
||||
})
|
||||
})
|
||||
|
||||
it("doesn't create an invite if the subscription is not in a group plan", function (done) {
|
||||
it("doesn't create an invite if the subscription is not in a group plan", async function () {
|
||||
this.subscription.groupPlan = false
|
||||
this.TeamInvitesHandler.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
'John.Snow@example.com',
|
||||
(err, invite) => {
|
||||
expect(err).to.deep.equal({ wrongPlan: true })
|
||||
done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.TeamInvitesHandler.promises.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
'John.Snow@example.com'
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
|
||||
expect(error).to.deep.equal({
|
||||
wrongPlan: true,
|
||||
})
|
||||
})
|
||||
|
||||
it("doesn't create an invite if the user is already part of the team", function (done) {
|
||||
it("doesn't create an invite if the user is already part of the team", async function () {
|
||||
const member = {
|
||||
id: '1a2b',
|
||||
_id: '1a2b',
|
||||
@@ -586,16 +571,23 @@ describe('TeamInvitesHandler', function () {
|
||||
.withArgs(member.email)
|
||||
.resolves(member)
|
||||
|
||||
this.TeamInvitesHandler.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
'tyrion@example.com',
|
||||
(err, invite) => {
|
||||
expect(err).to.deep.equal({ alreadyInTeam: true })
|
||||
expect(invite).not.to.exist
|
||||
done()
|
||||
}
|
||||
)
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.TeamInvitesHandler.promises.createInvite(
|
||||
this.manager._id,
|
||||
this.subscription,
|
||||
'tyrion@example.com'
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
|
||||
expect(error).to.eql({
|
||||
alreadyInTeam: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -30,78 +30,72 @@ describe('TagsHandler', function () {
|
||||
})
|
||||
|
||||
describe('finding users tags', function () {
|
||||
it('should find all the documents with that user id', function (done) {
|
||||
it('should find all the documents with that user id', async function () {
|
||||
const stubbedTags = [{ name: 'tag1' }, { name: 'tag2' }, { name: 'tag3' }]
|
||||
this.TagMock.expects('find')
|
||||
.once()
|
||||
.withArgs({ user_id: this.userId })
|
||||
.resolves(stubbedTags)
|
||||
this.TagsHandler.getAllTags(this.userId, (err, result) => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
expect(result).to.deep.equal(stubbedTags)
|
||||
done()
|
||||
})
|
||||
const result = await this.TagsHandler.promises.getAllTags(this.userId)
|
||||
this.TagMock.verify()
|
||||
expect(result).to.deep.equal(stubbedTags)
|
||||
})
|
||||
})
|
||||
|
||||
describe('createTag', function () {
|
||||
describe('when insert succeeds', function () {
|
||||
it('should call insert in mongo', function (done) {
|
||||
it('should call insert in mongo', async function () {
|
||||
this.TagMock.expects('create')
|
||||
.withArgs(this.tag)
|
||||
.once()
|
||||
.resolves(this.tag)
|
||||
this.TagsHandler.createTag(
|
||||
const resultTag = await this.TagsHandler.promises.createTag(
|
||||
this.tag.user_id,
|
||||
this.tag.name,
|
||||
this.tag.color,
|
||||
(err, resultTag) => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
expect(resultTag.user_id).to.equal(this.tag.user_id)
|
||||
expect(resultTag.name).to.equal(this.tag.name)
|
||||
expect(resultTag.color).to.equal(this.tag.color)
|
||||
done()
|
||||
}
|
||||
this.tag.color
|
||||
)
|
||||
this.TagMock.verify()
|
||||
expect(resultTag.user_id).to.equal(this.tag.user_id)
|
||||
expect(resultTag.name).to.equal(this.tag.name)
|
||||
expect(resultTag.color).to.equal(this.tag.color)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when truncate=true, and tag is too long', function () {
|
||||
it('should truncate the tag name', function (done) {
|
||||
it('should truncate the tag name', async function () {
|
||||
// Expect the tag to end up with this truncated name
|
||||
this.tag.name = 'a comically long tag that will be truncated intern'
|
||||
this.TagMock.expects('create')
|
||||
.withArgs(this.tag)
|
||||
.once()
|
||||
.resolves(this.tag)
|
||||
this.TagsHandler.createTag(
|
||||
const resultTag = await this.TagsHandler.promises.createTag(
|
||||
this.tag.user_id,
|
||||
// Pass this too-long name
|
||||
'a comically long tag that will be truncated internally and not throw an error',
|
||||
this.tag.color,
|
||||
{ truncate: true },
|
||||
(err, resultTag) => {
|
||||
expect(err).to.not.exist
|
||||
expect(resultTag.name).to.equal(this.tag.name)
|
||||
done()
|
||||
}
|
||||
{ truncate: true }
|
||||
)
|
||||
expect(resultTag.name).to.equal(this.tag.name)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when tag is too long', function () {
|
||||
it('should throw an error', function (done) {
|
||||
this.TagsHandler.createTag(
|
||||
this.tag.user_id,
|
||||
'this is a tag that is very very very very very very long',
|
||||
undefined,
|
||||
err => {
|
||||
expect(err.message).to.equal('Exceeded max tag length')
|
||||
done()
|
||||
}
|
||||
)
|
||||
it('should throw an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.TagsHandler.promises.createTag(
|
||||
this.tag.user_id,
|
||||
'this is a tag that is very very very very very very long',
|
||||
undefined
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
expect(error).to.have.property('message', 'Exceeded max tag length')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -111,7 +105,7 @@ describe('TagsHandler', function () {
|
||||
this.duplicateKeyError.code = 11000
|
||||
})
|
||||
|
||||
it('should get tag with findOne and return that tag', function (done) {
|
||||
it('should get tag with findOne and return that tag', async function () {
|
||||
this.TagMock.expects('create')
|
||||
.withArgs(this.tag)
|
||||
.once()
|
||||
@@ -120,26 +114,22 @@ describe('TagsHandler', function () {
|
||||
.withArgs({ user_id: this.tag.user_id, name: this.tag.name })
|
||||
.once()
|
||||
.resolves(this.tag)
|
||||
this.TagsHandler.createTag(
|
||||
const resultTag = await this.TagsHandler.promises.createTag(
|
||||
this.tag.user_id,
|
||||
this.tag.name,
|
||||
this.tag.color,
|
||||
(err, resultTag) => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
expect(resultTag.user_id).to.equal(this.tag.user_id)
|
||||
expect(resultTag.name).to.equal(this.tag.name)
|
||||
expect(resultTag.color).to.equal(this.tag.color)
|
||||
done()
|
||||
}
|
||||
this.tag.color
|
||||
)
|
||||
this.TagMock.verify()
|
||||
expect(resultTag.user_id).to.equal(this.tag.user_id)
|
||||
expect(resultTag.name).to.equal(this.tag.name)
|
||||
expect(resultTag.color).to.equal(this.tag.color)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('addProjectToTag', function () {
|
||||
describe('with a valid tag_id', function () {
|
||||
it('should call update in mongo', function (done) {
|
||||
it('should call update in mongo', async function () {
|
||||
this.TagMock.expects('findOneAndUpdate')
|
||||
.once()
|
||||
.withArgs(
|
||||
@@ -147,23 +137,19 @@ describe('TagsHandler', function () {
|
||||
{ $addToSet: { project_ids: this.projectId } }
|
||||
)
|
||||
.resolves()
|
||||
this.TagsHandler.addProjectToTag(
|
||||
await this.TagsHandler.promises.addProjectToTag(
|
||||
this.userId,
|
||||
this.tagId,
|
||||
this.projectId,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
this.projectId
|
||||
)
|
||||
this.TagMock.verify()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('addProjectsToTag', function () {
|
||||
describe('with a valid tag_id', function () {
|
||||
it('should call update in mongo', function (done) {
|
||||
it('should call update in mongo', async function () {
|
||||
this.TagMock.expects('findOneAndUpdate')
|
||||
.once()
|
||||
.withArgs(
|
||||
@@ -171,22 +157,18 @@ describe('TagsHandler', function () {
|
||||
{ $addToSet: { project_ids: { $each: this.projectIds } } }
|
||||
)
|
||||
.resolves()
|
||||
this.TagsHandler.addProjectsToTag(
|
||||
await this.TagsHandler.promises.addProjectsToTag(
|
||||
this.userId,
|
||||
this.tagId,
|
||||
this.projectIds,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
this.projectIds
|
||||
)
|
||||
this.TagMock.verify()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('addProjectToTagName', function () {
|
||||
it('should call update in mongo', function (done) {
|
||||
it('should call update in mongo', async function () {
|
||||
this.TagMock.expects('updateOne')
|
||||
.once()
|
||||
.withArgs(
|
||||
@@ -195,22 +177,18 @@ describe('TagsHandler', function () {
|
||||
{ upsert: true }
|
||||
)
|
||||
.resolves()
|
||||
this.TagsHandler.addProjectToTagName(
|
||||
await this.TagsHandler.promises.addProjectToTagName(
|
||||
this.tag.userId,
|
||||
this.tag.name,
|
||||
this.projectId,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
this.projectId
|
||||
)
|
||||
this.TagMock.verify()
|
||||
})
|
||||
})
|
||||
|
||||
describe('removeProjectFromTag', function () {
|
||||
describe('with a valid tag_id', function () {
|
||||
it('should call update in mongo', function (done) {
|
||||
it('should call update in mongo', async function () {
|
||||
this.TagMock.expects('updateOne')
|
||||
.once()
|
||||
.withArgs(
|
||||
@@ -223,23 +201,20 @@ describe('TagsHandler', function () {
|
||||
}
|
||||
)
|
||||
.resolves()
|
||||
this.TagsHandler.removeProjectFromTag(
|
||||
await this.TagsHandler.promises.removeProjectFromTag(
|
||||
this.userId,
|
||||
this.tagId,
|
||||
this.projectId,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
this.projectId
|
||||
)
|
||||
|
||||
this.TagMock.verify()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('removeProjectsFromTag', function () {
|
||||
describe('with a valid tag_id', function () {
|
||||
it('should call update in mongo', function (done) {
|
||||
it('should call update in mongo', async function () {
|
||||
this.TagMock.expects('updateOne')
|
||||
.once()
|
||||
.withArgs(
|
||||
@@ -252,22 +227,18 @@ describe('TagsHandler', function () {
|
||||
}
|
||||
)
|
||||
.resolves()
|
||||
this.TagsHandler.removeProjectsFromTag(
|
||||
await this.TagsHandler.promises.removeProjectsFromTag(
|
||||
this.userId,
|
||||
this.tagId,
|
||||
this.projectIds,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
this.projectIds
|
||||
)
|
||||
this.TagMock.verify()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('removeProjectFromAllTags', function () {
|
||||
it('should pull the project id from the tag', function (done) {
|
||||
it('should pull the project id from the tag', async function () {
|
||||
this.TagMock.expects('updateMany')
|
||||
.once()
|
||||
.withArgs(
|
||||
@@ -279,20 +250,16 @@ describe('TagsHandler', function () {
|
||||
}
|
||||
)
|
||||
.resolves()
|
||||
this.TagsHandler.removeProjectFromAllTags(
|
||||
await this.TagsHandler.promises.removeProjectFromAllTags(
|
||||
this.userId,
|
||||
this.projectId,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
this.projectId
|
||||
)
|
||||
this.TagMock.verify()
|
||||
})
|
||||
})
|
||||
|
||||
describe('addProjectToTags', function () {
|
||||
it('should add the project id to each tag', function (done) {
|
||||
it('should add the project id to each tag', async function () {
|
||||
const tagIds = []
|
||||
|
||||
this.TagMock.expects('updateMany')
|
||||
@@ -307,38 +274,31 @@ describe('TagsHandler', function () {
|
||||
}
|
||||
)
|
||||
.resolves()
|
||||
this.TagsHandler.addProjectToTags(
|
||||
await this.TagsHandler.promises.addProjectToTags(
|
||||
this.userId,
|
||||
tagIds,
|
||||
this.projectId,
|
||||
(err, result) => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
this.projectId
|
||||
)
|
||||
this.TagMock.verify()
|
||||
})
|
||||
})
|
||||
|
||||
describe('deleteTag', function () {
|
||||
describe('with a valid tag_id', function () {
|
||||
it('should call remove in mongo', function (done) {
|
||||
it('should call remove in mongo', async function () {
|
||||
this.TagMock.expects('deleteOne')
|
||||
.once()
|
||||
.withArgs({ _id: this.tagId, user_id: this.userId })
|
||||
.resolves()
|
||||
this.TagsHandler.deleteTag(this.userId, this.tagId, err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
})
|
||||
await this.TagsHandler.promises.deleteTag(this.userId, this.tagId)
|
||||
this.TagMock.verify()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('renameTag', function () {
|
||||
describe('with a valid tag_id', function () {
|
||||
it('should call remove in mongo', function (done) {
|
||||
it('should call remove in mongo', async function () {
|
||||
this.newName = 'new name'
|
||||
this.TagMock.expects('updateOne')
|
||||
.once()
|
||||
@@ -347,30 +307,31 @@ describe('TagsHandler', function () {
|
||||
{ $set: { name: this.newName } }
|
||||
)
|
||||
.resolves()
|
||||
this.TagsHandler.renameTag(
|
||||
await this.TagsHandler.promises.renameTag(
|
||||
this.userId,
|
||||
this.tagId,
|
||||
this.newName,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
this.newName
|
||||
)
|
||||
this.TagMock.verify()
|
||||
})
|
||||
})
|
||||
|
||||
describe('when tag is too long', function () {
|
||||
it('should throw an error', function (done) {
|
||||
this.TagsHandler.renameTag(
|
||||
this.userId,
|
||||
this.tagId,
|
||||
'this is a tag that is very very very very very very long',
|
||||
err => {
|
||||
expect(err.message).to.equal('Exceeded max tag length')
|
||||
done()
|
||||
}
|
||||
)
|
||||
it('should throw an error', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.TagsHandler.promises.renameTag(
|
||||
this.userId,
|
||||
this.tagId,
|
||||
'this is a tag that is very very very very very very long'
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.exist
|
||||
expect(error).to.have.property('message', 'Exceeded max tag length')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -65,22 +65,25 @@ describe('FileTypeManager', function () {
|
||||
describe('when it is a directory', function () {
|
||||
beforeEach(function () {
|
||||
this.stats.isDirectory.returns(true)
|
||||
this.FileTypeManager.isDirectory('/some/path', this.callback)
|
||||
})
|
||||
|
||||
it('should return true', function () {
|
||||
this.callback.should.have.been.calledWith(null, true)
|
||||
it('should return true', async function () {
|
||||
const result =
|
||||
await this.FileTypeManager.promises.isDirectory('/some/path')
|
||||
|
||||
expect(result).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when it is not a directory', function () {
|
||||
beforeEach(function () {
|
||||
this.stats.isDirectory.returns(false)
|
||||
this.FileTypeManager.isDirectory('/some/path', this.callback)
|
||||
})
|
||||
|
||||
it('should return false', function () {
|
||||
this.callback.should.have.been.calledWith(null, false)
|
||||
it('should return false', async function () {
|
||||
const result =
|
||||
await this.FileTypeManager.promises.isDirectory('/some/path')
|
||||
expect(result).to.equal(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -113,223 +116,158 @@ describe('FileTypeManager', function () {
|
||||
'/GNUMakefile',
|
||||
]
|
||||
TEXT_FILENAMES.forEach(filename => {
|
||||
it(`should classify ${filename} as text`, function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
it(`should classify ${filename} as text`, async function () {
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
filename,
|
||||
'utf8.tex',
|
||||
null,
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
binary.should.equal(false)
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
binary.should.equal(false)
|
||||
})
|
||||
})
|
||||
|
||||
it('should not classify short text files as binary', function (done) {
|
||||
it('should not classify short text files as binary', async function () {
|
||||
this.stats.size = 2 * 1024 * 1024 // 2MB
|
||||
this.FileTypeManager.getType(
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'text-short.tex',
|
||||
null,
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
binary.should.equal(false)
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
binary.should.equal(false)
|
||||
})
|
||||
|
||||
it('should not classify text files just under the size limit as binary', function (done) {
|
||||
it('should not classify text files just under the size limit as binary', async function () {
|
||||
this.stats.size = 2 * 1024 * 1024 // 2MB
|
||||
this.FileTypeManager.getType(
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'text-smaller.tex',
|
||||
null,
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
binary.should.equal(false)
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
binary.should.equal(false)
|
||||
})
|
||||
|
||||
it('should classify text files at the size limit as binary', function (done) {
|
||||
it('should classify text files at the size limit as binary', async function () {
|
||||
this.stats.size = 2 * 1024 * 1024 // 2MB
|
||||
this.FileTypeManager.getType(
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'text-exact.tex',
|
||||
null,
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
binary.should.equal(true)
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
binary.should.equal(true)
|
||||
})
|
||||
|
||||
it('should classify long text files as binary', function (done) {
|
||||
it('should classify long text files as binary', async function () {
|
||||
this.stats.size = 2 * 1024 * 1024 // 2MB
|
||||
this.FileTypeManager.getType(
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'text-long.tex',
|
||||
null,
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
binary.should.equal(true)
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
binary.should.equal(true)
|
||||
})
|
||||
|
||||
it('should classify large text files as binary', function (done) {
|
||||
it('should classify large text files as binary', async function () {
|
||||
this.stats.size = 8 * 1024 * 1024 // 8MB
|
||||
this.FileTypeManager.getType(
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'utf8.tex',
|
||||
null,
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
binary.should.equal(true)
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
binary.should.equal(true)
|
||||
})
|
||||
|
||||
it('should not try to determine the encoding of large files', function (done) {
|
||||
it('should not try to determine the encoding of large files', async function () {
|
||||
this.stats.size = 8 * 1024 * 1024 // 8MB
|
||||
this.FileTypeManager.getType('/file.tex', 'utf8.tex', null, err => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
sinon.assert.notCalled(this.isUtf8)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should detect the encoding of a utf8 file', function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'utf8.tex',
|
||||
null,
|
||||
(err, { binary, encoding }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
sinon.assert.calledOnce(this.isUtf8)
|
||||
this.isUtf8.returned(true).should.equal(true)
|
||||
encoding.should.equal('utf-8')
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
sinon.assert.notCalled(this.isUtf8)
|
||||
})
|
||||
|
||||
it("should return 'latin1' for non-unicode encodings", function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
it('should detect the encoding of a utf8 file', async function () {
|
||||
const { encoding } = await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'utf8.tex',
|
||||
null
|
||||
)
|
||||
|
||||
sinon.assert.calledOnce(this.isUtf8)
|
||||
this.isUtf8.returned(true).should.equal(true)
|
||||
encoding.should.equal('utf-8')
|
||||
})
|
||||
|
||||
it("should return 'latin1' for non-unicode encodings", async function () {
|
||||
const { encoding } = await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'latin1.tex',
|
||||
null,
|
||||
(err, { binary, encoding }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
sinon.assert.calledOnce(this.isUtf8)
|
||||
this.isUtf8.returned(false).should.equal(true)
|
||||
encoding.should.equal('latin1')
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
sinon.assert.calledOnce(this.isUtf8)
|
||||
this.isUtf8.returned(false).should.equal(true)
|
||||
encoding.should.equal('latin1')
|
||||
})
|
||||
|
||||
it('should classify utf16 with BOM as utf-16', function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
it('should classify utf16 with BOM as utf-16', async function () {
|
||||
const { encoding } = await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'utf16.tex',
|
||||
null,
|
||||
(err, { binary, encoding }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
sinon.assert.calledOnce(this.isUtf8)
|
||||
this.isUtf8.returned(false).should.equal(true)
|
||||
encoding.should.equal('utf-16le')
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
sinon.assert.calledOnce(this.isUtf8)
|
||||
this.isUtf8.returned(false).should.equal(true)
|
||||
encoding.should.equal('utf-16le')
|
||||
})
|
||||
|
||||
it('should classify latin1 files with a null char as binary', function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
it('should classify latin1 files with a null char as binary', async function () {
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'latin1-null.tex',
|
||||
null,
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
expect(binary).to.equal(true)
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
expect(binary).to.equal(true)
|
||||
})
|
||||
|
||||
it('should classify utf8 files with a null char as binary', function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
it('should classify utf8 files with a null char as binary', async function () {
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'utf8-null.tex',
|
||||
null,
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
expect(binary).to.equal(true)
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
expect(binary).to.equal(true)
|
||||
})
|
||||
|
||||
it('should classify utf8 files with non-BMP chars as binary', function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
it('should classify utf8 files with non-BMP chars as binary', async function () {
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'utf8-non-bmp.tex',
|
||||
null,
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
expect(binary).to.equal(true)
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
expect(binary).to.equal(true)
|
||||
})
|
||||
|
||||
it('should classify utf8 files with ascii control chars as utf-8', function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
'/file.tex',
|
||||
'utf8-control-chars.tex',
|
||||
null,
|
||||
(err, { binary, encoding }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
expect(binary).to.equal(false)
|
||||
expect(encoding).to.equal('utf-8')
|
||||
done()
|
||||
}
|
||||
)
|
||||
it('should classify utf8 files with ascii control chars as utf-8', async function () {
|
||||
const { binary, encoding } =
|
||||
await this.FileTypeManager.promises.getType(
|
||||
'/file.tex',
|
||||
'utf8-control-chars.tex',
|
||||
null
|
||||
)
|
||||
|
||||
expect(binary).to.equal(false)
|
||||
expect(encoding).to.equal('utf-8')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -342,189 +280,132 @@ describe('FileTypeManager', function () {
|
||||
'/tex',
|
||||
]
|
||||
BINARY_FILENAMES.forEach(filename => {
|
||||
it(`should classify ${filename} as binary`, function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
it(`should classify ${filename} as binary`, async function () {
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
filename,
|
||||
'latin1.tex', // even if the content is not binary
|
||||
null,
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
binary.should.equal(true)
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
binary.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
it('should not try to get the character encoding', function (done) {
|
||||
this.FileTypeManager.getType('/file.png', 'utf8.tex', null, err => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
sinon.assert.notCalled(this.isUtf8)
|
||||
done()
|
||||
})
|
||||
it('should not try to get the character encoding', async function () {
|
||||
await this.FileTypeManager.promises.getType(
|
||||
'/file.png',
|
||||
'utf8.tex',
|
||||
null
|
||||
)
|
||||
|
||||
sinon.assert.notCalled(this.isUtf8)
|
||||
})
|
||||
|
||||
it('should recognise new binary files as binary', function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
it('should recognise new binary files as binary', async function () {
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
'/file.py',
|
||||
'latin1.tex',
|
||||
null,
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
binary.should.equal(true)
|
||||
done()
|
||||
}
|
||||
null
|
||||
)
|
||||
|
||||
binary.should.equal(true)
|
||||
})
|
||||
|
||||
it('should recognise existing binary files as binary', function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
it('should recognise existing binary files as binary', async function () {
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
'/file.py',
|
||||
'latin1.tex',
|
||||
'file',
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
binary.should.equal(true)
|
||||
done()
|
||||
}
|
||||
'file'
|
||||
)
|
||||
|
||||
binary.should.equal(true)
|
||||
})
|
||||
|
||||
it('should preserve existing non-binary files as non-binary', function (done) {
|
||||
this.FileTypeManager.getType(
|
||||
it('should preserve existing non-binary files as non-binary', async function () {
|
||||
const { binary } = await this.FileTypeManager.promises.getType(
|
||||
'/file.py',
|
||||
'latin1.tex',
|
||||
'doc',
|
||||
(err, { binary }) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
binary.should.equal(false)
|
||||
done()
|
||||
}
|
||||
'doc'
|
||||
)
|
||||
|
||||
binary.should.equal(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('shouldIgnore', function () {
|
||||
it('should ignore tex auxiliary files', function (done) {
|
||||
this.FileTypeManager.shouldIgnore('file.aux', (err, ignore) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
ignore.should.equal(true)
|
||||
done()
|
||||
})
|
||||
it('should ignore tex auxiliary files', async function () {
|
||||
const ignore =
|
||||
await this.FileTypeManager.promises.shouldIgnore('file.aux')
|
||||
ignore.should.equal(true)
|
||||
})
|
||||
|
||||
it('should ignore dotfiles', function (done) {
|
||||
this.FileTypeManager.shouldIgnore('path/.git', (err, ignore) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
ignore.should.equal(true)
|
||||
done()
|
||||
})
|
||||
it('should ignore dotfiles', async function () {
|
||||
const ignore =
|
||||
await this.FileTypeManager.promises.shouldIgnore('path/.git')
|
||||
|
||||
ignore.should.equal(true)
|
||||
})
|
||||
|
||||
it('should ignore .git directories and contained files', function (done) {
|
||||
this.FileTypeManager.shouldIgnore('path/.git/info', (err, ignore) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
ignore.should.equal(true)
|
||||
done()
|
||||
})
|
||||
it('should ignore .git directories and contained files', async function () {
|
||||
const ignore =
|
||||
await this.FileTypeManager.promises.shouldIgnore('path/.git/info')
|
||||
|
||||
ignore.should.equal(true)
|
||||
})
|
||||
|
||||
it('should not ignore .latexmkrc dotfile', function (done) {
|
||||
this.FileTypeManager.shouldIgnore('path/.latexmkrc', (err, ignore) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
ignore.should.equal(false)
|
||||
done()
|
||||
})
|
||||
it('should not ignore .latexmkrc dotfile', async function () {
|
||||
const ignore =
|
||||
await this.FileTypeManager.promises.shouldIgnore('path/.latexmkrc')
|
||||
|
||||
ignore.should.equal(false)
|
||||
})
|
||||
|
||||
it('should ignore __MACOSX', function (done) {
|
||||
this.FileTypeManager.shouldIgnore('path/__MACOSX', (err, ignore) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
ignore.should.equal(true)
|
||||
done()
|
||||
})
|
||||
it('should ignore __MACOSX', async function () {
|
||||
const ignore =
|
||||
await this.FileTypeManager.promises.shouldIgnore('path/__MACOSX')
|
||||
|
||||
ignore.should.equal(true)
|
||||
})
|
||||
|
||||
it('should ignore synctex files', function (done) {
|
||||
this.FileTypeManager.shouldIgnore('file.synctex', (err, ignore) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
ignore.should.equal(true)
|
||||
done()
|
||||
})
|
||||
it('should ignore synctex files', async function () {
|
||||
const ignore =
|
||||
await this.FileTypeManager.promises.shouldIgnore('file.synctex')
|
||||
|
||||
ignore.should.equal(true)
|
||||
})
|
||||
|
||||
it('should ignore synctex(busy) files', function (done) {
|
||||
this.FileTypeManager.shouldIgnore('file.synctex(busy)', (err, ignore) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
ignore.should.equal(true)
|
||||
done()
|
||||
})
|
||||
it('should ignore synctex(busy) files', async function () {
|
||||
const ignore =
|
||||
await this.FileTypeManager.promises.shouldIgnore('file.synctex(busy)')
|
||||
|
||||
ignore.should.equal(true)
|
||||
})
|
||||
|
||||
it('should not ignore .tex files', function (done) {
|
||||
this.FileTypeManager.shouldIgnore('file.tex', (err, ignore) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
ignore.should.equal(false)
|
||||
done()
|
||||
})
|
||||
it('should not ignore .tex files', async function () {
|
||||
const ignore =
|
||||
await this.FileTypeManager.promises.shouldIgnore('file.tex')
|
||||
|
||||
ignore.should.equal(false)
|
||||
})
|
||||
|
||||
it('should ignore the case of the extension', function (done) {
|
||||
this.FileTypeManager.shouldIgnore('file.AUX', (err, ignore) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
ignore.should.equal(true)
|
||||
done()
|
||||
})
|
||||
it('should ignore the case of the extension', async function () {
|
||||
const ignore =
|
||||
await this.FileTypeManager.promises.shouldIgnore('file.AUX')
|
||||
|
||||
ignore.should.equal(true)
|
||||
})
|
||||
|
||||
it('should not ignore files with an ignored extension as full name', function (done) {
|
||||
this.FileTypeManager.shouldIgnore('dvi', (err, ignore) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
ignore.should.equal(false)
|
||||
done()
|
||||
})
|
||||
it('should not ignore files with an ignored extension as full name', async function () {
|
||||
const ignore = await this.FileTypeManager.promises.shouldIgnore('dvi')
|
||||
ignore.should.equal(false)
|
||||
})
|
||||
|
||||
it('should not ignore directories with an ignored extension as full name', function (done) {
|
||||
it('should not ignore directories with an ignored extension as full name', async function () {
|
||||
this.stats.isDirectory.returns(true)
|
||||
this.FileTypeManager.shouldIgnore('dvi', (err, ignore) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
ignore.should.equal(false)
|
||||
done()
|
||||
})
|
||||
const ignore = await this.FileTypeManager.promises.shouldIgnore('dvi')
|
||||
|
||||
ignore.should.equal(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,6 +2,9 @@ const sinon = require('sinon')
|
||||
const { expect } = require('chai')
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const OError = require('@overleaf/o-error')
|
||||
const {
|
||||
ThirdPartyUserNotFoundError,
|
||||
} = require('../../../../app/src/Features/Errors/Errors')
|
||||
const modulePath =
|
||||
'../../../../app/src/Features/User/ThirdPartyIdentityManager.js'
|
||||
|
||||
@@ -77,16 +80,19 @@ describe('ThirdPartyIdentityManager', function () {
|
||||
expect(user).to.deep.equal(this.user)
|
||||
})
|
||||
})
|
||||
it('should return ThirdPartyUserNotFoundError when no user linked', function (done) {
|
||||
this.ThirdPartyIdentityManager.getUser(
|
||||
'google',
|
||||
'an-id-not-linked',
|
||||
(error, user) => {
|
||||
expect(error).to.exist
|
||||
expect(error.name).to.equal('ThirdPartyUserNotFoundError')
|
||||
done()
|
||||
}
|
||||
)
|
||||
it('should return ThirdPartyUserNotFoundError when no user linked', async function () {
|
||||
let error
|
||||
|
||||
try {
|
||||
await this.ThirdPartyIdentityManager.promises.getUser(
|
||||
'google',
|
||||
'an-id-not-linked'
|
||||
)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
|
||||
expect(error).to.be.instanceOf(ThirdPartyUserNotFoundError)
|
||||
})
|
||||
})
|
||||
describe('link', function () {
|
||||
|
||||
Reference in New Issue
Block a user