From db6757b99e34377a1a26613a831c509045606633 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 2 Nov 2016 14:43:42 -0700 Subject: [PATCH 01/15] Adding stream endpoint and mocking --- routes/api/index.js | 1 + routes/api/stream/index.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 routes/api/stream/index.js diff --git a/routes/api/index.js b/routes/api/index.js index 7390f2010..bc6b45366 100644 --- a/routes/api/index.js +++ b/routes/api/index.js @@ -3,5 +3,6 @@ const express = require('express'); const router = express.Router(); router.use('/comments', require('./comments')); +router.use('/stream', require('./stream')); module.exports = router; diff --git a/routes/api/stream/index.js b/routes/api/stream/index.js new file mode 100644 index 000000000..f1b1536d2 --- /dev/null +++ b/routes/api/stream/index.js @@ -0,0 +1,34 @@ +const express = require('express'); + +const router = express.Router(); + +router.get('/', (req, res) => { + console.log('asset_id, should be assetTest', req.query.asset_id) + res.setHeader('Content-Type', 'application/json'); + res.send(JSON.stringify([ + { + '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' + } + ])); +}); + +module.exports = router; From 1c70b332605ff7c8b548b86a52820520a0f33363 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 2 Nov 2016 15:37:07 -0700 Subject: [PATCH 02/15] Adding route for static hosting of build files --- app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app.js b/app.js index e7ded2f9c..7ce7c91ab 100644 --- a/app.js +++ b/app.js @@ -6,5 +6,6 @@ const express = require('express'); const app = express(); app.use('/api/v1', require('./routes/api')); +app.use('/client/', express.static('./dist')); module.exports = app; From 15114c1b337885338570b08529ccd6f616741f0e Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 2 Nov 2016 15:37:36 -0700 Subject: [PATCH 03/15] Getting items from endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And updating ‘item_id’ to ‘id’ --- client/coral-framework/store/actions/items.js | 91 +++++++++++-------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/client/coral-framework/store/actions/items.js b/client/coral-framework/store/actions/items.js index fe45feb0c..82bcca52f 100644 --- a/client/coral-framework/store/actions/items.js +++ b/client/coral-framework/store/actions/items.js @@ -10,7 +10,6 @@ import mocks from '../../mocks.json' export const ADD_ITEM = 'ADD_ITEM' export const UPDATE_ITEM = 'UPDATE_ITEM' export const APPEND_ITEM_ARRAY = 'APPEND_ITEM_ARRAY' -export const APPEND_ITEM_RELATED = 'APPEND_ITEM_RELATED' /** * Action creators @@ -26,13 +25,13 @@ export const APPEND_ITEM_RELATED = 'APPEND_ITEM_RELATED' */ export const addItem = (item) => { - if (!item.item_id) { + if (!item.id) { console.warn('addItem called without an item id.') } return { type: ADD_ITEM, item: item, - item_id: item.item_id + id: item.id } } @@ -41,36 +40,26 @@ export const addItem = (item) => { * Useful for item-level toggles, etc. * * @params -* item_id - the id of the item to be posted +* id - the id of the item to be posted * property - the property to be updated * value - the value that the property should be set to * */ -export const updateItem = (item_id, property, value) => { +export const updateItem = (id, property, value) => { return { type: UPDATE_ITEM, - item_id, + id, property, value } } -export const appendItemArray = (item_id, property, value) => { +export const appendItemArray = (id, property, value) => { return { type: APPEND_ITEM_ARRAY, - item_id, - property, - value - } -} - - -export const appendItemRelated = (item_id, property, value) => { - return { - type: APPEND_ITEM_RELATED, - item_id, + id, property, value } @@ -89,26 +78,48 @@ export const appendItemRelated = (item_id, property, value) => { * @dispatches * A set of items to the item store */ -export function getItemsQuery (rootId) { +export function getStream (assetId) { return (dispatch) => { - // return fetch('/v1/exec/view/' + rootId) - // .then( - // response => { - // return response.ok ? response.json() : Promise.reject(response.status + ' ' + response.statusText) - // } - // ) - // .then((json) => { - // let items = json.results[0].Docs - // for (var i = 0; i < items.length; i++) { - // dispatch(addItem(items[i])) - // } - // return (items) - // }) - console.log('Loading mock data', mocks); - let mockData = mocks.query - for (var i=0; i < mockData.length; i++ ) { - dispatch(addItem(mockData[i])) - } + return fetch('/api/v1/stream?asset_id='+assetId) + .then( + response => { + return response.ok ? response.json() : Promise.reject(response.status + ' ' + response.statusText) + } + ) + .then((json) => { + + /* Sort comments by date*/ + let rootComments = [] + let childComments = {} + const sorted = json.sort((a,b) => b.created_at - a.created_at) + sorted.reduce((prev, item) => { + dispatch(addItem(item)) + + /* Check for root and child comments. */ + if ( + item.type === 'comment' && + item.asset_id === assetId && + !item.parent_id) { + rootComments.push(item.id) + } else if ( + item.type === 'comment' && + item.asset_id === assetId + ) { + let children = childComments[item.parent_id] || [] + childComments[item.parent_id] = children.concat(item.id) + } + }, {}) + + dispatch(addItem({ + id: assetId, + comments: rootComments + })) + + Object.keys(childComments).reduce((prev, key) => { + dispatch(updateItem(key, 'children', childComments[key])) + },{}) + return (json) + }) } } @@ -166,7 +177,7 @@ export function postItem (data, type, id) { version: 1 } if (id) { - item.item_id = id + item.id = id } let options = { method: 'POST', @@ -182,7 +193,7 @@ export function postItem (data, type, id) { .then((json) => { // Patch until ID is returned from backend dispatch(addItem(json)) - return json.item_id + return json.id }) } } @@ -194,7 +205,7 @@ export function postItem (data, type, id) { * Posts an action to an item * * @params -* item_id - the id of the item on which the action is taking place +* id - the id of the item on which the action is taking place * action - the name of the action * user - the user performing the action * host - the coral host From 8020213da538bf38a09787d5e7c7bfe76d56b067 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 2 Nov 2016 15:37:58 -0700 Subject: [PATCH 04/15] Updating commentStream to reflect new data structure --- .../coral-embed-stream/src/CommentStream.js | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index 28d35860d..dad8fbbf9 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -14,7 +14,7 @@ import Flag from '../../coral-plugin-flags/FlagButton' import {ReplyBox, ReplyButton} from '../../coral-plugin-replies' import Pym from 'pym.js' -const {addItem, updateItem, postItem, getItemsQuery, postAction, appendItemRelated} = itemActions +const {addItem, updateItem, postItem, getStream, postAction, appendItemArray} = itemActions const {addNotification, clearNotification} = notificationActions const {setLoggedInUser} = authActions @@ -38,8 +38,8 @@ const {setLoggedInUser} = authActions postItem: (data, type, id) => { return dispatch(postItem(data, type, id)) }, - getItemsQuery: (rootId) => { - return dispatch(getItemsQuery(rootId)) + getStream: (rootId) => { + return dispatch(getStream(rootId)) }, addNotification: (type, text) => { return dispatch(addNotification(type, text)) @@ -53,8 +53,8 @@ const {setLoggedInUser} = authActions postAction: (item, action, user) => { return dispatch(postAction(item, action, user)) }, - appendItemRelated: (item, property, value) => { - return dispatch(appendItemRelated(item, property, value)) + appendItemArray: (item, property, value) => { + return dispatch(appendItemArray(item, property, value)) } } } @@ -72,7 +72,7 @@ class CommentStream extends Component { // Set up messaging between embedded Iframe an parent component // Using recommended Pym init code which violates .eslint standards new Pym.Child({ polling: 500 }) - this.props.getItemsQuery('assetTest') + this.props.getStream('assetTest') } render () { @@ -104,53 +104,52 @@ class CommentStream extends Component {
+ id={rootItemId}/>
{ - rootItem.related.comment.map((commentId) => { + rootItem.comments.map((commentId) => { const comment = this.props.items[commentId] return

- +
+ id={commentId}/>
{ - comment.related && - comment.related.child && - comment.related.child.map((replyId) => { + comment.children && + comment.children.map((replyId) => { let reply = this.props.items[replyId] return

- +
From 8f48f62b02c0dd32eb9637c13141105bbc658943 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 2 Nov 2016 15:38:49 -0700 Subject: [PATCH 05/15] Replacing 'item_id' with 'id' and removing appendRelatedArray It now makes sense to have a generic appendItemArray function --- client/coral-framework/store/reducers/items.js | 11 +++-------- client/coral-plugin-comment-count/CommentCount.js | 10 +++++----- client/coral-plugin-commentbox/CommentBox.js | 4 ++-- client/coral-plugin-replies/ReplyBox.js | 2 +- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/client/coral-framework/store/reducers/items.js b/client/coral-framework/store/reducers/items.js index e8f0bbbdf..2bba3bf1b 100644 --- a/client/coral-framework/store/reducers/items.js +++ b/client/coral-framework/store/reducers/items.js @@ -8,18 +8,13 @@ const initialState = fromJS({}) export default (state = initialState, action) => { switch (action.type) { case actions.ADD_ITEM: - return state.set(action.item_id, fromJS(action.item)) + return state.set(action.id, fromJS(action.item)) case actions.UPDATE_ITEM: - return state.updateIn([action.item_id, 'data', action.property], () => + return state.updateIn([action.id, action.property], () => fromJS(action.value) ) case actions.APPEND_ITEM_ARRAY: - return state.updateIn([action.item_id, 'data', action.property], (prop) => { - return prop ? prop.push(action.value) : fromJS([action.value]) - } - ) - case actions.APPEND_ITEM_RELATED: - return state.updateIn([action.item_id, 'related', action.property], (prop) => { + return state.updateIn([action.id, action.property], (prop) => { return prop ? prop.push(action.value) : fromJS([action.value]) } ) diff --git a/client/coral-plugin-comment-count/CommentCount.js b/client/coral-plugin-comment-count/CommentCount.js index 861fc5df3..6c3b2e5eb 100644 --- a/client/coral-plugin-comment-count/CommentCount.js +++ b/client/coral-plugin-comment-count/CommentCount.js @@ -2,16 +2,16 @@ import React from 'react' const name = 'coral-plugin-comment-count' -const CommentCount = ({items, item_id}) => { +const CommentCount = ({items, id}) => { let count = 0 - if (items[item_id]) { - count += items[item_id].related.comment.length + if (items[id]) { + count += items[id].comments.length } const itemKeys = Object.keys(items) for (var i=0; i < itemKeys.length; i++) { const item = items[itemKeys[i]] - if (item.type === 'comment' && item.related && item.related.child) { - count += item.related.child.length + if (item.type === 'comment' && item.children) { + count += item.children.length } } diff --git a/client/coral-plugin-commentbox/CommentBox.js b/client/coral-plugin-commentbox/CommentBox.js index a32144407..f20ced54c 100644 --- a/client/coral-plugin-commentbox/CommentBox.js +++ b/client/coral-plugin-commentbox/CommentBox.js @@ -18,7 +18,7 @@ class CommentBox extends Component { } postComment = () => { - const {postItem, updateItem, item_id, reply, addNotification, appendItemRelated} = this.props + const {postItem, updateItem, item_id, reply, addNotification, appendItemArray} = this.props let comment = { content: this.state.content } @@ -33,7 +33,7 @@ class CommentBox extends Component { updateItem(item_id, 'showReply', false) postItem(comment, 'comment') .then((id) => { - appendItemRelated(item_id, related, id) + appendItemArray(item_id, related, id) addNotification('success', 'Your comment has been posted.') }).catch((err) => console.error(err)) this.setState({content: ''}) diff --git a/client/coral-plugin-replies/ReplyBox.js b/client/coral-plugin-replies/ReplyBox.js index 7a89bdeeb..d496a63f7 100644 --- a/client/coral-plugin-replies/ReplyBox.js +++ b/client/coral-plugin-replies/ReplyBox.js @@ -11,7 +11,7 @@ const ReplyBox = (props) =>
From e805573bd41c23aa53ebed20812fbdf5cf679ecf Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 2 Nov 2016 15:45:52 -0700 Subject: [PATCH 06/15] Adding build script to package.json --- client/coral-embed-stream/webpack.config.js | 8 ++++---- package.json | 1 + routes/api/stream/index.js | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/client/coral-embed-stream/webpack.config.js b/client/coral-embed-stream/webpack.config.js index 10076a159..2db94e6af 100644 --- a/client/coral-embed-stream/webpack.config.js +++ b/client/coral-embed-stream/webpack.config.js @@ -8,7 +8,7 @@ module.exports = { devtool: 'source-map', entry: [ 'babel-polyfill', - './src/app' + path.join(__dirname, 'src', 'app') ], output: { path: path.join(__dirname, '..', '..','dist', 'coral-embed-stream'), @@ -23,13 +23,13 @@ module.exports = { }, plugins: [ new Copy([{ - from: './index.html' + from: path.join(__dirname, 'index.html') }, { - from: './style/default.css' + from: path.join(__dirname, 'style', 'default.css') }, { - from: './public/', + from: path.join(__dirname, 'public'), to: './' }, { diff --git a/package.json b/package.json index 632135005..a93714339 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "lint": "eslint .", "start": "./bin/www", + "build": "webpack --config ./client/coral-embed-stream/webpack.config.js", "embed-start": "node client/coral-embed-stream/dev-server.js" }, "repository": { diff --git a/routes/api/stream/index.js b/routes/api/stream/index.js index f1b1536d2..feb3faf9d 100644 --- a/routes/api/stream/index.js +++ b/routes/api/stream/index.js @@ -3,7 +3,7 @@ const express = require('express'); const router = express.Router(); router.get('/', (req, res) => { - console.log('asset_id, should be assetTest', req.query.asset_id) + console.log('Stream endpoint has been hit with asset_id ', req.query.asset_id) res.setHeader('Content-Type', 'application/json'); res.send(JSON.stringify([ { From 83505417b06c8a5c2c1729f5b48655f4a0cf8349 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 2 Nov 2016 16:00:43 -0700 Subject: [PATCH 07/15] Adding sample article and removing unused log statement --- .../coral-embed-stream/public/samplearticle.html | 16 ++++++++++++++++ client/coral-embed-stream/src/CommentStream.js | 1 - 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 client/coral-embed-stream/public/samplearticle.html diff --git a/client/coral-embed-stream/public/samplearticle.html b/client/coral-embed-stream/public/samplearticle.html new file mode 100644 index 000000000..493fc29fa --- /dev/null +++ b/client/coral-embed-stream/public/samplearticle.html @@ -0,0 +1,16 @@ + + + + +
+

Lorem ipsum

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut lobortis sollicitudin eros a ornare. Curabitur dignissim vestibulum massa non rhoncus. Cras laoreet ante vel nunc hendrerit, ac imperdiet neque egestas. Suspendisse aliquet iaculis fermentum. Pellentesque interdum nec elit sed tincidunt. Donec volutpat, tellus posuere laoreet consequat, mi lacus laoreet massa, sed vehicula mauris velit non lectus. Integer non enim nec neque congue faucibus porttitor sit amet dui.

+

Nunc pharetra orci id diam feugiat, vitae rutrum magna efficitur. Morbi porttitor blandit lorem, et facilisis tellus luctus at. Morbi tincidunt eget nisl id placerat. Nullam consectetur quam vel mauris lacinia, non consectetur est faucibus. Duis cursus auctor nulla nec sagittis. Aenean sem erat, ultrices a hendrerit consectetur, accumsan non lorem. Integer ac neque sed magna sodales vulputate at quis neque. Praesent eget ornare lacus. Donec ultricies, dolor eget commodo faucibus, arcu velit ullamcorper tellus, in cursus tellus elit sed urna. Suspendisse in consequat magna. Duis vel ullamcorper tortor, vel cursus libero. Proin et nisi luctus ligula faucibus luctus. Morbi pulvinar, justo ac feugiat elementum, libero tellus congue justo, pharetra ultrices felis felis id leo. Integer mattis quam tempus libero porta, ac pretium ligula elementum.

+
+ + +
+ + diff --git a/client/coral-embed-stream/src/CommentStream.js b/client/coral-embed-stream/src/CommentStream.js index dad8fbbf9..da5e25ff4 100644 --- a/client/coral-embed-stream/src/CommentStream.js +++ b/client/coral-embed-stream/src/CommentStream.js @@ -97,7 +97,6 @@ class CommentStream extends Component { const rootItemId = 'assetTest' const rootItem = this.props.items[rootItemId] - console.log(this.props.items); return
{ rootItem ? From f50528e50a9c38880dda9ab8e9aaeed13a4bc45f Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 3 Nov 2016 10:07:01 -0700 Subject: [PATCH 08/15] Updating posting to support new framework --- client/coral-framework/store/actions/items.js | 3 +-- client/coral-plugin-commentbox/CommentBox.js | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/client/coral-framework/store/actions/items.js b/client/coral-framework/store/actions/items.js index 82bcca52f..7c5c908f9 100644 --- a/client/coral-framework/store/actions/items.js +++ b/client/coral-framework/store/actions/items.js @@ -183,7 +183,7 @@ export function postItem (data, type, id) { method: 'POST', body: JSON.stringify(item) } - return fetch('/v1/item', options) + return fetch('api/v1/' + type, options) .then( response => { return response.ok ? response.json() @@ -191,7 +191,6 @@ export function postItem (data, type, id) { } ) .then((json) => { - // Patch until ID is returned from backend dispatch(addItem(json)) return json.id }) diff --git a/client/coral-plugin-commentbox/CommentBox.js b/client/coral-plugin-commentbox/CommentBox.js index f20ced54c..6d56ecfde 100644 --- a/client/coral-plugin-commentbox/CommentBox.js +++ b/client/coral-plugin-commentbox/CommentBox.js @@ -25,10 +25,10 @@ class CommentBox extends Component { let related if (reply) { comment.parent_id = item_id - related = 'child' + related = 'children' } else { comment.asset_id = item_id - related = 'comment' + related = 'comments' } updateItem(item_id, 'showReply', false) postItem(comment, 'comment') From 46e6508abe746ceddba507d130e0c1ae02fe7a1d Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 3 Nov 2016 10:52:16 -0700 Subject: [PATCH 09/15] Adding action routes And fixing a few small issues with item posting. --- client/coral-framework/store/actions/items.js | 31 ++++++++++--------- client/coral-plugin-commentbox/CommentBox.js | 2 +- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/client/coral-framework/store/actions/items.js b/client/coral-framework/store/actions/items.js index 7c5c908f9..019b1bfbe 100644 --- a/client/coral-framework/store/actions/items.js +++ b/client/coral-framework/store/actions/items.js @@ -115,9 +115,11 @@ export function getStream (assetId) { comments: rootComments })) - Object.keys(childComments).reduce((prev, key) => { - dispatch(updateItem(key, 'children', childComments[key])) - },{}) + const keys = Object.keys(childComments) + for (var i=0; i < keys.length; i++ ) { + dispatch(updateItem(keys[i], 'children', childComments[keys[i]])) + } + return (json) }) } @@ -169,13 +171,8 @@ export function getItemsArray (ids) { * The newly put item to the item store */ -export function postItem (data, type, id) { +export function postItem (item, type, id) { return (dispatch) => { - let item = { - type, - data, - version: 1 - } if (id) { item.id = id } @@ -214,13 +211,19 @@ export function postItem (data, type, id) { * */ -export function postAction (item, action, user) { +export function postAction (id, type, user_id) { return (dispatch) => { - let options = { - method: 'POST' + const action = { + type, + user_id } - dispatch(appendItemArray(item, action, user)) - return fetch('/v1/action/' + action + '/user/' + user + '/on/item/' + item, options) + const options = { + method: 'POST', + body: JSON.stringify(action) + } + + dispatch(appendItemArray(id, type, user_id)) + return fetch('api/v1/comments/' + id + '/actions', options) .then( response => { return response.ok ? response.text() diff --git a/client/coral-plugin-commentbox/CommentBox.js b/client/coral-plugin-commentbox/CommentBox.js index 6d56ecfde..c893be075 100644 --- a/client/coral-plugin-commentbox/CommentBox.js +++ b/client/coral-plugin-commentbox/CommentBox.js @@ -31,7 +31,7 @@ class CommentBox extends Component { related = 'comments' } updateItem(item_id, 'showReply', false) - postItem(comment, 'comment') + postItem(comment, 'comments') .then((id) => { appendItemArray(item_id, related, id) addNotification('success', 'Your comment has been posted.') From 5f02d1e9487c68155ef5723ef3662236a9fc8138 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 3 Nov 2016 10:52:29 -0700 Subject: [PATCH 10/15] Simplifying mock routes and adding error handling. --- routes/api/stream/index.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/routes/api/stream/index.js b/routes/api/stream/index.js index feb3faf9d..155450d42 100644 --- a/routes/api/stream/index.js +++ b/routes/api/stream/index.js @@ -2,10 +2,9 @@ const express = require('express'); const router = express.Router(); -router.get('/', (req, res) => { - console.log('Stream endpoint has been hit with asset_id ', req.query.asset_id) - res.setHeader('Content-Type', 'application/json'); - res.send(JSON.stringify([ +router.get('/', (req, res, next) => { + console.log('Stream endpoint has been hit with asset_id ', req.query.asset_id); + res.json([ { 'id': 'abc', 'type': 'comment', @@ -28,7 +27,7 @@ router.get('/', (req, res) => { 'created_at': new Date().getTime() - 400000, 'asset_id': 'assetTest' } - ])); + ]).catch(next); }); module.exports = router; From df77ee963ad91bfb0b10e2e256caf2db4762997e Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 3 Nov 2016 17:06:15 -0700 Subject: [PATCH 11/15] Adding find functions and tests to comment model. --- models/comment.js | 27 +++++++++++++--------- package.json | 3 ++- routes/api/stream/index.js | 3 ++- tests/index.js | 4 +++- tests/models/comment.js | 46 ++++++++++++++++++++++++++++++++++++++ tests/utils/mongoose.js | 37 ++++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 tests/models/comment.js create mode 100644 tests/utils/mongoose.js diff --git a/models/comment.js b/models/comment.js index 107708a3b..a80e0dae7 100644 --- a/models/comment.js +++ b/models/comment.js @@ -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: 1 }, asset_id: String, author_id: String, @@ -23,22 +21,31 @@ const CommentSchema = new Schema({ default: '' }, parent_id: String -},{ - _id: false, - timestamps: { - createdAt: 'created_at', - updatedAt: 'updated_at' - } +// },{ +// _id: false, +// timestamps: { +// createdAt: 'created_at', +// updatedAt: 'updated_at' +// } }); /** * 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; diff --git a/package.json b/package.json index 096863202..c25e54eb5 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,8 @@ "dependencies": { "debug": "^2.2.0", "express": "^4.14.0", - "mongoose": "^4.6.5" + "mongoose": "^4.6.5", + "uuid": "^2.0.3" }, "devDependencies": { "babel-core": "6.14.0", diff --git a/routes/api/stream/index.js b/routes/api/stream/index.js index 155450d42..b8a4c76ba 100644 --- a/routes/api/stream/index.js +++ b/routes/api/stream/index.js @@ -1,8 +1,9 @@ const express = require('express'); - +const Setting = require('../../../models/comment'); const router = express.Router(); router.get('/', (req, res, next) => { + console.log('Stream endpoint has been hit with asset_id ', req.query.asset_id); res.json([ { diff --git a/tests/index.js b/tests/index.js index 0a212b7a4..51ccc54ee 100644 --- a/tests/index.js +++ b/tests/index.js @@ -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); }); diff --git a/tests/models/comment.js b/tests/models/comment.js new file mode 100644 index 000000000..2eaa22a01 --- /dev/null +++ b/tests/models/comment.js @@ -0,0 +1,46 @@ +/* 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 1', + asset_id: '123' + },{ + body: 'comment 2', + asset_id: '123' + },{ + body: 'comment 3', + 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 1'); + }); + }); + }); + + describe('#findByAssetId()', () => { + it('should find an array of comments by asset id', () => { + return Comment.findByAssetId('123').then((result) => { + expect(result).to.have.length(2); + expect(result[0]).to.have.property('body') + .and.to.equal('comment 1'); + expect(result[1]).to.have.property('body') + .and.to.equal('comment 2'); + }); + }); + }); + + // }); +}); diff --git a/tests/utils/mongoose.js b/tests/utils/mongoose.js new file mode 100644 index 000000000..002066001 --- /dev/null +++ b/tests/utils/mongoose.js @@ -0,0 +1,37 @@ +// Modified from https://github.com/elliotf/mocha-mongoose + +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(); +}); From 084ee98ce26f867c5820c3afabd3062d68194b1f Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 3 Nov 2016 17:13:47 -0700 Subject: [PATCH 12/15] Adding .eslintrc to tests. --- tests/.eslintrc | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/.eslintrc diff --git a/tests/.eslintrc b/tests/.eslintrc new file mode 100644 index 000000000..0f4ef75d7 --- /dev/null +++ b/tests/.eslintrc @@ -0,0 +1,10 @@ +{ + "env": { + "es6": true, + "node": true + }, + "extends": "eslint:recommended", + "rules": { + no-undef: [1] + } +} From 8e9ebfb1a9a8863ed3c7fd564db25a7eb1b1d5e3 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 3 Nov 2016 17:45:37 -0700 Subject: [PATCH 13/15] Adding find functions and tests to user and action models. --- models/action.js | 24 ++++++++++++++++-------- models/user.js | 23 ++++++++++++++++------- package.json | 3 ++- tests/models/action.js | 40 ++++++++++++++++++++++++++++++++++++++++ tests/models/comment.js | 4 ++-- tests/models/user.js | 40 ++++++++++++++++++++++++++++++++++++++++ tests/utils/mongoose.js | 3 --- 7 files changed, 116 insertions(+), 21 deletions(-) create mode 100644 tests/models/action.js create mode 100644 tests/models/user.js diff --git a/models/action.js b/models/action.js index 581108a71..cb1d075b1 100644 --- a/models/action.js +++ b/models/action.js @@ -1,5 +1,3 @@ -'use strict'; - const mongoose = require('../mongoose'); const uuid = require('uuid'); const Schema = mongoose.Schema; @@ -14,12 +12,12 @@ const ActionSchema = new Schema({ item_type: String, item_id: String, user_id: String -},{ - _id: false, - timestamps: { - createdAt: 'created_at', - updatedAt: 'updated_at' - } +// },{ +// _id: false, +// timestamps: { +// createdAt: 'created_at', +// updatedAt: 'updated_at' +// } }); /** @@ -30,6 +28,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; diff --git a/models/user.js b/models/user.js index d6b174075..6aba99f7b 100644 --- a/models/user.js +++ b/models/user.js @@ -1,4 +1,3 @@ -'use strict'; const mongoose = require('../mongoose'); const uuid = require('uuid'); @@ -12,12 +11,12 @@ const UserProfileSchema = new Schema({ }, display_name: String, auth_user_id: String -},{ - _id: false, - timestamps: { - createdAt: 'created_at', - updatedAt: 'updated_at' - } +// },{ +// _id: false, +// timestamps: { +// createdAt: 'created_at', +// updatedAt: 'updated_at' +// } }); /** @@ -28,6 +27,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 diff --git a/package.json b/package.json index c25e54eb5..b490ca856 100644 --- a/package.json +++ b/package.json @@ -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": { diff --git a/tests/models/action.js b/tests/models/action.js new file mode 100644 index 000000000..8736edcab --- /dev/null +++ b/tests/models/action.js @@ -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); + }); + }); + }); +}); diff --git a/tests/models/comment.js b/tests/models/comment.js index 2eaa22a01..0f98db6ac 100644 --- a/tests/models/comment.js +++ b/tests/models/comment.js @@ -5,7 +5,7 @@ const Comment = require('../../models/comment'); const expect = require('chai').expect; describe('Comment: models', () => { - var mockComments + var mockComments; beforeEach(() => { return Comment.create([{ body: 'comment 1', @@ -17,7 +17,7 @@ describe('Comment: models', () => { body: 'comment 3', asset_id: '456' }]).then((comments) => { - mockComments = comments + mockComments = comments; }); }); diff --git a/tests/models/user.js b/tests/models/user.js new file mode 100644 index 000000000..e1063e21c --- /dev/null +++ b/tests/models/user.js @@ -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); + }); + }); + }); + + // }); +}); diff --git a/tests/utils/mongoose.js b/tests/utils/mongoose.js index 002066001..7661eeb32 100644 --- a/tests/utils/mongoose.js +++ b/tests/utils/mongoose.js @@ -8,8 +8,6 @@ var mongoose = require('mongoose'); process.env.NODE_ENV = 'test'; beforeEach(function (done) { - - function clearDB() { for (var i in mongoose.connection.collections) { mongoose.connection.collections[i].remove(function() {}); @@ -30,7 +28,6 @@ beforeEach(function (done) { } }); - after(function (done) { mongoose.disconnect(); return done(); From 70630918cc47934ed477131b4183434a5e92cfe1 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 3 Nov 2016 17:52:33 -0700 Subject: [PATCH 14/15] Adding stream endpoint. --- routes/api/stream/index.js | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/routes/api/stream/index.js b/routes/api/stream/index.js index b8a4c76ba..942db826c 100644 --- a/routes/api/stream/index.js +++ b/routes/api/stream/index.js @@ -1,34 +1,14 @@ const express = require('express'); -const Setting = require('../../../models/comment'); +const Comment = require('../../../models/comment'); +const User = require('../../../models/user'); +const Action = require('../../../models/action'); const router = express.Router(); router.get('/', (req, res, next) => { - - 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' - } - ]).catch(next); + const comments = Comment.findByAssetId(req.query.asset_id) || []; + const users = User.findByIdArray(comments.map((comment) => comment.author_id)); + const actions = Action.findByItemIdArray(comments.map((comment) => comment.id)); + res.json(comments.concat(users).concat(actions)).catch(next); }); module.exports = router; From 6c25ca81d4c03ef196777462c9a536b0d41ab781 Mon Sep 17 00:00:00 2001 From: David Jay Date: Fri, 4 Nov 2016 00:02:34 -0700 Subject: [PATCH 15/15] Adding stream endpoint tests --- tests/routes/api/stream/index.js | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 tests/routes/api/stream/index.js diff --git a/tests/routes/api/stream/index.js b/tests/routes/api/stream/index.js new file mode 100644 index 000000000..4449cce61 --- /dev/null +++ b/tests/routes/api/stream/index.js @@ -0,0 +1,62 @@ +require('../../../utils/mongoose'); +const Action = require('../../../../models/action'); +const User = require('../../../../models/user'); +const Comment = require('../../../../models/comment'); +const expect = require('chai').expect; +const streamRoutes = require('../../../../routes/api/stream'); + +describe('api/stream: routes', () => { + const comments = [{ + id: 'abc', + body: 'comment 1', + asset_id: 'asset', + author_id: '123' + },{ + id: 'def', + body: 'comment 2', + asset_id: 'asset', + author_id: '456' + },{ + id: 'hij', + body: 'comment 3', + 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', () => { + console.log(streamRoutes('./')); + streamRoutes('./')({ + query: { + asset_id: 'asset' + } + }, { + json: (data) => { + console.log(data); + expect(data).to.equal(1); + } + }) + }) +})