mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-06-02 21:59:00 +02:00
Merge pull request #2614 from overleaf/sk-monolithify-tags
Move 'tags' into web GitOrigin-RevId: a248d1b2471f0bfa05589df9b7357b4d85793a79
This commit is contained in:
@@ -1,93 +1,88 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const TagsHandler = require('./TagsHandler')
|
||||
const AuthenticationController = require('../Authentication/AuthenticationController')
|
||||
const Errors = require('../Errors/Errors')
|
||||
|
||||
module.exports = {
|
||||
getAllTags(req, res, next) {
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
return TagsHandler.getAllTags(user_id, function(error, allTags) {
|
||||
const TagsController = {
|
||||
_getTags(userId, _req, res, next) {
|
||||
if (!userId) {
|
||||
return next(new Errors.NotFoundError())
|
||||
}
|
||||
TagsHandler.getAllTags(userId, function(error, allTags) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return res.json(allTags)
|
||||
res.json(allTags)
|
||||
})
|
||||
},
|
||||
|
||||
apiGetAllTags(req, res, next) {
|
||||
const { userId } = req.params
|
||||
TagsController._getTags(userId, req, res, next)
|
||||
},
|
||||
|
||||
getAllTags(req, res, next) {
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
TagsController._getTags(userId, req, res, next)
|
||||
},
|
||||
|
||||
createTag(req, res, next) {
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
const { name } = req.body
|
||||
return TagsHandler.createTag(user_id, name, function(error, tag) {
|
||||
TagsHandler.createTag(userId, name, function(error, tag) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return res.json(tag)
|
||||
res.json(tag)
|
||||
})
|
||||
},
|
||||
|
||||
addProjectToTag(req, res, next) {
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
const { tag_id, project_id } = req.params
|
||||
return TagsHandler.addProjectToTag(user_id, tag_id, project_id, function(
|
||||
error
|
||||
) {
|
||||
if (error != null) {
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
const { tagId, projectId } = req.params
|
||||
TagsHandler.addProjectToTag(userId, tagId, projectId, function(error) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
return res.status(204).end()
|
||||
res.status(204).end()
|
||||
})
|
||||
},
|
||||
|
||||
removeProjectFromTag(req, res, next) {
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
const { tag_id, project_id } = req.params
|
||||
return TagsHandler.removeProjectFromTag(
|
||||
user_id,
|
||||
tag_id,
|
||||
project_id,
|
||||
function(error) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return res.status(204).end()
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
const { tagId, projectId } = req.params
|
||||
TagsHandler.removeProjectFromTag(userId, tagId, projectId, function(error) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
)
|
||||
res.status(204).end()
|
||||
})
|
||||
},
|
||||
|
||||
deleteTag(req, res, next) {
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
const { tag_id } = req.params
|
||||
return TagsHandler.deleteTag(user_id, tag_id, function(error) {
|
||||
if (error != null) {
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
const { tagId } = req.params
|
||||
TagsHandler.deleteTag(userId, tagId, function(error) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
return res.status(204).end()
|
||||
res.status(204).end()
|
||||
})
|
||||
},
|
||||
|
||||
renameTag(req, res, next) {
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
const { tag_id } = req.params
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
const { tagId } = req.params
|
||||
const name = req.body != null ? req.body.name : undefined
|
||||
if (name == null) {
|
||||
if (!name) {
|
||||
return res.status(400).end()
|
||||
} else {
|
||||
return TagsHandler.renameTag(user_id, tag_id, name, function(error) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return res.status(204).end()
|
||||
})
|
||||
}
|
||||
TagsHandler.renameTag(userId, tagId, name, function(error) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
res.status(204).end()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TagsController
|
||||
|
||||
@@ -1,144 +1,104 @@
|
||||
const settings = require('settings-sharelatex')
|
||||
const request = require('request')
|
||||
const logger = require('logger-sharelatex')
|
||||
const { Tag } = require('../../models/Tag')
|
||||
const { promisifyAll } = require('../../util/promises')
|
||||
|
||||
const TIMEOUT = 10000
|
||||
|
||||
function getAllTags(userId, callback) {
|
||||
const opts = {
|
||||
url: `${settings.apis.tags.url}/user/${userId}/tag`,
|
||||
json: true,
|
||||
timeout: TIMEOUT
|
||||
}
|
||||
request.get(opts, (err, res, body) =>
|
||||
_handleResponse(err, res, { userId }, function(error) {
|
||||
if (error != null) {
|
||||
return callback(error, [])
|
||||
}
|
||||
callback(null, body || [])
|
||||
})
|
||||
)
|
||||
Tag.find({ user_id: userId }, callback)
|
||||
}
|
||||
|
||||
function createTag(userId, name, callback) {
|
||||
const opts = {
|
||||
url: `${settings.apis.tags.url}/user/${userId}/tag`,
|
||||
json: {
|
||||
name
|
||||
},
|
||||
timeout: TIMEOUT
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
}
|
||||
request.post(opts, (err, res, body) =>
|
||||
_handleResponse(err, res, { userId }, function(error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
callback(null, body || {})
|
||||
})
|
||||
)
|
||||
Tag.create({ user_id: userId, name }, function(err, tag) {
|
||||
// on duplicate key error return existing tag
|
||||
if (err && err.code === 11000) {
|
||||
return Tag.findOne({ user_id: userId, name }, callback)
|
||||
}
|
||||
callback(err, tag)
|
||||
})
|
||||
}
|
||||
|
||||
function renameTag(userId, tagId, name, callback) {
|
||||
const url = `${settings.apis.tags.url}/user/${userId}/tag/${tagId}/rename`
|
||||
request.post(
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
}
|
||||
Tag.update(
|
||||
{
|
||||
url,
|
||||
json: {
|
||||
name
|
||||
},
|
||||
timeout: TIMEOUT
|
||||
_id: tagId,
|
||||
user_id: userId
|
||||
},
|
||||
(err, res, body) =>
|
||||
_handleResponse(err, res, { url, userId, tagId, name }, callback)
|
||||
{
|
||||
$set: {
|
||||
name
|
||||
}
|
||||
},
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
function deleteTag(userId, tagId, callback) {
|
||||
const url = `${settings.apis.tags.url}/user/${userId}/tag/${tagId}`
|
||||
request.del({ url, timeout: TIMEOUT }, (err, res, body) =>
|
||||
_handleResponse(err, res, { url, userId, tagId }, callback)
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
}
|
||||
Tag.remove(
|
||||
{
|
||||
_id: tagId,
|
||||
user_id: userId
|
||||
},
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: unused?
|
||||
function updateTagUserIds(oldUserId, newUserId, callback) {
|
||||
const opts = {
|
||||
url: `${settings.apis.tags.url}/user/${oldUserId}/tag`,
|
||||
json: {
|
||||
user_id: newUserId
|
||||
},
|
||||
timeout: TIMEOUT
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
}
|
||||
request.put(opts, (err, res, body) =>
|
||||
_handleResponse(err, res, { oldUserId, newUserId }, callback)
|
||||
)
|
||||
const searchOps = { user_id: oldUserId }
|
||||
const updateOperation = { $set: { user_id: newUserId } }
|
||||
Tag.update(searchOps, updateOperation, { multi: true }, callback)
|
||||
}
|
||||
|
||||
function removeProjectFromTag(userId, tagId, projectId, callback) {
|
||||
const url = `${
|
||||
settings.apis.tags.url
|
||||
}/user/${userId}/tag/${tagId}/project/${projectId}`
|
||||
request.del({ url, timeout: TIMEOUT }, (err, res, body) =>
|
||||
_handleResponse(err, res, { url, userId, tagId, projectId }, callback)
|
||||
)
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
}
|
||||
const searchOps = {
|
||||
_id: tagId,
|
||||
user_id: userId
|
||||
}
|
||||
const deleteOperation = { $pull: { project_ids: projectId } }
|
||||
Tag.update(searchOps, deleteOperation, callback)
|
||||
}
|
||||
|
||||
function addProjectToTag(userId, tagId, projectId, callback) {
|
||||
const url = `${
|
||||
settings.apis.tags.url
|
||||
}/user/${userId}/tag/${tagId}/project/${projectId}`
|
||||
request.post({ url, timeout: TIMEOUT }, (err, res, body) =>
|
||||
_handleResponse(err, res, { url, userId, tagId, projectId }, callback)
|
||||
)
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
}
|
||||
const searchOps = {
|
||||
_id: tagId,
|
||||
user_id: userId
|
||||
}
|
||||
const insertOperation = { $addToSet: { project_ids: projectId } }
|
||||
Tag.findOneAndUpdate(searchOps, insertOperation, callback)
|
||||
}
|
||||
|
||||
function addProjectToTagName(userId, name, projectId, callback) {
|
||||
const url = `${
|
||||
settings.apis.tags.url
|
||||
}/user/${userId}/tag/project/${projectId}`
|
||||
const opts = {
|
||||
json: { name },
|
||||
timeout: TIMEOUT,
|
||||
url
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
}
|
||||
request.post(opts, (err, res, body) =>
|
||||
_handleResponse(err, res, { url, userId, name, projectId }, callback)
|
||||
)
|
||||
const searchOps = {
|
||||
name,
|
||||
user_id: userId
|
||||
}
|
||||
const insertOperation = { $addToSet: { project_ids: projectId } }
|
||||
Tag.update(searchOps, insertOperation, { upsert: true }, callback)
|
||||
}
|
||||
|
||||
function removeProjectFromAllTags(userId, projectId, callback) {
|
||||
const url = `${settings.apis.tags.url}/user/${userId}/project/${projectId}`
|
||||
const opts = {
|
||||
url,
|
||||
timeout: TIMEOUT
|
||||
}
|
||||
request.del(opts, (err, res, body) =>
|
||||
_handleResponse(err, res, { url, userId, projectId }, callback)
|
||||
)
|
||||
}
|
||||
|
||||
function _handleResponse(err, res, params, callback) {
|
||||
if (err != null) {
|
||||
params.err = err
|
||||
logger.warn(params, 'error in tag api')
|
||||
return callback(err)
|
||||
} else if (res != null && res.statusCode >= 200 && res.statusCode < 300) {
|
||||
return callback(null)
|
||||
} else {
|
||||
err = new Error(
|
||||
`tags api returned a failure status code: ${
|
||||
res != null ? res.statusCode : undefined
|
||||
}`
|
||||
)
|
||||
params.err = err
|
||||
logger.warn(
|
||||
params,
|
||||
`tags api returned failure status code: ${
|
||||
res != null ? res.statusCode : undefined
|
||||
}`
|
||||
)
|
||||
callback(err)
|
||||
}
|
||||
const searchOps = { user_id: userId }
|
||||
const deleteOperation = { $pull: { project_ids: projectId } }
|
||||
Tag.update(searchOps, deleteOperation, { multi: true }, callback)
|
||||
}
|
||||
|
||||
const TagsHandler = {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
const mongoose = require('../infrastructure/Mongoose')
|
||||
const { Schema } = mongoose
|
||||
|
||||
// Note that for legacy reasons, user_id and project_ids are plain strings,
|
||||
// not ObjectIds.
|
||||
|
||||
const TagSchema = new Schema({
|
||||
user_id: { type: String, required: true },
|
||||
name: { type: String, required: true },
|
||||
project_ids: [String]
|
||||
})
|
||||
|
||||
exports.Tag = mongoose.model('Tag', TagSchema)
|
||||
exports.TagSchema = TagSchema
|
||||
@@ -628,6 +628,11 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
||||
UserController.expireDeletedUser
|
||||
)
|
||||
|
||||
privateApiRouter.get(
|
||||
'/user/:userId/tag',
|
||||
AuthenticationController.httpAuth,
|
||||
TagsController.apiGetAllTags
|
||||
)
|
||||
webRouter.get(
|
||||
'/tag',
|
||||
AuthenticationController.requireLogin(),
|
||||
@@ -644,7 +649,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
||||
TagsController.createTag
|
||||
)
|
||||
webRouter.post(
|
||||
'/tag/:tag_id/rename',
|
||||
'/tag/:tagId/rename',
|
||||
AuthenticationController.requireLogin(),
|
||||
RateLimiterMiddleware.rateLimit({
|
||||
endpointName: 'rename-tag',
|
||||
@@ -654,7 +659,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
||||
TagsController.renameTag
|
||||
)
|
||||
webRouter.delete(
|
||||
'/tag/:tag_id',
|
||||
'/tag/:tagId',
|
||||
AuthenticationController.requireLogin(),
|
||||
RateLimiterMiddleware.rateLimit({
|
||||
endpointName: 'delete-tag',
|
||||
@@ -664,7 +669,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
||||
TagsController.deleteTag
|
||||
)
|
||||
webRouter.post(
|
||||
'/tag/:tag_id/project/:project_id',
|
||||
'/tag/:tagId/project/:projectId',
|
||||
AuthenticationController.requireLogin(),
|
||||
RateLimiterMiddleware.rateLimit({
|
||||
endpointName: 'add-project-to-tag',
|
||||
@@ -674,7 +679,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
||||
TagsController.addProjectToTag
|
||||
)
|
||||
webRouter.delete(
|
||||
'/tag/:tag_id/project/:project_id',
|
||||
'/tag/:tagId/project/:projectId',
|
||||
AuthenticationController.requireLogin(),
|
||||
RateLimiterMiddleware.rateLimit({
|
||||
endpointName: 'remove-project-from-tag',
|
||||
|
||||
@@ -7,7 +7,6 @@ const { db, ObjectId } = require('../../../app/src/infrastructure/mongojs')
|
||||
const { Subscription } = require('../../../app/src/models/Subscription')
|
||||
const SubscriptionViewModelBuilder = require('../../../app/src/Features/Subscription/SubscriptionViewModelBuilder')
|
||||
const MockDocstoreApi = require('./helpers/MockDocstoreApi')
|
||||
require('./helpers/MockTagsApi')
|
||||
require('./helpers/MockV1Api')
|
||||
require('./helpers/MockProjectHistoryApi')
|
||||
|
||||
|
||||
@@ -18,14 +18,12 @@ const request = require('./helpers/request')
|
||||
const settings = require('settings-sharelatex')
|
||||
const redis = require('./helpers/redis')
|
||||
const MockV1Api = require('./helpers/MockV1Api')
|
||||
const MockTagsApi = require('./helpers/MockTagsApi')
|
||||
|
||||
describe('Sessions', function() {
|
||||
beforeEach(function(done) {
|
||||
this.timeout(20000)
|
||||
this.user1 = new User()
|
||||
this.site_admin = new User({ email: 'admin@example.com' })
|
||||
MockTagsApi.tags[this.user1] = []
|
||||
return async.series(
|
||||
[cb => this.user1.login(cb), cb => this.user1.logout(cb)],
|
||||
done
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
const User = require('./helpers/User')
|
||||
const async = require('async')
|
||||
const { expect } = require('chai')
|
||||
const _ = require('lodash')
|
||||
const request = require('./helpers/request')
|
||||
|
||||
const _initUser = (user, callback) => {
|
||||
async.series([cb => user.login(cb), cb => user.getCsrfToken(cb)], callback)
|
||||
}
|
||||
|
||||
const _initUsers = (users, callback) => {
|
||||
async.each(users, _initUser, callback)
|
||||
}
|
||||
|
||||
const _expect200 = (err, response) => {
|
||||
expect(err).to.not.exist
|
||||
expect(response.statusCode).to.equal(200)
|
||||
}
|
||||
|
||||
const _expect204 = (err, response) => {
|
||||
expect(err).to.not.exist
|
||||
expect(response.statusCode).to.equal(204)
|
||||
}
|
||||
|
||||
const _createTag = (user, name, callback) => {
|
||||
user.request.post({ url: `/tag`, json: { name: name } }, callback)
|
||||
}
|
||||
|
||||
const _createTags = (user, tagNames, callback) => {
|
||||
const tags = []
|
||||
async.series(
|
||||
tagNames.map(tagName => cb =>
|
||||
_createTag(user, tagName, (err, response, body) => {
|
||||
_expect200(err, response)
|
||||
tags.push(body)
|
||||
cb()
|
||||
})
|
||||
),
|
||||
err => {
|
||||
callback(err, tags)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const _getTags = (user, callback) => {
|
||||
user.request.get({ url: `/tag`, json: true }, callback)
|
||||
}
|
||||
|
||||
const _names = tags => {
|
||||
return tags.map(tag => tag.name)
|
||||
}
|
||||
|
||||
const _ids = tags => {
|
||||
return tags.map(tag => tag._id)
|
||||
}
|
||||
|
||||
const _expectTagStructure = tag => {
|
||||
expect(tag).to.have.keys('_id', 'user_id', 'name', 'project_ids', '__v')
|
||||
expect(typeof tag._id).to.equal('string')
|
||||
expect(typeof tag.user_id).to.equal('string')
|
||||
expect(typeof tag.name).to.equal('string')
|
||||
expect(tag.project_ids).to.deep.equal([])
|
||||
}
|
||||
|
||||
describe('Tags', function() {
|
||||
beforeEach(function(done) {
|
||||
this.user = new User()
|
||||
this.otherUser = new User()
|
||||
_initUsers([this.user, this.otherUser], done)
|
||||
})
|
||||
|
||||
describe('get tags, anonymous', function() {
|
||||
it('should refuse to get user tags', function(done) {
|
||||
this.user.logout(err => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
_getTags(this.user, (err, response, body) => {
|
||||
expect(err).to.not.exist
|
||||
expect(response.statusCode).to.equal(302)
|
||||
expect(body).to.not.exist
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('get tags, none', function() {
|
||||
it('should get user tags', function(done) {
|
||||
_getTags(this.user, (err, response, body) => {
|
||||
_expect200(err, response)
|
||||
expect(body).to.deep.equal([])
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('create some tags, then get', function() {
|
||||
it('should get tags only for that user', function(done) {
|
||||
// Create a few tags
|
||||
_createTags(this.user, ['one', 'two', 'three'], (err, tags) => {
|
||||
expect(err).to.not.exist
|
||||
// Check structure of tags we just created
|
||||
expect(tags.length).to.equal(3)
|
||||
for (let tag of tags) {
|
||||
_expectTagStructure(tag)
|
||||
expect(tag.user_id).to.equal(this.user._id.toString())
|
||||
}
|
||||
// Get the list of tags for this user
|
||||
_getTags(this.user, (err, response, body) => {
|
||||
_expect200(err, response)
|
||||
expect(body).to.be.an.instanceof(Array)
|
||||
expect(body.length).to.equal(3)
|
||||
// Check structure of each tag in response
|
||||
for (let tag of body) {
|
||||
_expectTagStructure(tag)
|
||||
expect(tag.user_id).to.equal(this.user._id.toString())
|
||||
}
|
||||
// Check that the set of ids we created are the same as
|
||||
// the ids we got in the tag-list body
|
||||
expect(_.sortBy(_ids(tags))).to.deep.equal(_.sortBy(_ids(body)))
|
||||
// Check that the other user can't see these tags
|
||||
_getTags(this.otherUser, (err, response, body) => {
|
||||
_expect200(err, response)
|
||||
expect(body).to.deep.equal([])
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('get tags via api', function() {
|
||||
const auth = Buffer.from('sharelatex:password').toString('base64')
|
||||
const authedRequest = request.defaults({
|
||||
headers: {
|
||||
Authorization: `Basic ${auth}`
|
||||
}
|
||||
})
|
||||
|
||||
it('should disallow without appropriate auth headers', function(done) {
|
||||
_createTags(this.user, ['one', 'two', 'three'], (err, tags) => {
|
||||
expect(err).to.not.exist
|
||||
// Get the tags, but with a regular request, not authorized
|
||||
request.get(
|
||||
{ url: `/user/${this.user._id}/tag`, json: true },
|
||||
(err, response, body) => {
|
||||
expect(err).to.not.exist
|
||||
expect(response.statusCode).to.equal(401)
|
||||
expect(body).to.equal('Unauthorized')
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('should get the tags from api endpoint', function(done) {
|
||||
_createTags(this.user, ['one', 'two', 'three'], (err, tags) => {
|
||||
expect(err).to.not.exist
|
||||
// Get tags for user
|
||||
authedRequest.get(
|
||||
{ url: `/user/${this.user._id}/tag`, json: true },
|
||||
(err, response, body) => {
|
||||
_expect200(err, response)
|
||||
expect(body.length).to.equal(3)
|
||||
// Get tags for other user, expect none
|
||||
authedRequest.get(
|
||||
{ url: `/user/${this.otherUser._id}/tag`, json: true },
|
||||
(err, response, body) => {
|
||||
_expect200(err, response)
|
||||
expect(body.length).to.equal(0)
|
||||
done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('rename tag', function() {
|
||||
it('should reject malformed tag id', function(done) {
|
||||
this.user.request.post(
|
||||
{ url: `/tag/lol/rename`, json: { name: 'five' } },
|
||||
(err, response) => {
|
||||
expect(err).to.not.exist
|
||||
expect(response.statusCode).to.equal(500)
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it('should allow user to rename a tag', function(done) {
|
||||
_createTags(this.user, ['one', 'two'], (err, tags) => {
|
||||
expect(err).to.not.exist
|
||||
// Pick out the first tag
|
||||
const firstTagId = tags[0]._id
|
||||
// Change its name
|
||||
this.user.request.post(
|
||||
{ url: `/tag/${firstTagId}/rename`, json: { name: 'five' } },
|
||||
(err, response) => {
|
||||
_expect204(err, response)
|
||||
// Get the tag list
|
||||
_getTags(this.user, (err, response, body) => {
|
||||
_expect200(err, response)
|
||||
expect(body.length).to.equal(2)
|
||||
// Check the set of tag names is correct
|
||||
const tagNames = _names(body)
|
||||
expect(_.sortBy(tagNames)).to.deep.equal(
|
||||
_.sortBy(['five', 'two'])
|
||||
)
|
||||
// Check the id is the same
|
||||
const tagWithNameFive = _.find(body, t => t.name === 'five')
|
||||
expect(tagWithNameFive._id).to.equal(firstTagId)
|
||||
done()
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('should not allow other user to change name', function(done) {
|
||||
const initialTagNames = ['one', 'two']
|
||||
_createTags(this.user, initialTagNames, (err, tags) => {
|
||||
expect(err).to.not.exist
|
||||
const firstTagId = tags[0]._id
|
||||
// Post with the other user
|
||||
this.otherUser.request.post(
|
||||
{ url: `/tag/${firstTagId}/rename`, json: { name: 'six' } },
|
||||
(err, response) => {
|
||||
_expect204(err, response)
|
||||
// Should not have altered the tag
|
||||
this.user.request.get(
|
||||
{ url: `/tag`, json: true },
|
||||
(err, response, body) => {
|
||||
_expect200(err, response)
|
||||
expect(_.sortBy(_names(body))).to.deep.equal(
|
||||
_.sortBy(initialTagNames)
|
||||
)
|
||||
done()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('delete tag', function() {
|
||||
it('should reject malformed tag id', function(done) {
|
||||
this.user.request.delete(
|
||||
{ url: `/tag/lol`, json: { name: 'five' } },
|
||||
(err, response) => {
|
||||
expect(err).to.not.exist
|
||||
expect(response.statusCode).to.equal(500)
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it('should delete a tag', function(done) {
|
||||
const initialTagNames = ['one', 'two', 'three']
|
||||
_createTags(this.user, initialTagNames, (err, tags) => {
|
||||
expect(err).to.not.exist
|
||||
const firstTagId = tags[0]._id
|
||||
this.user.request.delete(
|
||||
{ url: `/tag/${firstTagId}` },
|
||||
(err, response) => {
|
||||
_expect204(err, response)
|
||||
// Check the tag list
|
||||
_getTags(this.user, (err, response, body) => {
|
||||
_expect200(err, response)
|
||||
expect(_.sortBy(_names(body))).to.deep.equal(
|
||||
_.sortBy(['two', 'three'])
|
||||
)
|
||||
done()
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('add project to tag', function() {
|
||||
beforeEach(function(done) {
|
||||
this.user.createProject('test 1', (err, projectId) => {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
this.projectId = projectId
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should reject malformed tag id', function(done) {
|
||||
this.user.request.post(
|
||||
{ url: `/tag/lol/project/bad` },
|
||||
(err, response) => {
|
||||
expect(err).to.not.exist
|
||||
expect(response.statusCode).to.equal(500)
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it('should allow the user to add a project to a tag, and remove it', function(done) {
|
||||
_createTags(this.user, ['one', 'two'], (err, tags) => {
|
||||
expect(err).to.not.exist
|
||||
const firstTagId = tags[0]._id
|
||||
_getTags(this.user, (err, response, body) => {
|
||||
_expect200(err, response)
|
||||
// Confirm that project_ids is empty for this tag
|
||||
expect(
|
||||
_.find(body, tag => tag.name === 'one').project_ids
|
||||
).to.deep.equal([])
|
||||
// Add the project to the tag
|
||||
this.user.request.post(
|
||||
{ url: `/tag/${firstTagId}/project/${this.projectId}` },
|
||||
(err, response) => {
|
||||
_expect204(err, response)
|
||||
// Get tags again
|
||||
_getTags(this.user, (err, response, body) => {
|
||||
_expect200(err, response)
|
||||
// Check the project has been added to project_ids
|
||||
expect(
|
||||
_.find(body, tag => tag.name === 'one').project_ids
|
||||
).to.deep.equal([this.projectId])
|
||||
// Remove the project from the tag
|
||||
this.user.request.delete(
|
||||
{ url: `/tag/${firstTagId}/project/${this.projectId}` },
|
||||
(err, response) => {
|
||||
_expect204(err, response)
|
||||
// Check tag list again
|
||||
_getTags(this.user, (err, response, body) => {
|
||||
_expect200(err, response)
|
||||
// Check the project has been removed from project_ids
|
||||
expect(
|
||||
_.find(body, tag => tag.name === 'one').project_ids
|
||||
).to.deep.equal([])
|
||||
done()
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('should not allow another user to add a project to the tag', function(done) {
|
||||
_createTags(this.user, ['one', 'two'], (err, tags) => {
|
||||
expect(err).to.not.exist
|
||||
const firstTagId = tags[0]._id
|
||||
_getTags(this.user, (err, response, body) => {
|
||||
_expect200(err, response)
|
||||
// Confirm that project_ids is empty for this tag
|
||||
expect(
|
||||
_.find(body, tag => tag.name === 'one').project_ids
|
||||
).to.deep.equal([])
|
||||
// Have the other user try to add their own project to the tag
|
||||
this.otherUser.createProject(
|
||||
'rogue project',
|
||||
(err, rogueProjectId) => {
|
||||
expect(err).to.not.exist
|
||||
this.otherUser.request.post(
|
||||
{ url: `/tag/${firstTagId}/project/${rogueProjectId}` },
|
||||
(err, response) => {
|
||||
_expect204(err, response)
|
||||
// Get original user tags again
|
||||
_getTags(this.user, (err, response, body) => {
|
||||
_expect200(err, response)
|
||||
// Check the rogue project has not been added to project_ids
|
||||
expect(
|
||||
_.find(body, tag => tag.name === 'one').project_ids
|
||||
).to.deep.equal([])
|
||||
done()
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,33 +0,0 @@
|
||||
const express = require('express')
|
||||
const app = express()
|
||||
|
||||
const MockTagsApi = {
|
||||
tags: {},
|
||||
|
||||
run() {
|
||||
app.get('/user/:userId/tag', (req, res) => {
|
||||
const { userId } = req.params
|
||||
const tags = this.tags[userId]
|
||||
res.json(tags)
|
||||
})
|
||||
|
||||
app.delete('/user/:user_id/project/:project_id', (req, res) => {
|
||||
res.sendStatus(200)
|
||||
})
|
||||
|
||||
app
|
||||
.listen(3012, error => {
|
||||
if (error) {
|
||||
throw error
|
||||
}
|
||||
})
|
||||
.on('error', error => {
|
||||
console.error('error starting MockTagsApi:', error.message)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
MockTagsApi.run()
|
||||
|
||||
module.exports = MockTagsApi
|
||||
@@ -21,8 +21,8 @@ const modulePath = require('path').join(
|
||||
)
|
||||
|
||||
describe('TagsController', function() {
|
||||
const user_id = '123nd3ijdks'
|
||||
const project_id = '123njdskj9jlk'
|
||||
const userId = '123nd3ijdks'
|
||||
const projectId = '123njdskj9jlk'
|
||||
const tag = 'some_class101'
|
||||
|
||||
beforeEach(function() {
|
||||
@@ -54,11 +54,11 @@ describe('TagsController', function() {
|
||||
})
|
||||
this.req = {
|
||||
params: {
|
||||
project_id
|
||||
projectId
|
||||
},
|
||||
session: {
|
||||
user: {
|
||||
_id: user_id
|
||||
_id: userId
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ describe('TagsController', function() {
|
||||
return this.controller.getAllTags(this.req, {
|
||||
json: body => {
|
||||
body.should.equal(allTags)
|
||||
this.handler.getAllTags.calledWith(user_id).should.equal(true)
|
||||
this.handler.getAllTags.calledWith(userId).should.equal(true)
|
||||
return done()
|
||||
}
|
||||
})
|
||||
@@ -86,14 +86,14 @@ describe('TagsController', function() {
|
||||
describe('createTag', function() {
|
||||
beforeEach(function() {
|
||||
this.handler.createTag.callsArgWith(2, null, (this.tag = { mock: 'tag' }))
|
||||
this.req.session.user._id = this.user_id = 'user-id-123'
|
||||
this.req.session.user._id = this.userId = 'user-id-123'
|
||||
this.req.body = { name: (this.name = 'tag-name') }
|
||||
return this.controller.createTag(this.req, this.res)
|
||||
})
|
||||
|
||||
it('should create the tag in the backend', function() {
|
||||
return this.handler.createTag
|
||||
.calledWith(this.user_id, this.name)
|
||||
.calledWith(this.userId, this.name)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
@@ -104,14 +104,14 @@ describe('TagsController', function() {
|
||||
|
||||
describe('deleteTag', function() {
|
||||
beforeEach(function() {
|
||||
this.req.params.tag_id = this.tag_id = 'tag-id-123'
|
||||
this.req.session.user._id = this.user_id = 'user-id-123'
|
||||
this.req.params.tagId = this.tagId = 'tag-id-123'
|
||||
this.req.session.user._id = this.userId = 'user-id-123'
|
||||
return this.controller.deleteTag(this.req, this.res)
|
||||
})
|
||||
|
||||
it('should delete the tag in the backend', function() {
|
||||
return this.handler.deleteTag
|
||||
.calledWith(this.user_id, this.tag_id)
|
||||
.calledWith(this.userId, this.tagId)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
@@ -123,8 +123,8 @@ describe('TagsController', function() {
|
||||
|
||||
describe('renameTag', function() {
|
||||
beforeEach(function() {
|
||||
this.req.params.tag_id = this.tag_id = 'tag-id-123'
|
||||
return (this.req.session.user._id = this.user_id = 'user-id-123')
|
||||
this.req.params.tagId = this.tagId = 'tag-id-123'
|
||||
return (this.req.session.user._id = this.userId = 'user-id-123')
|
||||
})
|
||||
|
||||
describe('with a name', function() {
|
||||
@@ -135,7 +135,7 @@ describe('TagsController', function() {
|
||||
|
||||
it('should delete the tag in the backend', function() {
|
||||
return this.handler.renameTag
|
||||
.calledWith(this.user_id, this.tag_id, this.name)
|
||||
.calledWith(this.userId, this.tagId, this.name)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
@@ -163,15 +163,15 @@ describe('TagsController', function() {
|
||||
|
||||
describe('addProjectToTag', function() {
|
||||
beforeEach(function() {
|
||||
this.req.params.tag_id = this.tag_id = 'tag-id-123'
|
||||
this.req.params.project_id = this.project_id = 'project-id-123'
|
||||
this.req.session.user._id = this.user_id = 'user-id-123'
|
||||
this.req.params.tagId = this.tagId = 'tag-id-123'
|
||||
this.req.params.projectId = this.projectId = 'project-id-123'
|
||||
this.req.session.user._id = this.userId = 'user-id-123'
|
||||
return this.controller.addProjectToTag(this.req, this.res)
|
||||
})
|
||||
|
||||
it('should add the tag to the project in the backend', function() {
|
||||
return this.handler.addProjectToTag
|
||||
.calledWith(this.user_id, this.tag_id, this.project_id)
|
||||
.calledWith(this.userId, this.tagId, this.projectId)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
@@ -183,15 +183,15 @@ describe('TagsController', function() {
|
||||
|
||||
describe('removeProjectFromTag', function() {
|
||||
beforeEach(function() {
|
||||
this.req.params.tag_id = this.tag_id = 'tag-id-123'
|
||||
this.req.params.project_id = this.project_id = 'project-id-123'
|
||||
this.req.session.user._id = this.user_id = 'user-id-123'
|
||||
this.req.params.tagId = this.tagId = 'tag-id-123'
|
||||
this.req.params.projectId = this.projectId = 'project-id-123'
|
||||
this.req.session.user._id = this.userId = 'user-id-123'
|
||||
return this.controller.removeProjectFromTag(this.req, this.res)
|
||||
})
|
||||
|
||||
it('should remove the tag from the project in the backend', function() {
|
||||
return this.handler.removeProjectFromTag
|
||||
.calledWith(this.user_id, this.tag_id, this.project_id)
|
||||
.calledWith(this.userId, this.tagId, this.projectId)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
|
||||
@@ -1,425 +1,260 @@
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const { assert } = require('chai')
|
||||
const { expect } = require('chai')
|
||||
require('chai').should()
|
||||
const sinon = require('sinon')
|
||||
const { Tag } = require('../helpers/models/Tag')
|
||||
const { ObjectId } = require('mongojs')
|
||||
const modulePath = require('path').join(
|
||||
__dirname,
|
||||
'../../../../app/src/Features/Tags/TagsHandler.js'
|
||||
)
|
||||
describe('TagsHandler', function() {
|
||||
const userId = 'user-id-123'
|
||||
const tagId = 'tag-id-123'
|
||||
const projectId = 'project-id-123'
|
||||
const tagsUrl = 'tags.sharelatex.testing'
|
||||
const tag = 'tag_name'
|
||||
|
||||
describe('TagsHandler', function() {
|
||||
beforeEach(function() {
|
||||
this.request = {
|
||||
post: sinon.stub().callsArgWith(1),
|
||||
del: sinon.stub().callsArgWith(1),
|
||||
get: sinon.stub()
|
||||
}
|
||||
this.userId = ObjectId().toString()
|
||||
this.callback = sinon.stub()
|
||||
this.handler = SandboxedModule.require(modulePath, {
|
||||
globals: {
|
||||
console: console
|
||||
},
|
||||
|
||||
this.tag = { user_id: this.userId, name: 'some name' }
|
||||
this.tagId = ObjectId().toString()
|
||||
this.projectId = ObjectId().toString()
|
||||
|
||||
this.mongojs = { ObjectId: ObjectId }
|
||||
this.TagMock = sinon.mock(Tag)
|
||||
|
||||
this.TagsHandler = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'settings-sharelatex': {
|
||||
apis: { tags: { url: tagsUrl } }
|
||||
},
|
||||
request: this.request,
|
||||
'logger-sharelatex': {
|
||||
log() {},
|
||||
warn() {},
|
||||
err() {}
|
||||
}
|
||||
'../../infrastructure/mongojs': this.mongojs,
|
||||
'../../models/Tag': { Tag: Tag }
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('removeProjectFromAllTags', function() {
|
||||
it('should tell the tags api to remove the project_id from all the users tags', function(done) {
|
||||
this.handler.removeProjectFromAllTags(userId, projectId, () => {
|
||||
this.request.del
|
||||
.calledWith({
|
||||
url: `${tagsUrl}/user/${userId}/project/${projectId}`,
|
||||
timeout: 10000
|
||||
})
|
||||
.should.equal(true)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getAllTags', function() {
|
||||
it('should get all tags', function(done) {
|
||||
const stubbedAllTags = [
|
||||
{ name: 'tag', project_ids: ['123423', '423423'] }
|
||||
]
|
||||
this.request.get.callsArgWith(
|
||||
1,
|
||||
null,
|
||||
{ statusCode: 200 },
|
||||
stubbedAllTags
|
||||
)
|
||||
this.handler.getAllTags(userId, (err, allTags) => {
|
||||
assert.notExists(err)
|
||||
stubbedAllTags.should.deep.equal(allTags)
|
||||
const getOpts = {
|
||||
url: `${tagsUrl}/user/${userId}/tag`,
|
||||
json: true,
|
||||
timeout: 10000
|
||||
}
|
||||
this.request.get.calledWith(getOpts).should.equal(true)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should callback with an empty array on error', function(done) {
|
||||
this.request.get.callsArgWith(
|
||||
1,
|
||||
{ something: 'wrong' },
|
||||
{ statusCode: 200 },
|
||||
[]
|
||||
)
|
||||
this.handler.getAllTags(userId, (err, allTags) => {
|
||||
allTags.length.should.equal(0)
|
||||
assert.isDefined(err)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should callback with an empty array if there are no tags', function(done) {
|
||||
this.request.get.callsArgWith(
|
||||
1,
|
||||
{ something: 'wrong' },
|
||||
{ statusCode: 200 },
|
||||
undefined
|
||||
)
|
||||
this.handler.getAllTags(userId, (err, allTags) => {
|
||||
allTags.length.should.equal(0)
|
||||
assert.isDefined(err)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should callback with an empty array on a non 200 response', function(done) {
|
||||
this.request.get.callsArgWith(1, null, { statusCode: 201 }, [])
|
||||
this.handler.getAllTags(userId, (err, allTags) => {
|
||||
allTags.length.should.equal(0)
|
||||
assert.isDefined(err)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should callback with an empty array on no body and no response', function(done) {
|
||||
this.request.get.callsArgWith(
|
||||
1,
|
||||
{ something: 'wrong' },
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
this.handler.getAllTags(userId, (err, allTags) => {
|
||||
allTags.length.should.equal(0)
|
||||
assert.isDefined(err)
|
||||
describe('finding users tags', function() {
|
||||
it('should find all the documents with that user id', function(done) {
|
||||
const stubbedTags = [{ name: 'tag1' }, { name: 'tag2' }, { name: 'tag3' }]
|
||||
this.TagMock.expects('find')
|
||||
.once()
|
||||
.withArgs({ user_id: this.userId })
|
||||
.yields(null, stubbedTags)
|
||||
this.TagsHandler.getAllTags(this.userId, (err, result) => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
expect(result).to.deep.equal(stubbedTags)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('createTag', function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 }, '')
|
||||
this.handler.createTag(userId, (this.name = 'tag_name'), this.callback)
|
||||
})
|
||||
|
||||
it('should send a request to the tag backend', function() {
|
||||
this.request.post
|
||||
.calledWith({
|
||||
url: `${tagsUrl}/user/${userId}/tag`,
|
||||
json: {
|
||||
name: this.name
|
||||
},
|
||||
timeout: 10000
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with no error', function() {
|
||||
this.callback.calledWith(null).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('deleteTag', function() {
|
||||
describe('successfully', function() {
|
||||
beforeEach(function() {
|
||||
this.request.del = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 }, '')
|
||||
this.handler.deleteTag(userId, tagId, this.callback)
|
||||
})
|
||||
|
||||
it('should send a request to the tag backend', function() {
|
||||
this.request.del
|
||||
.calledWith({
|
||||
url: `${tagsUrl}/user/${userId}/tag/${tagId}`,
|
||||
timeout: 10000
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with no error', function() {
|
||||
this.callback.calledWith(null).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with error', function() {
|
||||
beforeEach(function() {
|
||||
this.request.del = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
this.handler.deleteTag(userId, tagId, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with an Error', function() {
|
||||
this.callback
|
||||
.calledWith(sinon.match.instanceOf(Error))
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('renameTag', function() {
|
||||
describe('successfully', function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 }, '')
|
||||
this.handler.renameTag(
|
||||
userId,
|
||||
tagId,
|
||||
(this.name = 'new-name'),
|
||||
this.callback
|
||||
describe('when insert succeeds', function() {
|
||||
it('should call insert in mongo', function(done) {
|
||||
this.TagMock.expects('create')
|
||||
.withArgs(this.tag)
|
||||
.once()
|
||||
.yields(null, this.tag)
|
||||
this.TagsHandler.createTag(
|
||||
this.tag.user_id,
|
||||
this.tag.name,
|
||||
(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)
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it('should send a request to the tag backend', function() {
|
||||
this.request.post
|
||||
.calledWith({
|
||||
url: `${tagsUrl}/user/${userId}/tag/${tagId}/rename`,
|
||||
json: {
|
||||
name: this.name
|
||||
},
|
||||
timeout: 10000
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with no error', function() {
|
||||
this.callback.calledWith(null).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with error', function() {
|
||||
describe('when insert has duplicate key error error', function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
this.handler.renameTag(userId, tagId, 'name', this.callback)
|
||||
this.duplicateKeyError = new Error('Duplicate')
|
||||
this.duplicateKeyError.code = 11000
|
||||
})
|
||||
|
||||
it('should call the callback with an Error', function() {
|
||||
this.callback
|
||||
.calledWith(sinon.match.instanceOf(Error))
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('removeProjectFromTag', function() {
|
||||
describe('successfully', function() {
|
||||
beforeEach(function() {
|
||||
this.request.del = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 }, '')
|
||||
this.handler.removeProjectFromTag(
|
||||
userId,
|
||||
tagId,
|
||||
projectId,
|
||||
this.callback
|
||||
it('should get tag with findOne and return that tag', function(done) {
|
||||
this.TagMock.expects('create')
|
||||
.withArgs(this.tag)
|
||||
.once()
|
||||
.yields(this.duplicateKeyError)
|
||||
this.TagMock.expects('findOne')
|
||||
.withArgs({ user_id: this.tag.user_id, name: this.tag.name })
|
||||
.once()
|
||||
.yields(null, this.tag)
|
||||
this.TagsHandler.createTag(
|
||||
this.tag.user_id,
|
||||
this.tag.name,
|
||||
(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)
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it('should send a request to the tag backend', function() {
|
||||
this.request.del
|
||||
.calledWith({
|
||||
url: `${tagsUrl}/user/${userId}/tag/${tagId}/project/${projectId}`,
|
||||
timeout: 10000
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with no error', function() {
|
||||
this.callback.calledWith(null).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with error', function() {
|
||||
beforeEach(function() {
|
||||
this.request.del = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
this.handler.removeProjectFromTag(
|
||||
userId,
|
||||
tagId,
|
||||
projectId,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback with an Error', function() {
|
||||
this.callback
|
||||
.calledWith(sinon.match.instanceOf(Error))
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('addProjectToTag', function() {
|
||||
describe('successfully', function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 }, '')
|
||||
this.handler.addProjectToTag(userId, tagId, projectId, this.callback)
|
||||
})
|
||||
describe('with a valid tag_id', function() {
|
||||
beforeEach(function() {})
|
||||
|
||||
it('should send a request to the tag backend', function() {
|
||||
this.request.post
|
||||
.calledWith({
|
||||
url: `${tagsUrl}/user/${userId}/tag/${tagId}/project/${projectId}`,
|
||||
timeout: 10000
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with no error', function() {
|
||||
this.callback.calledWith(null).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with error', function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
this.handler.addProjectToTag(userId, tagId, projectId, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with an Error', function() {
|
||||
this.callback
|
||||
.calledWith(sinon.match.instanceOf(Error))
|
||||
.should.equal(true)
|
||||
it('should call update in mongo', function(done) {
|
||||
this.TagMock.expects('findOneAndUpdate')
|
||||
.once()
|
||||
.withArgs(
|
||||
{ _id: this.tagId, user_id: this.userId },
|
||||
{ $addToSet: { project_ids: this.projectId } }
|
||||
)
|
||||
.yields()
|
||||
this.TagsHandler.addProjectToTag(
|
||||
this.userId,
|
||||
this.tagId,
|
||||
this.projectId,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('addProjectToTagName', function() {
|
||||
describe('successfully', function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 }, '')
|
||||
this.handler.addProjectToTagName(userId, tag, projectId, this.callback)
|
||||
})
|
||||
|
||||
it('should send a request to the tag backend', function() {
|
||||
this.request.post
|
||||
.calledWith({
|
||||
json: {
|
||||
name: tag
|
||||
},
|
||||
url: `${tagsUrl}/user/${userId}/tag/project/${projectId}`,
|
||||
timeout: 10000
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with no error', function() {
|
||||
this.callback.calledWith(null).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with error', function() {
|
||||
beforeEach(function() {
|
||||
this.request.post = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
this.handler.addProjectToTagName(
|
||||
userId,
|
||||
tagId,
|
||||
projectId,
|
||||
this.callback
|
||||
it('should call update in mongo', function(done) {
|
||||
this.TagMock.expects('update')
|
||||
.once()
|
||||
.withArgs(
|
||||
{ name: this.tag.name, user_id: this.tag.userId },
|
||||
{ $addToSet: { project_ids: this.projectId } },
|
||||
{ upsert: true }
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback with an Error', function() {
|
||||
this.callback
|
||||
.calledWith(sinon.match.instanceOf(Error))
|
||||
.should.equal(true)
|
||||
})
|
||||
.yields()
|
||||
this.TagsHandler.addProjectToTagName(
|
||||
this.tag.userId,
|
||||
this.tag.name,
|
||||
this.projectId,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('updateTagUserIds', function() {
|
||||
describe('successfully', function() {
|
||||
beforeEach(function() {
|
||||
this.request.put = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 204 }, '')
|
||||
this.handler.updateTagUserIds(
|
||||
'old-user-id',
|
||||
'new-user-id',
|
||||
this.callback
|
||||
it('should call update in mongo', function(done) {
|
||||
this.newUserId = ObjectId().toString()
|
||||
this.TagMock.expects('update')
|
||||
.once()
|
||||
.withArgs(
|
||||
{ user_id: this.userId },
|
||||
{ $set: { user_id: this.newUserId } },
|
||||
{ multi: true }
|
||||
)
|
||||
})
|
||||
|
||||
it('should send a request to the tag backend', function() {
|
||||
this.request.put
|
||||
.calledWith({
|
||||
json: {
|
||||
user_id: 'new-user-id'
|
||||
},
|
||||
url: `${tagsUrl}/user/old-user-id/tag`,
|
||||
timeout: 10000
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with no error', function() {
|
||||
this.callback.calledWith(null).should.equal(true)
|
||||
.yields()
|
||||
this.TagsHandler.updateTagUserIds(this.userId, this.newUserId, err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with error', function() {
|
||||
beforeEach(function() {
|
||||
this.request.put = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, { statusCode: 500 }, '')
|
||||
this.handler.updateTagUserIds(
|
||||
'old-user-id',
|
||||
'new-user-id',
|
||||
this.callback
|
||||
describe('removeProjectFromTag', function() {
|
||||
describe('with a valid tag_id', function() {
|
||||
it('should call update in mongo', function(done) {
|
||||
this.TagMock.expects('update')
|
||||
.once()
|
||||
.withArgs(
|
||||
{
|
||||
_id: this.tagId,
|
||||
user_id: this.userId
|
||||
},
|
||||
{
|
||||
$pull: { project_ids: this.projectId }
|
||||
}
|
||||
)
|
||||
.yields()
|
||||
this.TagsHandler.removeProjectFromTag(
|
||||
this.userId,
|
||||
this.tagId,
|
||||
this.projectId,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the callback with an Error', function() {
|
||||
this.callback
|
||||
.calledWith(sinon.match.instanceOf(Error))
|
||||
.should.equal(true)
|
||||
describe('removeProjectFromAllTags', function() {
|
||||
it('should pull the project id from the tag', function(done) {
|
||||
this.TagMock.expects('update')
|
||||
.once()
|
||||
.withArgs(
|
||||
{
|
||||
user_id: this.userId
|
||||
},
|
||||
{
|
||||
$pull: { project_ids: this.projectId }
|
||||
}
|
||||
)
|
||||
.yields()
|
||||
this.TagsHandler.removeProjectFromAllTags(
|
||||
this.userId,
|
||||
this.projectId,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('deleteTag', function() {
|
||||
describe('with a valid tag_id', function() {
|
||||
it('should call remove in mongo', function(done) {
|
||||
this.TagMock.expects('remove')
|
||||
.once()
|
||||
.withArgs({ _id: this.tagId, user_id: this.userId })
|
||||
.yields()
|
||||
this.TagsHandler.deleteTag(this.userId, this.tagId, err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('renameTag', function() {
|
||||
describe('with a valid tag_id', function() {
|
||||
it('should call remove in mongo', function(done) {
|
||||
this.newName = 'new name'
|
||||
this.TagMock.expects('update')
|
||||
.once()
|
||||
.withArgs(
|
||||
{ _id: this.tagId, user_id: this.userId },
|
||||
{ $set: { name: this.newName } }
|
||||
)
|
||||
.yields()
|
||||
this.TagsHandler.renameTag(
|
||||
this.userId,
|
||||
this.tagId,
|
||||
this.newName,
|
||||
err => {
|
||||
expect(err).to.not.exist
|
||||
this.TagMock.verify()
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
const mockModel = require('../MockModel')
|
||||
|
||||
module.exports = mockModel('Tag')
|
||||
Reference in New Issue
Block a user