mirror of
https://github.com/wassname/talk.git
synced 2026-08-05 13:30:26 +08:00
Merge branch 'master' into csrf
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import 'react';
|
||||
import 'redux';
|
||||
import {expect} from 'chai';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import * as actions from '../../../../client/coral-admin/src/actions/assets';
|
||||
import {Map} from 'immutable';
|
||||
|
||||
import configureStore from 'redux-mock-store';
|
||||
|
||||
const mockStore = configureStore();
|
||||
|
||||
describe('Asset actions', () => {
|
||||
let store;
|
||||
|
||||
const assets = [
|
||||
{
|
||||
url: 'http://test.com',
|
||||
id: '123',
|
||||
status: 'closed'
|
||||
},
|
||||
{
|
||||
url: 'http://test.org',
|
||||
id: '456',
|
||||
status: 'open'
|
||||
}
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
store = mockStore(new Map({}));
|
||||
fetchMock.restore();
|
||||
});
|
||||
|
||||
describe('FETCH_ASSETS_REQUEST', () => {
|
||||
|
||||
it('should fetch a list of assets', () => {
|
||||
|
||||
fetchMock.get('*', JSON.stringify({
|
||||
result: assets,
|
||||
count: 2
|
||||
}));
|
||||
|
||||
return actions.fetchAssets(2, 20)(store.dispatch)
|
||||
.then(() => {
|
||||
expect(store.getActions()[0]).to.have.property('type', 'FETCH_ASSETS_REQUEST');
|
||||
expect(store.getActions()[1]).to.have.property('type', 'FETCH_ASSETS_SUCCESS');
|
||||
expect(store.getActions()[1]).to.have.property('count', 2);
|
||||
expect(store.getActions()[1]).to.have.property('assets').
|
||||
and.to.deep.equal(assets);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an error appropriatly', () => {
|
||||
|
||||
fetchMock.get('*', 404);
|
||||
|
||||
return actions.fetchAssets(2, 20)(store.dispatch)
|
||||
.then(() => {
|
||||
expect(store.getActions()[0]).to.have.property('type', 'FETCH_ASSETS_REQUEST');
|
||||
expect(store.getActions()[1]).to.have.property('type', 'FETCH_ASSETS_FAILURE');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('UPDATE_ASSET_STATE_REQUEST', () => {
|
||||
|
||||
it('should update an asset', () => {
|
||||
|
||||
fetchMock.put('*', JSON.stringify(assets[0]));
|
||||
|
||||
return actions.updateAssetState('123', 'status', 'open')(store.dispatch)
|
||||
.then(() => {
|
||||
expect(store.getActions()[0]).to.have.property('type', 'UPDATE_ASSET_STATE_REQUEST');
|
||||
expect(store.getActions()[1]).to.have.property('type', 'UPDATE_ASSET_STATE_SUCCESS');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should return an error appropriately', () => {
|
||||
|
||||
fetchMock.put('*', 404);
|
||||
|
||||
return actions.updateAssetState('123', 'status', 'open')(store.dispatch)
|
||||
.then(() => {
|
||||
expect(store.getActions()[0]).to.have.property('type', 'UPDATE_ASSET_STATE_REQUEST');
|
||||
expect(store.getActions()[1]).to.have.property('type', 'UPDATE_ASSET_STATE_FAILURE');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
import {Map, fromJS} from 'immutable';
|
||||
import {expect} from 'chai';
|
||||
import assetsReducer from '../../../../client/coral-admin/src/reducers/assets';
|
||||
|
||||
describe ('assetsReducer', () => {
|
||||
describe('FETCH_ASSETS_SUCCESS', () => {
|
||||
it('should replace the existing assets', () => {
|
||||
const action = {
|
||||
type: 'FETCH_ASSETS_SUCCESS',
|
||||
count: 200,
|
||||
assets: [
|
||||
{
|
||||
id: '123',
|
||||
url: 'http://test.com',
|
||||
closedAt: 'tomorrow'
|
||||
},
|
||||
{
|
||||
id: '456',
|
||||
url: 'http://test2.com',
|
||||
closedAt: 'thursday'
|
||||
},
|
||||
]
|
||||
};
|
||||
const store = new Map({});
|
||||
const result = assetsReducer(store, action);
|
||||
expect(result.getIn(['byId', '123']).toJS()).to.deep.equal({
|
||||
url: 'http://test.com',
|
||||
closedAt: 'tomorrow',
|
||||
id: '123'
|
||||
});
|
||||
expect(result.getIn(['ids']).toJS()).to.deep.equal([
|
||||
'123',
|
||||
'456'
|
||||
]);
|
||||
expect(result.getIn(['count'])).to.equal(200);
|
||||
});
|
||||
});
|
||||
|
||||
describe('UPDATE_ASSET_STATE_REQUEST', () => {
|
||||
it('should update the state of a particular asset', () => {
|
||||
const action = {
|
||||
type: 'UPDATE_ASSET_STATE_REQUEST',
|
||||
id: '123',
|
||||
closedAt: null
|
||||
};
|
||||
const store = new fromJS({
|
||||
byId: {
|
||||
'123': {
|
||||
id: '123',
|
||||
url: 'http://test.com',
|
||||
closedAt: Date.now()
|
||||
},
|
||||
'456': {
|
||||
id: '456',
|
||||
url: 'http://test2.com',
|
||||
closedAt: 'thursday'
|
||||
}
|
||||
}
|
||||
});
|
||||
const result = assetsReducer(store, action);
|
||||
expect(result.getIn(['byId', '123', 'closedAt'])).to.equal.null;
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -18,12 +18,13 @@ describe('/api/v1/assets', () => {
|
||||
url: 'https://coralproject.net/news/asset1',
|
||||
title: 'Asset 1',
|
||||
description: 'term1',
|
||||
id: '1'
|
||||
closedAt: Date.now()
|
||||
},
|
||||
{
|
||||
url: 'https://coralproject.net/news/asset2',
|
||||
title: 'Asset 2',
|
||||
description: 'term2'
|
||||
description: 'term2',
|
||||
closedAt: null
|
||||
}
|
||||
]);
|
||||
});
|
||||
@@ -81,6 +82,38 @@ describe('/api/v1/assets', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should return only closed assets', () => {
|
||||
return chai.request(app)
|
||||
.get('/api/v1/assets?filter=closed')
|
||||
.set(passport.inject({roles: ['admin']}))
|
||||
.then((res) => {
|
||||
const body = res.body;
|
||||
|
||||
expect(body).to.have.property('count', 1);
|
||||
expect(body).to.have.property('result');
|
||||
|
||||
const assets = body.result;
|
||||
|
||||
expect(assets[0]).to.have.property('title', 'Asset 1');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return only opened assets', () => {
|
||||
return chai.request(app)
|
||||
.get('/api/v1/assets?filter=open')
|
||||
.set(passport.inject({roles: ['admin']}))
|
||||
.then((res) => {
|
||||
const body = res.body;
|
||||
|
||||
expect(body).to.have.property('count', 1);
|
||||
expect(body).to.have.property('result');
|
||||
|
||||
const assets = body.result;
|
||||
|
||||
expect(assets[0]).to.have.property('title', 'Asset 2');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#put', () => {
|
||||
|
||||
@@ -10,22 +10,18 @@ const agent = chai.request.agent(app);
|
||||
chai.should();
|
||||
chai.use(require('chai-http'));
|
||||
|
||||
const wordlist = require('../../../../services/wordlist');
|
||||
const Comment = require('../../../../models/comment');
|
||||
const Asset = require('../../../../models/asset');
|
||||
const Action = require('../../../../models/action');
|
||||
const User = require('../../../../models/user');
|
||||
|
||||
const Setting = require('../../../../models/setting');
|
||||
const settings = {id: '1', moderation: 'pre'};
|
||||
const settings = {id: '1', moderation: 'pre', wordlist: {banned: ['bad words'], suspect: ['suspect words']}};
|
||||
|
||||
describe('/api/v1/comments', () => {
|
||||
|
||||
// Ensure that the settings are always available.
|
||||
beforeEach(() => Promise.all([
|
||||
wordlist.insert(['bad words']),
|
||||
Setting.init(settings)
|
||||
]));
|
||||
beforeEach(() => Setting.init(settings));
|
||||
|
||||
describe('#get', () => {
|
||||
const comments = [{
|
||||
@@ -171,12 +167,22 @@ describe('/api/v1/comments', () => {
|
||||
describe('#post', () => {
|
||||
|
||||
let asset_id;
|
||||
let postmod_asset_id;
|
||||
|
||||
beforeEach(() => Asset.findOrCreateByUrl('https://coralproject.net/section/article-is-the-best').then((asset) => {
|
||||
beforeEach(() => Promise.all([
|
||||
Asset.findOrCreateByUrl('https://coralproject.net/section/article-is-the-best').then((asset) => {
|
||||
|
||||
// Update the asset id.
|
||||
asset_id = asset.id;
|
||||
}));
|
||||
// Update the asset id.
|
||||
asset_id = asset.id;
|
||||
}),
|
||||
Asset.findOrCreateByUrl('https://coralproject.net/section/postmod-article-is-the-best').then((asset) => {
|
||||
|
||||
// Update the asset id.
|
||||
postmod_asset_id = asset.id;
|
||||
|
||||
return Asset.overrideSettings(postmod_asset_id, {moderation: 'post'});
|
||||
}),
|
||||
]));
|
||||
|
||||
it('should create a comment', () => {
|
||||
agent
|
||||
@@ -211,6 +217,37 @@ describe('/api/v1/comments', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a comment with no status and a flag if it contains a suspected word', () => {
|
||||
agent
|
||||
.get('/api/v1/auth')
|
||||
.then((resa) => {
|
||||
expect(resa.status).to.be.equal(200);
|
||||
expect(resa.body).to.have.property('csrfToken');
|
||||
return agent.post('/api/v1/comments')
|
||||
.set(passport.inject({roles: []}))
|
||||
.send({'body': 'suspect words are the most suspicious', 'author_id': '123', 'asset_id': postmod_asset_id, 'parent_id': ''})
|
||||
.then((res) => {
|
||||
expect(res).to.have.status(201);
|
||||
expect(res.body).to.have.property('id');
|
||||
expect(res.body).to.have.property('status', null);
|
||||
|
||||
return Promise.all([
|
||||
res.body,
|
||||
Action.findByType('flag', 'comments')
|
||||
]);
|
||||
})
|
||||
.then(([comment, actions]) => {
|
||||
expect(actions).to.have.length(1);
|
||||
|
||||
let action = actions[0];
|
||||
|
||||
expect(action).to.have.property('item_id', comment.id);
|
||||
expect(action).to.have.property('field', 'body');
|
||||
expect(action).to.have.property('detail', 'Matched suspect word filters.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a comment with a premod status if it\'s asset is has pre-moderation enabled', () => {
|
||||
return Asset
|
||||
.findOrCreateByUrl('https://coralproject.net/article1')
|
||||
@@ -478,7 +515,8 @@ describe('/api/v1/comments/:comment_id/actions', () => {
|
||||
expect(res).to.have.status(201);
|
||||
expect(res).to.have.body;
|
||||
expect(res.body).to.have.property('action_type', 'flag');
|
||||
expect(res.body).to.have.property('detail', 'Comment is too awesome.');
|
||||
expect(res.body).to.have.property('metadata')
|
||||
.and.to.deep.equal({'reason': 'Comment is too awesome.'});
|
||||
expect(res.body).to.have.property('item_id', 'abc');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -42,9 +42,11 @@ describe('/api/v1/users/:user_id/actions', () => {
|
||||
expect(res).to.have.status(201);
|
||||
expect(res).to.have.body;
|
||||
expect(res.body).to.have.property('action_type', 'flag');
|
||||
expect(res.body).to.have.property('detail', 'Bio is too awesome.');
|
||||
expect(res.body).to.have.property('metadata')
|
||||
.and.to.deep.equal({'reason': 'Bio is too awesome.'});
|
||||
expect(res.body).to.have.property('item_id', 'abc');
|
||||
});
|
||||
})
|
||||
.catch(err => console.error(err.message));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+45
-72
@@ -1,54 +1,58 @@
|
||||
const expect = require('chai').expect;
|
||||
|
||||
const wordlist = require('../../services/wordlist');
|
||||
const Wordlist = require('../../services/wordlist');
|
||||
|
||||
describe('wordlist: services', () => {
|
||||
|
||||
before(() => wordlist.insert([
|
||||
'BAD',
|
||||
'bad',
|
||||
'how to murder',
|
||||
'how to kill'
|
||||
]));
|
||||
const wordlists = {
|
||||
banned: [
|
||||
'cookies',
|
||||
'how to do bad things',
|
||||
'how to do really bad things'
|
||||
],
|
||||
suspect: [
|
||||
'do bad things'
|
||||
]
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
expect(wordlist.list).to.not.be.empty;
|
||||
expect(wordlist.enabled).to.be.true;
|
||||
});
|
||||
let wordlist = new Wordlist();
|
||||
|
||||
describe('#init', () => {
|
||||
|
||||
before(() => wordlist.upsert(wordlists));
|
||||
|
||||
it('has entries', () => {
|
||||
expect(wordlist.list).to.not.be.empty;
|
||||
expect(wordlist.enabled).to.be.true;
|
||||
expect(wordlist.lists.banned).to.not.be.empty;
|
||||
expect(wordlist.lists.suspect).to.not.be.empty;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#match', () => {
|
||||
|
||||
const bannedList = Wordlist.parseList(wordlists.banned);
|
||||
|
||||
it('does match on a bad word', () => {
|
||||
[
|
||||
'how to kill',
|
||||
'what is bad',
|
||||
'bad',
|
||||
'BAD.',
|
||||
'how to murder',
|
||||
'How To mUrDer'
|
||||
'how to do really bad things',
|
||||
'what is cookies',
|
||||
'cookies',
|
||||
'COOKIES.',
|
||||
'how to do bad things',
|
||||
'How To do bad things!'
|
||||
].forEach((word) => {
|
||||
expect(wordlist.match(word)).to.be.true;
|
||||
expect(wordlist.match(bannedList, word)).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
it('does not match on a good word', () => {
|
||||
[
|
||||
'how to',
|
||||
'kill',
|
||||
'bads',
|
||||
'cookie',
|
||||
'how to be a great person?',
|
||||
'how to not kill?'
|
||||
'how to not do really bad things?'
|
||||
].forEach((word) => {
|
||||
expect(wordlist.match(word)).to.be.false;
|
||||
expect(wordlist.match(bannedList, word)).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -56,62 +60,31 @@ describe('wordlist: services', () => {
|
||||
|
||||
describe('#filter', () => {
|
||||
|
||||
it('matches on bodies containing bad words', (done) => {
|
||||
before(() => wordlist.upsert(wordlists));
|
||||
|
||||
let req = {
|
||||
body: {
|
||||
content: 'how to kill?'
|
||||
}
|
||||
};
|
||||
|
||||
wordlist.filter('content')(req, {}, (err) => {
|
||||
expect(err).to.be.undefined;
|
||||
expect(req).to.have.property('wordlist');
|
||||
expect(req.wordlist).to.have.property('matched');
|
||||
expect(req.wordlist.matched).to.be.equal(wordlist.ErrContainsProfanity);
|
||||
|
||||
done();
|
||||
});
|
||||
it('matches on bodies containing bad words', () => {
|
||||
let errors = wordlist.filter({
|
||||
content: 'how to do really bad things?'
|
||||
}, 'content');
|
||||
|
||||
expect(errors).to.have.property('banned', Wordlist.ErrContainsProfanity);
|
||||
});
|
||||
|
||||
it('does not match on bodies not containing bad words', (done) => {
|
||||
|
||||
let req = {
|
||||
body: {
|
||||
content: 'how to be a great person?'
|
||||
}
|
||||
};
|
||||
|
||||
wordlist.filter('content')(req, {}, (err) => {
|
||||
expect(err).to.be.undefined;
|
||||
expect(req).to.have.property('wordlist');
|
||||
expect(req.wordlist).to.have.property('matched');
|
||||
expect(req.wordlist.matched).to.be.false;
|
||||
|
||||
done();
|
||||
});
|
||||
it('does not match on bodies not containing bad words', () => {
|
||||
let errors = wordlist.filter({
|
||||
content: 'how to not do really bad things?'
|
||||
}, 'content');
|
||||
|
||||
expect(errors).to.not.have.property('banned');
|
||||
});
|
||||
|
||||
it('does not match on bodies not containing the bad word field', (done) => {
|
||||
|
||||
let req = {
|
||||
body: {
|
||||
author: 'how to kill?',
|
||||
content: 'how to be a great person?'
|
||||
}
|
||||
};
|
||||
|
||||
wordlist.filter('content')(req, {}, (err) => {
|
||||
expect(err).to.be.undefined;
|
||||
expect(req).to.have.property('wordlist');
|
||||
expect(req.wordlist).to.have.property('matched');
|
||||
expect(req.wordlist.matched).to.be.false;
|
||||
|
||||
done();
|
||||
});
|
||||
it('does not match on bodies not containing the bad word field', () => {
|
||||
let errors = wordlist.filter({
|
||||
author: 'how to do really bad things?',
|
||||
content: 'how to be a great person?'
|
||||
}, 'content');
|
||||
|
||||
expect(errors).to.not.have.property('banned');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user