Merge pull request #15 from coralproject/comment-api

Comment api
This commit is contained in:
Riley Davis
2016-11-04 16:19:08 -06:00
committed by GitHub
15 changed files with 427 additions and 42 deletions
+1
View File
@@ -4,3 +4,4 @@ dist
.DS_Store
*.iml
.env
gaba.cfg
+10 -3
View File
@@ -1,5 +1,3 @@
'use strict';
const mongoose = require('../mongoose');
const uuid = require('uuid');
const Schema = mongoose.Schema;
@@ -15,7 +13,6 @@ const ActionSchema = new Schema({
item_id: String,
user_id: String
},{
_id: false,
timestamps: {
createdAt: 'created_at',
updatedAt: 'updated_at'
@@ -30,6 +27,16 @@ ActionSchema.statics.findById = function(id) {
return Action.findOne({id});
};
/**
* Finds users in an array of ids.
* @param {String} ids array of user identifiers (uuid)
*/
ActionSchema.statics.findByItemIdArray = function(item_ids) {
return Action.find({
'item_id': {$in: item_ids}
});
};
const Action = mongoose.model('Action', ActionSchema);
module.exports = Action;
+11 -5
View File
@@ -1,5 +1,3 @@
'use strict';
const mongoose = require('../mongoose');
const uuid = require('uuid');
const Schema = mongoose.Schema;
@@ -13,7 +11,7 @@ const CommentSchema = new Schema({
body: {
type: String,
required: [true, 'The body is required.'],
minlength: 50
minlength: 2
},
asset_id: String,
author_id: String,
@@ -24,7 +22,6 @@ const CommentSchema = new Schema({
},
parent_id: String
},{
_id: false,
timestamps: {
createdAt: 'created_at',
updatedAt: 'updated_at'
@@ -33,12 +30,21 @@ const CommentSchema = new Schema({
/**
* Finds a comment by the id.
* @param {String} id identifier of the comment (uuid)
* @param {String} asset_id identifier of comment (uuid)
*/
CommentSchema.statics.findById = function(id) {
return Comment.findOne({id});
};
/**
* Finds a comment by the asset_id.
* @param {String} asset_id identifier of the asset which owns this comment (uuid)
*/
CommentSchema.statics.findByAssetId = function(asset_id) {
return Comment.find({asset_id});
};
const Comment = mongoose.model('Comment', CommentSchema);
module.exports = Comment;
+10 -2
View File
@@ -1,4 +1,3 @@
'use strict';
const mongoose = require('../mongoose');
const uuid = require('uuid');
@@ -13,7 +12,6 @@ const UserProfileSchema = new Schema({
display_name: String,
auth_user_id: String
},{
_id: false,
timestamps: {
createdAt: 'created_at',
updatedAt: 'updated_at'
@@ -28,6 +26,16 @@ UserProfileSchema.statics.findById = function(id) {
return UserProfile.findOne({id});
};
/**
* Finds users in an array of idd.
* @param {String} idd array of user identifiers (uuid)
*/
UserProfileSchema.statics.findByIdArray = function(ids) {
return UserProfile.find({
'id': {$in: ids}
});
};
// TO DO: methods
// modifications to user as statics
// find by auth user id
+4 -1
View File
@@ -8,7 +8,8 @@
"build": "webpack --config ./client/coral-embed-stream/webpack.config.js",
"lint": "eslint .",
"pretest": "npm install",
"test": "mocha tests",
"test": "mocha tests --recursive",
"test-watch": "mocha tests --recursive -w",
"embed-start": "node client/coral-embed-stream/dev-server.js"
},
"config": {
@@ -45,6 +46,7 @@
"debug": "^2.2.0",
"express": "^4.14.0",
"mongoose": "^4.6.5",
"uuid": "^2.0.3",
"morgan": "^1.7.0"
},
"devDependencies": {
@@ -60,6 +62,7 @@
"babel-preset-es2015-minimal": "^2.1.0",
"babel-preset-stage-0": "^6.16.0",
"chai": "^3.5.0",
"chai-http": "^1.0.0",
"copy-webpack-plugin": "^3.0.1",
"eslint": "^3.9.1",
"exports-loader": "^0.6.3",
+26 -4
View File
@@ -1,17 +1,39 @@
const express = require('express');
const Comment = require('../../../models/comment');
const router = express.Router();
//==============================================================================
// Routes
//==============================================================================
router.get('/', (req, res) => {
res.send('Read all of the comments ever');
});
router.get('/:comment_id', (req, res) => {
res.send('Read a comment');
router.get('/:comment_id', (req, res, next) => {
Comment.findById(req.params.comment_id).then((comment) => {
res.status(200).json(comment);
}).catch(error => {
next(error);
});
});
router.post('/', (req, res) => {
res.send('Write a comment');
router.post('/', (req, res, next) => {
let comment = new Comment({
body: req.query.body,
author_id: req.query.author_id,
asset_id: req.query.asset_id,
parent_id: req.query.parent_id,
status: req.query.status
});
comment.save().then(({id}) => {
res.status(201).send(id);
}).catch(error => {
next(error);
});
});
router.put('/:comment_id', (req, res) => {
+19 -26
View File
@@ -1,33 +1,26 @@
const express = require('express');
const Comment = require('../../../models/comment');
const User = require('../../../models/user');
const Action = require('../../../models/action');
const router = express.Router();
router.get('/', (req, res) => {
console.log('Stream endpoint has been hit with asset_id ', req.query.asset_id);
res.json([
{
'id': 'abc',
'type': 'comment',
'body': 'Sample comment',
'created_at': new Date().getTime(),
'asset_id': 'assetTest'
},
{
'id': 'xyz',
'type': 'comment',
'body': 'Sample reply',
'created_at': new Date().getTime() - 600000,
'parent_id': 'abc',
'asset_id': 'assetTest'
},
{
'id': 'def',
'type': 'comment',
'body': 'Another comment',
'created_at': new Date().getTime() - 400000,
'asset_id': 'assetTest'
}
]);
router.get('/', (req, res, next) => {
const commentsPromise = Comment.findByAssetId(req.query.asset_id);
commentsPromise.then(comments => {
return Promise.all([
comments,
User.findByIdArray(comments.map((comment) => comment.author_id)),
Action.findByItemIdArray(comments.map((comment) => comment.id))
]);
}).then(([comments, users, actions]) => {
res.json([...comments,...users,...actions]);
}).catch(error => {
next(error);
});
});
module.exports = router;
+10
View File
@@ -0,0 +1,10 @@
{
"env": {
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"rules": {
"no-undef": [0]
}
}
+3 -1
View File
@@ -1,10 +1,12 @@
/* eslint-env node, mocha */
'use strict';
// require('./utils/mongoose')
const expect = require('chai').expect;
describe('Comment', () => {
describe.only('#add', () => {
describe('#add', () => {
it('should add a comment', () => {
expect(0).to.be.equal(0);
});
+40
View File
@@ -0,0 +1,40 @@
/* eslint-env node, mocha */
require('../utils/mongoose');
const Action = require('../../models/action');
const expect = require('chai').expect;
describe('Action: models', () => {
var mockActions;
beforeEach(() => {
return Action.create([{
action_type: 'flag',
item_id: '123'
},{
action_type: 'like',
item_id: '789'
},{
action_type: 'flag',
item_id: '456'
}]).then((actions) => {
mockActions = actions;
});
});
describe('#findById()', () => {
it('should find an action by id', () => {
return Action.findById(mockActions[0].id).then((result) => {
expect(result).to.have.property('action_type')
.and.to.equal('flag');
});
});
});
describe('#findByItemIdArray()', () => {
it('should find an array of actions from an array of item_ids', () => {
return Action.findByItemIdArray(['123','456']).then((result) => {
expect(result).to.have.length(2);
});
});
});
});
+51
View File
@@ -0,0 +1,51 @@
/* eslint-env node, mocha */
require('../utils/mongoose');
const Comment = require('../../models/comment');
const expect = require('chai').expect;
describe('Comment: models', () => {
var mockComments;
beforeEach(() => {
return Comment.create([{
body: 'comment 10',
asset_id: '123'
},{
body: 'comment 20',
asset_id: '123'
},{
body: 'comment 30',
asset_id: '456'
}]).then((comments) => {
mockComments = comments;
});
});
describe('#findById()', () => {
it('should find a comment by id', () => {
return Comment.findById(mockComments[0].id).then((result) => {
expect(result).to.have.property('body')
.and.to.equal('comment 10');
});
});
});
describe('#findByAssetId()', () => {
it('should find an array of comments by asset id', () => {
return Comment.findByAssetId('123').then((result) => {
expect(result).to.have.length(2);
result.sort((a,b) => {
if (a.body < b.body) {return -1;}
else {return 1;}
});
expect(result[0]).to.have.property('body')
.and.to.equal('comment 10');
expect(result[1]).to.have.property('body')
.and.to.equal('comment 20');
});
});
});
// });
});
+40
View File
@@ -0,0 +1,40 @@
/* eslint-env node, mocha */
require('../utils/mongoose');
const User = require('../../models/user');
const expect = require('chai').expect;
describe('User: models', () => {
var mockUsers;
beforeEach(() => {
return User.create([{
display_name: 'Stampi',
},{
display_name: 'Sockmonster',
},{
display_name: 'Marvel',
}]).then((users) => {
mockUsers = users;
});
});
describe('#findById()', () => {
it('should find a user by id', () => {
return User.findById(mockUsers[0].id).then((result) => {
expect(result).to.have.property('display_name')
.and.to.equal('Stampi');
});
});
});
describe('#findByIdArray()', () => {
it('should find an array of users from an array of ids', () => {
const ids = mockUsers.map((user) => user.id)
return User.findByIdArray(ids).then((result) => {
expect(result).to.have.length(3);
});
});
});
// });
});
+106
View File
@@ -0,0 +1,106 @@
process.env.NODE_ENV = 'test';
require('../../../utils/mongoose');
const app = require('../../../../app');
const chai = require('chai');
const chaiHttp = require('chai-http');
chai.use(chaiHttp);
var expect = chai.expect;
const Comment = require('../../../../models/comment');
const Action = require('../../../../models/action');
const User = require('../../../../models/user');
describe('Post /comments', () => {
const users = [{
id: '123',
display_name: 'John',
},{
id: '456',
display_name: 'Paul',
}]
const actions = [{
action_type: 'flag',
item_id: 'abc'
},{
action_type: 'like',
item_id: 'hij'
}]
beforeEach(() => {
return User.create(users).then(() => {
return Action.create(actions)
})
})
it('it should create a comment', function(done) {
chai.request(app)
.post('/api/v1/comments')
.query({'body': 'Something body.', 'author_id': '123', 'asset_id': '1', 'parent_id': ''})
.end(function(err, res){
expect(res).to.have.status(201)
done()
})
})
})
describe('Get /:comment_id', () => {
const comments = [{
id: 'abc',
body: 'comment 10',
asset_id: 'asset',
author_id: '123'
},{
id: 'def',
body: 'comment 20',
asset_id: 'asset',
author_id: '456'
},{
id: 'hij',
body: 'comment 30',
asset_id: '456'
}]
const users = [{
id: '123',
display_name: 'John',
},{
id: '456',
display_name: 'Paul',
}]
const actions = [{
action_type: 'flag',
item_id: 'abc'
},{
action_type: 'like',
item_id: 'hij'
}]
beforeEach(() => {
return Comment.create(comments).then(() => {
return User.create(users)
}).then(() => {
return Action.create(actions)
})
})
it('should return the right comment for the comment_id', function(done){
chai.request(app)
.get('/api/v1/comments')
.query({'comment_id': 'abc'})
.end(function(err, res){
expect(err).to.be.null;
expect(res).to.have.status(200);
if (err) return done(err);
done();
});
})
})
+65
View File
@@ -0,0 +1,65 @@
require('../../../utils/mongoose');
const app = require('../../../../app');
const chai = require('chai');
const chaiHttp = require('chai-http');
chai.use(chaiHttp);
var expect = chai.expect;
const Action = require('../../../../models/action');
const User = require('../../../../models/user');
const Comment = require('../../../../models/comment');
describe('api/stream: routes', () => {
const comments = [{
id: 'abc',
body: 'comment 10',
asset_id: 'asset',
author_id: '123'
},{
id: 'def',
body: 'comment 20',
asset_id: 'asset',
author_id: '456'
},{
id: 'hij',
body: 'comment 30',
asset_id: '456'
}]
const users = [{
id: '123',
display_name: 'John',
},{
id: '456',
display_name: 'Paul',
}]
const actions = [{
action_type: 'flag',
item_id: 'abc'
},{
action_type: 'like',
item_id: 'hij'
}]
beforeEach(() => {
return Comment.create(comments).then(() => {
return User.create(users)
}).then(() => {
return Action.create(actions)
})
})
it('should return a stream with comments, users and actions', function(done){
chai.request(app)
.get('/api/v1/stream')
.query({'asset_id': 'asset'})
.end(function(err, res){
expect(err).to.be.null;
expect(res).to.have.status(200);
if (err) return done(err);
done();
});
})
})
+31
View File
@@ -0,0 +1,31 @@
var mongoose = require('mongoose');
// Ensure the NODE_ENV is set to 'test',
// this is helpful when you would like to change behavior when testing.
process.env.NODE_ENV = 'test';
beforeEach(function (done) {
function clearDB() {
for (var i in mongoose.connection.collections) {
mongoose.connection.collections[i].remove(function() {});
}
return done();
}
if (mongoose.connection.readyState === 0) {
mongoose.connect('coral-talk-test', function (err) {
if (err) {
throw err;
}
return clearDB();
});
} else {
return clearDB();
}
});
after(function (done) {
mongoose.disconnect();
return done();
});