mirror of
https://github.com/wassname/talk.git
synced 2026-07-10 17:08:48 +08:00
Merged master into password-reset
This commit is contained in:
@@ -14,9 +14,10 @@ import AuthorName from '../../coral-plugin-author-name/AuthorName';
|
||||
import {ReplyBox, ReplyButton} from '../../coral-plugin-replies';
|
||||
import Pym from 'pym.js';
|
||||
import FlagButton from '../../coral-plugin-flags/FlagButton';
|
||||
import LikeButton from '../../coral-plugin-likes/LikeButton';
|
||||
import PermalinkButton from '../../coral-plugin-permalinks/PermalinkButton';
|
||||
|
||||
const {addItem, updateItem, postItem, getStream, postAction, appendItemArray} = itemActions;
|
||||
const {addItem, updateItem, postItem, getStream, postAction, deleteAction, appendItemArray} = itemActions;
|
||||
const {addNotification, clearNotification} = notificationActions;
|
||||
const {setLoggedInUser} = authActions;
|
||||
|
||||
@@ -55,6 +56,9 @@ const mapDispatchToProps = (dispatch) => {
|
||||
postAction: (item, action, user, itemType) => {
|
||||
return dispatch(postAction(item, action, user, itemType));
|
||||
},
|
||||
deleteAction: (item, action, user, itemType) => {
|
||||
return dispatch(deleteAction(item, action, user, itemType));
|
||||
},
|
||||
appendItemArray: (item, property, value, addToFront, itemType) => {
|
||||
return dispatch(appendItemArray(item, property, value, addToFront, itemType));
|
||||
}
|
||||
@@ -120,21 +124,33 @@ class CommentStream extends Component {
|
||||
<AuthorName name={comment.username}/>
|
||||
<PubDate created_at={comment.created_at}/>
|
||||
<Content body={comment.body}/>
|
||||
<div className="commentActions">
|
||||
<div className="commentActionsLeft">
|
||||
<ReplyButton
|
||||
updateItem={this.props.updateItem}
|
||||
id={commentId}/>
|
||||
<LikeButton
|
||||
addNotification={this.props.addNotification}
|
||||
id={commentId}
|
||||
like={this.props.items.actions[comment.like]}
|
||||
postAction={this.props.postAction}
|
||||
deleteAction={this.props.deleteAction}
|
||||
addItem={this.props.addItem}
|
||||
updateItem={this.props.updateItem}
|
||||
currentUser={this.props.auth.user}/>
|
||||
</div>
|
||||
<div className="commentActionsRight">
|
||||
<FlagButton
|
||||
addNotification={this.props.addNotification}
|
||||
id={commentId}
|
||||
flag={this.props.items.actions[comment.flag]}
|
||||
postAction={this.props.postAction}
|
||||
deleteAction={this.props.deleteAction}
|
||||
addItem={this.props.addItem}
|
||||
updateItem={this.props.updateItem}
|
||||
currentUser={this.props.auth.user}/>
|
||||
<ReplyButton
|
||||
updateItem={this.props.updateItem}
|
||||
id={commentId}/>
|
||||
<PermalinkButton
|
||||
comment_id={commentId}
|
||||
asset_id={comment.asset_id}/>
|
||||
<PermalinkButton
|
||||
comment_id={commentId}
|
||||
asset_id={comment.asset_id}/>
|
||||
</div>
|
||||
<ReplyBox
|
||||
addNotification={this.props.addNotification}
|
||||
@@ -154,23 +170,35 @@ class CommentStream extends Component {
|
||||
<AuthorName name={reply.username}/>
|
||||
<PubDate created_at={reply.created_at}/>
|
||||
<Content body={reply.body}/>
|
||||
<div className="replyActions">
|
||||
<FlagButton
|
||||
addNotification={this.props.addNotification}
|
||||
id={replyId}
|
||||
flag={this.props.items.actions[reply.flag]}
|
||||
postAction={this.props.postAction}
|
||||
addItem={this.props.addItem}
|
||||
updateItem={this.props.updateItem}
|
||||
currentUser={this.props.auth.user}/>
|
||||
<ReplyButton
|
||||
updateItem={this.props.updateItem}
|
||||
parent_id={reply.parent_id}/>
|
||||
<PermalinkButton
|
||||
comment_id={reply.comment_id}
|
||||
asset_id={reply.comment_id}
|
||||
/>
|
||||
</div>
|
||||
<div className="replyActionsLeft">
|
||||
<ReplyButton
|
||||
updateItem={this.props.updateItem}
|
||||
id={replyId}/>
|
||||
<LikeButton
|
||||
addNotification={this.props.addNotification}
|
||||
id={replyId}
|
||||
like={this.props.items.actions[reply.like]}
|
||||
postAction={this.props.postAction}
|
||||
deleteAction={this.props.deleteAction}
|
||||
addItem={this.props.addItem}
|
||||
updateItem={this.props.updateItem}
|
||||
currentUser={this.props.auth.user}/>
|
||||
</div>
|
||||
<div className="replyActionsRight">
|
||||
<FlagButton
|
||||
addNotification={this.props.addNotification}
|
||||
id={replyId}
|
||||
flag={this.props.items.actions[reply.flag]}
|
||||
postAction={this.props.postAction}
|
||||
deleteAction={this.props.deleteAction}
|
||||
addItem={this.props.addItem}
|
||||
updateItem={this.props.updateItem}
|
||||
currentUser={this.props.auth.user}/>
|
||||
<PermalinkButton
|
||||
comment_id={reply.comment_id}
|
||||
asset_id={reply.comment_id}
|
||||
/>
|
||||
</div>
|
||||
</div>;
|
||||
})
|
||||
}
|
||||
|
||||
@@ -105,16 +105,33 @@ hr {
|
||||
|
||||
/* Comment Action Styles */
|
||||
|
||||
.commentActions, .replyActions {
|
||||
.commentActionsRight, .replyActionsRight {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
width: 50%;
|
||||
}
|
||||
.commentActionsLeft, .replyActionsLeft {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.commentActions .material-icons, .replyActions .material-icons {
|
||||
.commentActionsLeft .material-icons,.commentActionsRight .material-icons,
|
||||
.replyActionsLeft .material-icons, .replyActionsRight .material-icons {
|
||||
font-size: 12px;
|
||||
margin-left: 3px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.likedButton {
|
||||
color: rgb(0,134,227);
|
||||
}
|
||||
|
||||
.flaggedIcon {
|
||||
color: #F00;
|
||||
}
|
||||
|
||||
/* Comment count styles */
|
||||
.coral-plugin-comment-count-text {
|
||||
margin-bottom: 15px;
|
||||
|
||||
@@ -8,6 +8,23 @@ export const ADD_ITEM = 'ADD_ITEM';
|
||||
export const UPDATE_ITEM = 'UPDATE_ITEM';
|
||||
export const APPEND_ITEM_ARRAY = 'APPEND_ITEM_ARRAY';
|
||||
|
||||
const getInit = (method, body) => {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
};
|
||||
|
||||
const init = {method, headers};
|
||||
if (method.toLowerCase() !== 'get') {
|
||||
init.body = JSON.stringify(body);
|
||||
}
|
||||
|
||||
return init;
|
||||
};
|
||||
|
||||
const responseHandler = response => {
|
||||
return response.ok ? response.json() : Promise.reject(`${response.status} ${response.statusText}`);
|
||||
};
|
||||
/**
|
||||
* Action creators
|
||||
*/
|
||||
@@ -79,12 +96,8 @@ export const appendItemArray = (id, property, value, add_to_front, item_type) =>
|
||||
*/
|
||||
export function getStream (assetId) {
|
||||
return (dispatch) => {
|
||||
return fetch(`/api/v1/stream?asset_id=${assetId}`)
|
||||
.then(
|
||||
response => {
|
||||
return response.ok ? response.json() : Promise.reject(`${response.status} ${response.statusText}`);
|
||||
}
|
||||
)
|
||||
return fetch(`/api/v1/stream?asset_id=${assetId}`, getInit('GET'))
|
||||
.then(responseHandler)
|
||||
.then((json) => {
|
||||
|
||||
/* Add items to the store */
|
||||
@@ -148,13 +161,8 @@ export function getStream (assetId) {
|
||||
|
||||
export function getItemsArray (ids) {
|
||||
return (dispatch) => {
|
||||
return fetch(`/v1/item/${ids}`)
|
||||
.then(
|
||||
response => {
|
||||
return response.ok ? response.json()
|
||||
: Promise.reject(`${response.status } ${ response.statusText}`);
|
||||
}
|
||||
)
|
||||
return fetch(`/v1/item/${ids}`, getInit('GET'))
|
||||
.then(responseHandler)
|
||||
.then((json) => {
|
||||
for (let i = 0; i < json.items.length; i++) {
|
||||
dispatch(addItem(json.items[i]));
|
||||
@@ -183,20 +191,8 @@ export function postItem (item, type, id) {
|
||||
if (id) {
|
||||
item.id = id;
|
||||
}
|
||||
let options = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(item),
|
||||
headers: {
|
||||
'Content-Type':'application/json'
|
||||
}
|
||||
};
|
||||
return fetch(`/api/v1/${type}`, options)
|
||||
.then(
|
||||
response => {
|
||||
return response.ok ? response.json()
|
||||
: Promise.reject(`${response.status} ${response.statusText}`);
|
||||
}
|
||||
)
|
||||
return fetch(`/api/v1/${type}`, getInit('POST', item))
|
||||
.then(responseHandler)
|
||||
.then((json) => {
|
||||
dispatch(addItem({...item, id:json.id}, type));
|
||||
return json.id;
|
||||
@@ -227,23 +223,35 @@ export function postAction (item_id, action_type, user_id, item_type) {
|
||||
action_type,
|
||||
user_id
|
||||
};
|
||||
const options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type':'application/json'
|
||||
},
|
||||
body: JSON.stringify(action)
|
||||
};
|
||||
|
||||
return fetch(`/api/v1/${item_type}/${item_id}/actions`, options)
|
||||
.then(
|
||||
response => {
|
||||
return response.ok ? response.json()
|
||||
: Promise.reject(`${response.status} ${response.statusText}`);
|
||||
}
|
||||
)
|
||||
.then((json)=>{
|
||||
return json;
|
||||
});
|
||||
return fetch(`/api/v1/${item_type}/${item_id}/actions`, getInit('POST', action))
|
||||
.then(responseHandler);
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* DeleteAction
|
||||
* Deletes an action to an item
|
||||
*
|
||||
* @params
|
||||
* 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
|
||||
*
|
||||
* @returns
|
||||
* A promise resolving to null or an error
|
||||
*
|
||||
*/
|
||||
|
||||
export function deleteAction (item_id, action_type, user_id, item_type) {
|
||||
return () => {
|
||||
const action = {
|
||||
action_type,
|
||||
user_id
|
||||
};
|
||||
|
||||
return fetch(`/api/v1/${item_type}/${item_id}/actions`, getInit('DELETE', action))
|
||||
.then(responseHandler);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ const name = 'coral-plugin-comment-count';
|
||||
|
||||
const CommentCount = ({items, id}) => {
|
||||
let count = 0;
|
||||
if (items[id]) {
|
||||
count += items[id].comments.length;
|
||||
if (items.assets[id]) {
|
||||
count += items.assets[id].comments.length;
|
||||
}
|
||||
const itemKeys = Object.keys(items);
|
||||
const itemKeys = Object.keys(items.comments);
|
||||
for (let i = 0; i < itemKeys.length; i++) {
|
||||
const item = items[itemKeys[i]];
|
||||
const item = items.comments[itemKeys[i]];
|
||||
if (item.children) {
|
||||
count += item.children.length;
|
||||
}
|
||||
|
||||
@@ -4,27 +4,35 @@ import translations from './translations.json';
|
||||
|
||||
const name = 'coral-plugin-flags';
|
||||
|
||||
const FlagButton = ({flag, id, postAction, addItem, updateItem, addNotification}) => {
|
||||
const FlagButton = ({flag, id, postAction, deleteAction, addItem, updateItem, addNotification}) => {
|
||||
const flagged = flag && flag.current_user;
|
||||
const onFlagClick = () => {
|
||||
postAction(id, 'flag', '123', 'comments')
|
||||
.then((action) => {
|
||||
addItem({...action, current_user:true}, 'actions');
|
||||
updateItem(action.item_id, action.action_type, action.id, 'comments');
|
||||
});
|
||||
addNotification('success', lang.t('flag-notif'));
|
||||
if (!flagged) {
|
||||
postAction(id, 'flag', '123', 'comments')
|
||||
.then((action) => {
|
||||
addItem({...action, current_user:true}, 'actions');
|
||||
updateItem(action.item_id, action.action_type, action.id, 'comments');
|
||||
});
|
||||
addNotification('success', lang.t('flag-notif'));
|
||||
} else {
|
||||
deleteAction(id, 'flag', '123', 'comments')
|
||||
.then(() => {
|
||||
updateItem(id, 'flag', '', 'comments');
|
||||
});
|
||||
addNotification('success', lang.t('flag-notif-remove'));
|
||||
}
|
||||
};
|
||||
|
||||
return <div className={`${name }-container`}>
|
||||
<button onClick={onFlagClick} className={`${name }-button`}>
|
||||
<i className={`${name }-icon material-icons`}
|
||||
style={flagged ? styles.flaggedIcon : styles.unflaggedIcon}
|
||||
aria-hidden={true}>flag</i>
|
||||
return <div className={`${name}-container`}>
|
||||
<button onClick={onFlagClick} className={`${name}-button`}>
|
||||
{
|
||||
flagged
|
||||
? <span className={`${name}-button-text`}>{lang.t('flag')}</span>
|
||||
: <span className={`${name}-button-text`}>{lang.t('flagged')}</span>
|
||||
? <span className={`${name}-button-text`}>{lang.t('flagged')}</span>
|
||||
: <span className={`${name}-button-text`}>{lang.t('flag')}</span>
|
||||
}
|
||||
<i className={`${name}-icon material-icons ${flagged && 'flaggedIcon'}`}
|
||||
style={flagged && styles.flaggedIcon}
|
||||
aria-hidden={true}>flag</i>
|
||||
</button>
|
||||
</div>;
|
||||
};
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
"en": {
|
||||
"flag": "Flag",
|
||||
"flagged": "Flagged",
|
||||
"flag-notif": "Thank you for reporting this comment. Our moderation team has been notified and will review it shortly."
|
||||
"flag-notif": "Thank you for reporting this comment. Our moderation team has been notified and will review it shortly.",
|
||||
"flag-notif-remove": "Your flag has been removed."
|
||||
},
|
||||
"es": {
|
||||
"flag": "Marcar",
|
||||
"flagged": "Marcado",
|
||||
"flag-notif": "Gracias por marcar este comentario. Nuestro equipo de moderación ha sido notificado y muy pronto lo va a revisar."
|
||||
"flag-notif": "Gracias por marcar este comentario. Nuestro equipo de moderación ha sido notificado y muy pronto lo va a revisar.",
|
||||
"flag-notif-remove": "¡traduceme!"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import {I18n} from '../coral-framework';
|
||||
import translations from './translations.json';
|
||||
|
||||
const name = 'coral-plugin-flags';
|
||||
|
||||
const LikeButton = ({like, id, postAction, deleteAction, addItem, updateItem}) => {
|
||||
const liked = like && like.current_user;
|
||||
const onLikeClick = () => {
|
||||
if (!liked) {
|
||||
postAction(id, 'like', '123', 'comments')
|
||||
.then((action) => {
|
||||
addItem({id: action.id, current_user:true, count: like ? like.count + 1 : 1}, 'actions');
|
||||
updateItem(action.item_id, action.action_type, action.id, 'comments');
|
||||
});
|
||||
} else {
|
||||
deleteAction(id, 'like', '123', 'comments')
|
||||
.then(() => {
|
||||
updateItem(like.id, 'count', like.count - 1, 'actions');
|
||||
updateItem(like.id, 'current_user', false, 'actions');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return <div className={`${name}-container`}>
|
||||
<button onClick={onLikeClick} className={`${name}-button ${liked && 'likedButton'}`}>
|
||||
{
|
||||
liked
|
||||
? <span className={`${name}-button-text`}>{lang.t('liked')}</span>
|
||||
: <span className={`${name}-button-text`}>{lang.t('like')}</span>
|
||||
}
|
||||
<i className={`${name}-icon material-icons`}
|
||||
aria-hidden={true}>thumb_up</i>
|
||||
<span className={`${name}-like-count`}>{like && like.count > 0 && like.count}</span>
|
||||
</button>
|
||||
</div>;
|
||||
};
|
||||
|
||||
export default LikeButton;
|
||||
|
||||
const lang = new I18n(translations);
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"en": {
|
||||
"like": "Like",
|
||||
"liked": "Liked"
|
||||
},
|
||||
"es": {
|
||||
"like": "Me Gusta",
|
||||
"liked": "Me Gustó"
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,9 @@ const name = 'coral-plugin-replies';
|
||||
const ReplyButton = (props) => <button
|
||||
className={`${name}-reply-button`}
|
||||
onClick={() => props.updateItem(props.id || props.parent_id, 'showReply', true, 'comments')}>
|
||||
{lang.t('reply')}
|
||||
<i className={`${name}-icon material-icons`}
|
||||
aria-hidden={true}>reply</i>
|
||||
{lang.t('reply')}
|
||||
</button>;
|
||||
|
||||
export default ReplyButton;
|
||||
|
||||
+11
-1
@@ -62,11 +62,21 @@ AssetSchema.statics.findByUrl = function(url) {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds a asset by its url.
|
||||
* @param {String} url identifier of the asset (uuid).
|
||||
*/
|
||||
AssetSchema.statics.findOrCreateByUrl = function(url) {
|
||||
|
||||
return Asset.findOne({url})
|
||||
.then((asset) => asset ? asset
|
||||
: Asset.upsert({url}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Upserts an asset.
|
||||
*/
|
||||
AssetSchema.statics.upsert = function(data) {
|
||||
|
||||
// If an id is not sent, create one.
|
||||
if (typeof data.id === 'undefined') {
|
||||
data.id = uuid.v4();
|
||||
|
||||
+18
-3
@@ -104,14 +104,14 @@ CommentSchema.statics.findByStatusByActionType = function(status, action_type) {
|
||||
return Action
|
||||
.findCommentsIdByActionType(action_type, 'comment')
|
||||
.then((actions) => {
|
||||
|
||||
|
||||
return Comment.find({
|
||||
'status': status,
|
||||
'status': status,
|
||||
'id': {
|
||||
'$in': actions.map(a => {
|
||||
return a.item_id;
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -188,6 +188,21 @@ CommentSchema.statics.removeById = function(id) {
|
||||
return Comment.remove({'id': id});
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove an action from the comment.
|
||||
* @param {String} id identifier of the comment (uuid)
|
||||
* @param {String} action_type the type of the action to be removed
|
||||
* @param {String} user_id the id of the user performing the action
|
||||
*/
|
||||
CommentSchema.statics.removeAction = function(item_id, user_id, action_type) {
|
||||
return Action.remove({
|
||||
action_type,
|
||||
item_type: 'comment',
|
||||
item_id,
|
||||
user_id
|
||||
});
|
||||
};
|
||||
|
||||
const Comment = mongoose.model('Comment', CommentSchema);
|
||||
|
||||
module.exports = Comment;
|
||||
|
||||
@@ -126,7 +126,19 @@ router.delete('/:comment_id', (req, res, next) => {
|
||||
Comment
|
||||
.removeById(req.params.comment_id)
|
||||
.then(() => {
|
||||
res.status(201).send('OK. Removed');
|
||||
res.status(201).send({});
|
||||
})
|
||||
.catch(error => {
|
||||
next(error);
|
||||
});
|
||||
});
|
||||
|
||||
router.delete('/:comment_id/actions', (req, res, next) => {
|
||||
console.log(req.params);
|
||||
Comment
|
||||
.removeAction(req.params.comment_id, req.body.user_id, req.body.action_type)
|
||||
.then(() => {
|
||||
res.status(201).send({});
|
||||
})
|
||||
.catch(error => {
|
||||
next(error);
|
||||
|
||||
@@ -119,6 +119,7 @@ describe('itemActions', () => {
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type':'application/json'
|
||||
},
|
||||
body: JSON.stringify(item.data)
|
||||
@@ -162,6 +163,24 @@ describe('itemActions', () => {
|
||||
expect(err).to.be.truthy;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteAction', () => {
|
||||
it ('should remove an action', () => {
|
||||
fetchMock.delete('*', {});
|
||||
return actions.deleteAction('abc', 'flag', '123', 'comments')(store.dispatch)
|
||||
.then(response => {
|
||||
expect(fetchMock.calls().matched[0][0]).to.equal('/api/v1/comments/abc/actions');
|
||||
expect(response).to.deep.equal({});
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle an error', () => {
|
||||
fetchMock.post('*', 404);
|
||||
return actions.postAction('abc', 'flag', '123')(store.dispatch)
|
||||
.catch((err) => {
|
||||
expect(err).to.be.truthy;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+97
-84
@@ -1,95 +1,108 @@
|
||||
/* eslint-env node, mocha */
|
||||
|
||||
require('../utils/mongoose');
|
||||
|
||||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
const server = require('../../app');
|
||||
const Asset = require('../../models/asset');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
// Setup chai.
|
||||
chai.should();
|
||||
chai.use(require('chai-http'));
|
||||
describe('Asset: model', () => {
|
||||
|
||||
let fixture = {
|
||||
'url': 'http://hhgg.com/total-perspective-vortex',
|
||||
'type': 'article',
|
||||
'headline': 'The Total Perspective Vortex',
|
||||
'summary': 'You are an insignificant dot on an insignificant dot.',
|
||||
'section': 'Everything',
|
||||
'authors': ['Ford Prefect']
|
||||
};
|
||||
beforeEach(() => {
|
||||
const defaults = {url:'http://test.com'};
|
||||
return Asset.update({id: '1'}, {$setOnInsert: defaults}, {upsert: true});
|
||||
});
|
||||
|
||||
describe('Asset: models', () => {
|
||||
|
||||
describe('/GET Asset', () => {
|
||||
describe('#get', () => {
|
||||
it('It should get an empty array when there are no assets.', (done) => {
|
||||
|
||||
chai.request(server)
|
||||
.get('/api/v1/asset')
|
||||
.end((err, res) => {
|
||||
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
res.should.have.status(200);
|
||||
res.body.should.be.a('array');
|
||||
res.body.length.should.be.eql(0);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
describe('#findById', ()=> {
|
||||
it('should find an asset by the id', () => {
|
||||
return Asset.findById(1)
|
||||
.then((asset) => {
|
||||
expect(asset).to.have.property('url')
|
||||
.and.to.equal('http://test.com');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// This test checks PUT and read
|
||||
describe('/PUT Asset', () => {
|
||||
describe('#put', () => {
|
||||
it('It should save an asset and load it again.', (done) => {
|
||||
|
||||
chai.request(server)
|
||||
.put('/api/v1/asset')
|
||||
.send(fixture)
|
||||
.end((err, res) => {
|
||||
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
res.should.have.status(200);
|
||||
res.body.should.be.a('object');
|
||||
|
||||
// Id should be generated by the model if absent.
|
||||
res.body.should.have.property('id');
|
||||
|
||||
// Save the asset id to compare with GET result.
|
||||
let assetId = res.body.id;
|
||||
|
||||
// Load the asset to make sure it's really there.
|
||||
chai.request(server)
|
||||
.get(`/api/v1/asset?url=${encodeURIComponent(fixture.url)}`)
|
||||
.end((err, res) => {
|
||||
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
res.should.have.status(200);
|
||||
res.body.should.be.an('array');
|
||||
|
||||
let asset = res.body[0];
|
||||
|
||||
expect(asset).to.have.property('id');
|
||||
|
||||
// Ensure the asset has the same id as above.
|
||||
// This tests the single url per Id concept.
|
||||
expect(assetId).to.equal(asset.id);
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#findByUrl', ()=> {
|
||||
it('should find an asset by a url', () => {
|
||||
return Asset.findByUrl('http://test.com')
|
||||
.then((asset) => {
|
||||
expect(asset).to.have.property('url')
|
||||
.and.to.equal('http://test.com');
|
||||
});
|
||||
});
|
||||
}); // End describe /PUT Asset
|
||||
|
||||
it('should return null when a url does not exist', () => {
|
||||
return Asset.findByUrl('http://new.test.com')
|
||||
.then((asset) => {
|
||||
expect(asset).to.be.null;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#findOrCreateByUrl', ()=> {
|
||||
it('should find an asset by a url', () => {
|
||||
return Asset.findOrCreateByUrl('http://test.com')
|
||||
.then((asset) => {
|
||||
expect(asset).to.have.property('url')
|
||||
.and.to.equal('http://test.com');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return a new asset when the url does not exist', () => {
|
||||
return Asset.findOrCreateByUrl('http://new.test.com')
|
||||
.then((asset) => {
|
||||
expect(asset).to.have.property('id')
|
||||
.and.to.not.equal(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#findOrCreateByUrl', ()=> {
|
||||
it('should find an asset by a url', () => {
|
||||
return Asset.findOrCreateByUrl('http://test.com')
|
||||
.then((asset) => {
|
||||
expect(asset).to.have.property('url')
|
||||
.and.to.equal('http://test.com');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return a new asset when the url does not exist', () => {
|
||||
return Asset.findOrCreateByUrl('http://new.test.com')
|
||||
.then((asset) => {
|
||||
expect(asset).to.have.property('id')
|
||||
.and.to.not.equal(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#upsert', ()=> {
|
||||
it('should insert an asset with no id', () => {
|
||||
return Asset.upsert({url: 'http://newasset.test.com'})
|
||||
.then((asset) => {
|
||||
expect(asset).to.have.property('id');
|
||||
});
|
||||
});
|
||||
|
||||
it('should update an asset when the id exists', () => {
|
||||
return Asset.upsert({id: 1, url: 'http://new.test.com'})
|
||||
.then((asset) => {
|
||||
expect(asset).to.have.property('id')
|
||||
.and.to.equal('1');
|
||||
expect(asset).to.have.property('url')
|
||||
.and.to.equal('http://new.test.com');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#removeAll', ()=> {
|
||||
it('should insert an asset with no id', () => {
|
||||
return Asset.removeAll({id:1})
|
||||
.then(() => {
|
||||
return Asset.findById(1);
|
||||
})
|
||||
.then((result) => {
|
||||
expect(result).to.be.null;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -134,4 +134,15 @@ describe('Comment: models', () => {
|
||||
// });
|
||||
// });
|
||||
});
|
||||
|
||||
describe('#removeAction', () => {
|
||||
it('should remove an action', () => {
|
||||
return Comment.removeAction('3', '123', 'flag').then(() => {
|
||||
return Action.findByItemIdArray(['123']);
|
||||
})
|
||||
.then((actions) => {
|
||||
expect(actions.length).to.equal(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
require('../../../utils/mongoose');
|
||||
|
||||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
const server = require('../../../../app');
|
||||
|
||||
// Setup chai.
|
||||
chai.should();
|
||||
chai.use(require('chai-http'));
|
||||
|
||||
let fixture = {
|
||||
'url': 'http://hhgg.com/total-perspective-vortex',
|
||||
'type': 'article',
|
||||
'headline': 'The Total Perspective Vortex',
|
||||
'summary': 'You are an insignificant dot on an insignificant dot.',
|
||||
'section': 'Everything',
|
||||
'authors': ['Ford Prefect']
|
||||
};
|
||||
|
||||
describe('Asset: routes', () => {
|
||||
|
||||
describe('/GET Asset', () => {
|
||||
describe('#get', () => {
|
||||
it('It should get an empty array when there are no assets.', (done) => {
|
||||
|
||||
chai.request(server)
|
||||
.get('/api/v1/asset')
|
||||
.end((err, res) => {
|
||||
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
res.should.have.status(200);
|
||||
res.body.should.be.a('array');
|
||||
res.body.length.should.be.eql(0);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// This test checks PUT and read
|
||||
describe('/PUT Asset', () => {
|
||||
describe('#put', () => {
|
||||
it('It should save an asset and load it again.', (done) => {
|
||||
|
||||
chai.request(server)
|
||||
.put('/api/v1/asset')
|
||||
.send(fixture)
|
||||
.end((err, res) => {
|
||||
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
res.should.have.status(200);
|
||||
res.body.should.be.a('object');
|
||||
|
||||
// Id should be generated by the model if absent.
|
||||
res.body.should.have.property('id');
|
||||
|
||||
// Save the asset id to compare with GET result.
|
||||
let assetId = res.body.id;
|
||||
|
||||
// Load the asset to make sure it's really there.
|
||||
chai.request(server)
|
||||
.get(`/api/v1/asset?url=${encodeURIComponent(fixture.url)}`)
|
||||
.end((err, res) => {
|
||||
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
res.should.have.status(200);
|
||||
res.body.should.be.an('array');
|
||||
|
||||
let asset = res.body[0];
|
||||
|
||||
expect(asset).to.have.property('id');
|
||||
|
||||
// Ensure the asset has the same id as above.
|
||||
// This tests the single url per Id concept.
|
||||
expect(assetId).to.equal(asset.id);
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}); // End describe /PUT Asset
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user