mirror of
https://github.com/stolksdorf/homebrewery.git
synced 2025-12-12 23:55:57 +00:00
Merge branch 'search' into newAdmin
This commit is contained in:
@@ -11,7 +11,7 @@ const AdminSearch = React.createClass({
|
||||
},
|
||||
render: function(){
|
||||
return <div className='adminSearch'>
|
||||
AdminSearch Component Ready.
|
||||
<h1>Admin Search</h1>
|
||||
</div>
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"quick": "node scripts/quick.js",
|
||||
"build": "node scripts/build.js",
|
||||
"phb": "node scripts/phb.js",
|
||||
"populate": "node scripts/populate.js",
|
||||
"prod": "set NODE_ENV=production&& npm run build",
|
||||
"postinstall": "npm run build",
|
||||
"start": "node server.js",
|
||||
@@ -43,6 +44,7 @@
|
||||
"app-module-path": "^2.1.0",
|
||||
"chai": "^3.5.0",
|
||||
"chai-as-promised": "^6.0.0",
|
||||
"chai-subset": "^1.4.0",
|
||||
"mocha": "^3.2.0",
|
||||
"supertest": "^2.0.1",
|
||||
"supertest-as-promised": "^4.0.2"
|
||||
|
||||
22
scripts/populate.js
Normal file
22
scripts/populate.js
Normal file
@@ -0,0 +1,22 @@
|
||||
//Populates the DB with a bunch of brews for UI testing
|
||||
const _ = require('lodash');
|
||||
|
||||
const DB = require('../server/db.js');
|
||||
const BrewData = require('../server/brew.data.js');
|
||||
const BrewGen = require('../test/brew.gen.js');
|
||||
|
||||
return Promise.resolve()
|
||||
.then(DB.connect)
|
||||
.then(BrewData.removeAll)
|
||||
.then(() => {
|
||||
console.log('Adding random brews...');
|
||||
return return BrewGen.populateDB(BrewGen.random(5));
|
||||
})
|
||||
.then(() => {
|
||||
console.log('Adding specific brews...');
|
||||
return return BrewGen.populateDB(BrewGen.static());
|
||||
})
|
||||
.then(() => {
|
||||
return DB.close();
|
||||
})
|
||||
.catch(console.error);
|
||||
@@ -6,10 +6,25 @@ const mw = require('./middleware.js');
|
||||
|
||||
//Search
|
||||
router.get('/api/brew', (req, res, next) => {
|
||||
const opts = _.pick(req.query, ['limit', 'sort', 'page']);
|
||||
|
||||
//TODO
|
||||
BrewData.termSearch(req.query.terms, opts, req.admin)
|
||||
.then((result) => {
|
||||
return res.status(200).json(result);
|
||||
})
|
||||
.catch(next);
|
||||
});
|
||||
|
||||
//User
|
||||
router.get('/api/user/:username', (req, res, next) => {
|
||||
const fullAccess = req.admin ||
|
||||
!!(req.account && req.params.username == req.account.username);
|
||||
|
||||
BrewData.userSearch(req.params.username, fullAccess)
|
||||
.then((result) => {
|
||||
return res.status(200).json(result);
|
||||
})
|
||||
.catch(next);
|
||||
});
|
||||
|
||||
//Get
|
||||
|
||||
@@ -21,7 +21,8 @@ const BrewSchema = mongoose.Schema({
|
||||
createdAt : { type: Date, default: Date.now },
|
||||
updatedAt : { type: Date, default: Date.now},
|
||||
lastViewed : { type: Date, default: Date.now},
|
||||
views : {type:Number, default:0}
|
||||
views : {type:Number, default:0},
|
||||
version : {type: Number, default:1}
|
||||
}, {
|
||||
versionKey: false,
|
||||
toJSON : {
|
||||
@@ -32,6 +33,9 @@ const BrewSchema = mongoose.Schema({
|
||||
}
|
||||
});
|
||||
|
||||
//Index these fields for fast text searching
|
||||
BrewSchema.index({ title: "text", description: "text" });
|
||||
|
||||
BrewSchema.methods.increaseView = function(){
|
||||
this.views = this.views + 1;
|
||||
return this.save();
|
||||
@@ -39,9 +43,6 @@ BrewSchema.methods.increaseView = function(){
|
||||
|
||||
|
||||
const Brew = mongoose.model('Brew', BrewSchema);
|
||||
|
||||
|
||||
|
||||
const BrewData = {
|
||||
schema : BrewSchema,
|
||||
model : Brew,
|
||||
@@ -92,15 +93,8 @@ const BrewData = {
|
||||
getByEdit : (editId) => {
|
||||
return BrewData.get({ editId });
|
||||
},
|
||||
|
||||
search : (query, req={}) => {
|
||||
//defaults with page and count
|
||||
//returns a non-text version of brews
|
||||
//assume sanatized ?
|
||||
return Promise.resolve([]);
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
|
||||
module.exports = BrewData;
|
||||
const BrewSearch = require('./brew.search.js')(Brew);
|
||||
|
||||
module.exports = _.merge(BrewData, BrewSearch);
|
||||
66
server/brew.search.js
Normal file
66
server/brew.search.js
Normal file
@@ -0,0 +1,66 @@
|
||||
const _ = require('lodash');
|
||||
|
||||
module.exports = (Brew) => {
|
||||
const cmds = {
|
||||
termSearch : (terms='', opts, fullAccess) => {
|
||||
let query = {};
|
||||
if(terms){
|
||||
query = {$text: {
|
||||
//Wrap terms in quotes to perform an AND operation
|
||||
$search: _.map(terms.split(' '), (term)=>{
|
||||
return `\"${term}\"`;
|
||||
}).join(' '),
|
||||
$caseSensitive : false
|
||||
}};
|
||||
}
|
||||
return cmds.search(query, opts, fullAccess);
|
||||
},
|
||||
|
||||
userSearch : (username, fullAccess) => {
|
||||
const query = {
|
||||
authors : username
|
||||
};
|
||||
|
||||
return cmds.search(query, {}, fullAccess);
|
||||
},
|
||||
|
||||
search : (queryObj={}, options={}, fullAccess = true) => {
|
||||
const opts = _.merge({
|
||||
limit : 25,
|
||||
page : 0,
|
||||
sort : {}
|
||||
}, options);
|
||||
opts.limit = _.toNumber(opts.limit);
|
||||
opts.page = _.toNumber(opts.page);
|
||||
|
||||
let filter = {
|
||||
text : 0
|
||||
};
|
||||
|
||||
if(!fullAccess){
|
||||
filter.editId = 0;
|
||||
queryObj.published = true;
|
||||
}
|
||||
|
||||
const searchQuery = Brew
|
||||
.find(queryObj)
|
||||
.sort(opts.sort)
|
||||
.select(filter)
|
||||
.limit(opts.limit)
|
||||
.skip(opts.page * opts.limit)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
const countQuery = Brew.count(queryObj).exec();
|
||||
|
||||
return Promise.all([searchQuery, countQuery])
|
||||
.then((result) => {
|
||||
return {
|
||||
brews : result[0],
|
||||
total : result[1]
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
return cmds;
|
||||
};
|
||||
14
server/db.js
14
server/db.js
@@ -8,14 +8,14 @@ module.exports = {
|
||||
connect : ()=>{
|
||||
return new Promise((resolve, reject)=>{
|
||||
if(mongoose.connection.readyState == 1){
|
||||
log.info('DB already connected');
|
||||
log.warn('DB already connected');
|
||||
return resolve();
|
||||
}
|
||||
mongoose.connect(dbPath,
|
||||
(err) => {
|
||||
if(err){
|
||||
log.info('Error : Could not connect to a Mongo Database.');
|
||||
log.info(' If you are running locally, make sure mongodb.exe is running.');
|
||||
log.error('Error : Could not connect to a Mongo Database.');
|
||||
log.error(' If you are running locally, make sure mongodb.exe is running.');
|
||||
return reject(err);
|
||||
}
|
||||
log.info('DB connected.');
|
||||
@@ -24,5 +24,13 @@ module.exports = {
|
||||
);
|
||||
});
|
||||
},
|
||||
close : ()=>{
|
||||
return new Promise((resolve, reject) => {
|
||||
mongoose.connection.close(()=>{
|
||||
log.info('DB connection closed.');
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
instance : mongoose
|
||||
}
|
||||
@@ -16,7 +16,8 @@ const Middleware = {
|
||||
return next();
|
||||
},
|
||||
admin : (req, res, next) => {
|
||||
if(req.query.admin_key === config.get('admin:key')){
|
||||
req.admin = false;
|
||||
if(req.headers['x-homebrew-admin'] === config.get('admin:key')){
|
||||
req.admin = true;
|
||||
}
|
||||
return next();
|
||||
@@ -44,6 +45,7 @@ const Middleware = {
|
||||
},
|
||||
|
||||
|
||||
//TODO: REMOVE
|
||||
//Loaders
|
||||
loadBrew : (req, res, next) => {
|
||||
BrewData.getByEdit(req.params.editId)
|
||||
|
||||
@@ -76,4 +76,7 @@
|
||||
font-size: 0.8em;
|
||||
line-height : 1.5em;
|
||||
}
|
||||
.thumbnail.field{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ let brewA = {
|
||||
authors : ['your_dm']
|
||||
};
|
||||
|
||||
|
||||
describe('Admin API', ()=>{
|
||||
before('Connect DB', DB.connect);
|
||||
|
||||
@@ -35,7 +36,7 @@ describe('Admin API', ()=>{
|
||||
it('looks up a brew based on the share id', () => {
|
||||
return request(app)
|
||||
.get(`/admin/lookup/${brewA.shareId}`)
|
||||
.query({ admin_key : config.get('admin:key') })
|
||||
.set('x-homebrew-admin', config.get('admin:key'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const brew = res.body;
|
||||
@@ -47,7 +48,7 @@ describe('Admin API', ()=>{
|
||||
it('looks up a brew based on the edit id', () => {
|
||||
return request(app)
|
||||
.get(`/admin/lookup/${brewA.editId}`)
|
||||
.query({ admin_key : config.get('admin:key') })
|
||||
.set('x-homebrew-admin', config.get('admin:key'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const brew = res.body;
|
||||
@@ -60,7 +61,7 @@ describe('Admin API', ()=>{
|
||||
const query = brewA.editId.substring(0, brewA.editId.length -2);
|
||||
return request(app)
|
||||
.get(`/admin/lookup/${query}`)
|
||||
.query({ admin_key : config.get('admin:key') })
|
||||
.set('x-homebrew-admin', config.get('admin:key'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const brew = res.body;
|
||||
@@ -72,7 +73,7 @@ describe('Admin API', ()=>{
|
||||
it('throws an error if it can not find a brew', ()=>{
|
||||
return request(app)
|
||||
.get(`/admin/lookup/BADID`)
|
||||
.query({ admin_key : config.get('admin:key') })
|
||||
.set('x-homebrew-admin', config.get('admin:key'))
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
302
test/api.test.js
302
test/api.test.js
@@ -1,112 +1,246 @@
|
||||
const testing = require('./test.init.js');
|
||||
const Test = require('./test.init.js');
|
||||
const _ = require('lodash');
|
||||
const request = require('supertest-as-promised');
|
||||
const jwt = require('jwt-simple');
|
||||
|
||||
const config = require('nconf');
|
||||
|
||||
const app = require('app.js');
|
||||
const DB = require('db.js');
|
||||
const BrewData = require('brew.data.js');
|
||||
const BrewGen = require('./brew.gen.js');
|
||||
const Error = require('error.js');
|
||||
|
||||
const apiPath = '/api/brew';
|
||||
|
||||
let session_token;
|
||||
const test_user = {
|
||||
username : 'cool guy'
|
||||
};
|
||||
let storedBrew = {
|
||||
title : 'good title',
|
||||
text : 'original text',
|
||||
authors : ['your_dm']
|
||||
};
|
||||
const UserX = { username : 'userX' };
|
||||
const UserA = { username : 'userA' };
|
||||
let UserXToken, UserAToken;
|
||||
|
||||
describe('Brew API', () => {
|
||||
before('Connect DB', DB.connect);
|
||||
before('Clear DB', BrewData.removeAll);
|
||||
before('Create session token', () => {
|
||||
session_token = jwt.encode(test_user, config.get('jwt_secret'));
|
||||
});
|
||||
before('Create brew', ()=>{
|
||||
return BrewData.create(storedBrew)
|
||||
.then((brew)=>{ storedBrew = brew; });
|
||||
UserXToken = Test.getSessionToken(UserX);
|
||||
UserAToken = Test.getSessionToken(UserA);
|
||||
});
|
||||
|
||||
describe('CRUD', ()=>{
|
||||
before('Connect DB', DB.connect);
|
||||
before('Clear DB', BrewData.removeAll);
|
||||
before('Populate brews', ()=>{
|
||||
return BrewGen.populateDB(BrewGen.static());
|
||||
});
|
||||
describe('Create', () => {
|
||||
it('creates a new brew', () => {
|
||||
return request(app)
|
||||
.post(`/api/brew`)
|
||||
.send({ text : 'Brew Text' })
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const brew = res.body;
|
||||
brew.should.have.property('editId').that.is.a('string');
|
||||
brew.should.have.property('shareId').that.is.a('string');
|
||||
brew.should.have.property('text').equal('Brew Text');
|
||||
brew.should.not.have.property('_id');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Create', () => {
|
||||
it('creates a new brew', () => {
|
||||
return request(app)
|
||||
.post(apiPath)
|
||||
.send({ text : 'Brew Text' })
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const brew = res.body;
|
||||
brew.should.have.property('editId').that.is.a('string');
|
||||
brew.should.have.property('shareId').that.is.a('string');
|
||||
brew.should.have.property('text').equal('Brew Text');
|
||||
brew.should.not.have.property('_id');
|
||||
});
|
||||
it('creates a new brew with a session author', () => {
|
||||
return request(app)
|
||||
.post(`/api/brew`)
|
||||
.set('Cookie', `nc_session=${UserXToken}`)
|
||||
.send({ text : 'Brew Text' })
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const brew = res.body;
|
||||
brew.should.have.property('authors').include(UserX.username);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('creates a new brew with a session author', () => {
|
||||
return request(app)
|
||||
.post(apiPath)
|
||||
.set('Cookie', `nc_session=${session_token}`)
|
||||
.send({ text : 'Brew Text' })
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const brew = res.body;
|
||||
brew.should.have.property('authors').include(test_user.username);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('Update', () => {
|
||||
it('updates an existing brew', () => {
|
||||
const storedBrew = BrewGen.get('BrewA');
|
||||
return request(app)
|
||||
.put(`/api/brew/${storedBrew.editId}`)
|
||||
.send({ text : 'New Text' })
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const brew = res.body;
|
||||
brew.should.have.property('editId').equal(storedBrew.editId);
|
||||
brew.should.have.property('text').equal('New Text');
|
||||
brew.should.have.property('authors').include(storedBrew.authors[0]);
|
||||
brew.should.not.have.property('_id');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Update', () => {
|
||||
it('updates an existing brew', () => {
|
||||
return request(app)
|
||||
.put(`${apiPath}/${storedBrew.editId}`)
|
||||
.send({ text : 'New Text' })
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const brew = res.body;
|
||||
brew.should.have.property('editId').equal(storedBrew.editId);
|
||||
brew.should.have.property('text').equal('New Text');
|
||||
brew.should.have.property('authors').include('your_dm');
|
||||
brew.should.not.have.property('_id');
|
||||
});
|
||||
it('adds the user as author', () => {
|
||||
const storedBrew = BrewGen.get('BrewA');
|
||||
return request(app)
|
||||
.put(`/api/brew/${storedBrew.editId}`)
|
||||
.set('Cookie', `nc_session=${UserXToken}`)
|
||||
.send({ text : 'New Text' })
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const brew = res.body;
|
||||
brew.should.have.property('authors').include(UserX.username);
|
||||
brew.should.have.property('authors').include(storedBrew.authors[0]);
|
||||
});
|
||||
});
|
||||
it('should throw error on bad edit id', ()=>{
|
||||
const storedBrew = BrewGen.get('BrewA');
|
||||
return request(app)
|
||||
.put(`/api/brew/BADEDITID`)
|
||||
.send({ text : 'New Text' })
|
||||
.expect(404)
|
||||
});
|
||||
});
|
||||
|
||||
it('adds the user as author', () => {
|
||||
return request(app)
|
||||
.put(`${apiPath}/${storedBrew.editId}`)
|
||||
.set('Cookie', `nc_session=${session_token}`)
|
||||
.send({ text : 'New Text' })
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const brew = res.body;
|
||||
brew.should.have.property('authors').include(test_user.username);
|
||||
brew.should.have.property('authors').include('your_dm');
|
||||
});
|
||||
describe('Remove', () => {
|
||||
it('should removes a brew', ()=>{
|
||||
const storedBrew = BrewGen.get('BrewA');
|
||||
return request(app)
|
||||
.del(`/api/brew/${storedBrew.editId}`)
|
||||
.send()
|
||||
.expect(200)
|
||||
.then(() => {
|
||||
BrewData.getByEdit(storedBrew.editId)
|
||||
.then(() => { throw 'Brew found when one should not have been'; })
|
||||
.catch((err) => {
|
||||
err.should.be.instanceof(Error.noBrew);
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should throw error on bad edit id', ()=>{
|
||||
return request(app)
|
||||
.put(`${apiPath}/BADEDITID`)
|
||||
.send({ text : 'New Text' })
|
||||
.expect(404)
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
describe('Remove', () => {
|
||||
it('should removes a brew', ()=>{
|
||||
|
||||
describe('Search', () => {
|
||||
before('Connect DB', DB.connect);
|
||||
before('Clear DB', BrewData.removeAll);
|
||||
before('Populate brews', ()=>{
|
||||
return BrewGen.populateDB(BrewGen.static());
|
||||
});
|
||||
|
||||
it('should be able to search for all published brews', ()=>{
|
||||
return request(app)
|
||||
.del(`${apiPath}/${storedBrew.editId}`)
|
||||
.get(`/api/brew`)
|
||||
.query({})
|
||||
.send()
|
||||
.expect(200)
|
||||
.then(() => {
|
||||
BrewData.getByEdit(storedBrew.editId)
|
||||
.then(() => { throw 'Brew found when one should not have been'; })
|
||||
.catch((err) => {
|
||||
err.should.be.instanceof(Error.noBrew);
|
||||
})
|
||||
.then((res) => {
|
||||
const result = res.body;
|
||||
result.total.should.be.equal(2);
|
||||
result.brews.should.have.brews('BrewB','BrewD');
|
||||
result.brews[0].should.not.have.property('editId');
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to search for brews with given terms', ()=>{
|
||||
return request(app)
|
||||
.get(`/api/brew`)
|
||||
.query({
|
||||
terms : '5e ranger'
|
||||
})
|
||||
.send()
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const result = res.body;
|
||||
result.total.should.be.equal(1);
|
||||
result.brews.should.have.brews('BrewD');
|
||||
});
|
||||
});
|
||||
it('should be able to sort the search', ()=>{
|
||||
return request(app)
|
||||
.get(`/api/brew`)
|
||||
.query({
|
||||
sort : { views : 1}
|
||||
})
|
||||
.send()
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const result = res.body;
|
||||
result.total.should.be.equal(2);
|
||||
result.brews[0].should.be.brew('BrewD');
|
||||
result.brews[1].should.be.brew('BrewB');
|
||||
});
|
||||
});
|
||||
it('should use pagniation on the search', ()=>{
|
||||
return request(app)
|
||||
.get(`/api/brew`)
|
||||
.query({
|
||||
limit : 1,
|
||||
page : 1,
|
||||
sort : { views : -1}
|
||||
})
|
||||
.send()
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const result = res.body;
|
||||
result.total.should.be.equal(2);
|
||||
result.brews[0].should.be.brew('BrewD');
|
||||
})
|
||||
});
|
||||
it('should return all brews and editIds if admin', ()=>{
|
||||
return request(app)
|
||||
.get(`/api/brew`)
|
||||
.query({})
|
||||
.set('x-homebrew-admin', config.get('admin:key'))
|
||||
.send()
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const result = res.body;
|
||||
const brewCount = _.size(BrewGen.static());
|
||||
result.total.should.be.equal(brewCount);
|
||||
result.brews.length.should.be.equal(brewCount);
|
||||
result.brews[0].should.have.property('editId');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('User', () => {
|
||||
before('Connect DB', DB.connect);
|
||||
before('Clear DB', BrewData.removeAll);
|
||||
before('Populate brews', ()=>{
|
||||
return BrewGen.populateDB(BrewGen.static());
|
||||
});
|
||||
|
||||
it('should be able to query brews for a specific user', ()=>{
|
||||
return request(app)
|
||||
.get(`/api/user/userA`)
|
||||
.send()
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const result = res.body;
|
||||
result.total.should.be.equal(1);
|
||||
result.brews.length.should.be.equal(1);
|
||||
result.brews.should.have.brews('BrewB');
|
||||
result.brews[0].should.not.have.property('editId');
|
||||
});
|
||||
});
|
||||
it('should have full access if loggedin user is queried user', ()=>{
|
||||
return request(app)
|
||||
.get(`/api/user/userA`)
|
||||
.set('Cookie', `nc_session=${UserAToken}`)
|
||||
.send()
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const result = res.body;
|
||||
result.total.should.be.equal(3);
|
||||
result.brews.length.should.be.equal(3);
|
||||
result.brews.should.have.brews('BrewA', 'BrewB', 'BrewC');
|
||||
result.brews[0].should.have.property('editId');
|
||||
});
|
||||
});
|
||||
it('should have full access if admin', ()=>{
|
||||
return request(app)
|
||||
.get(`/api/user/userA`)
|
||||
.set('x-homebrew-admin', config.get('admin:key'))
|
||||
.send()
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const result = res.body;
|
||||
result.total.should.be.equal(3);
|
||||
result.brews.length.should.be.equal(3);
|
||||
result.brews.should.have.brews('BrewA', 'BrewB', 'BrewC');
|
||||
result.brews[0].should.have.property('editId');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
111
test/brew.gen.js
Normal file
111
test/brew.gen.js
Normal file
@@ -0,0 +1,111 @@
|
||||
const _ = require('lodash');
|
||||
const BrewData = require('../server/brew.data.js');
|
||||
|
||||
let PopulatedBrews = {};
|
||||
|
||||
module.exports = {
|
||||
//TODO: Add in a generator for old brews to test the old rendering code
|
||||
|
||||
random : (num = 20)=>{
|
||||
return _.times(num, ()=>{
|
||||
//TODO: Build better generator
|
||||
return {
|
||||
title : 'BrewA',
|
||||
description : '',
|
||||
text : '',
|
||||
authors : _.sampleSize(['userA','userB','userC','userD'], _.random(0, 3)),
|
||||
systems : _.sampleSize(['5e', '4e', '3.5e', 'Pathfinder'], _.random(0,2)),
|
||||
views : _.random(0,1000),
|
||||
published : !!_.random(0,1)
|
||||
};
|
||||
});
|
||||
},
|
||||
static : () => {
|
||||
return {
|
||||
BrewA : {
|
||||
title : 'Brew-Alpha',
|
||||
description : 'fancy',
|
||||
authors : ['userA'],
|
||||
systems : [],
|
||||
views : 12,
|
||||
published : false
|
||||
},
|
||||
BrewB : {
|
||||
title : 'Brew-Beta',
|
||||
description : 'very fancy',
|
||||
authors : ['userA'],
|
||||
systems : [],
|
||||
views : 7,
|
||||
published : true
|
||||
},
|
||||
BrewC : {
|
||||
title : 'Brew-Charlie',
|
||||
description : 'test',
|
||||
authors : ['userA', 'userB'],
|
||||
systems : [],
|
||||
views : 0,
|
||||
published : false
|
||||
},
|
||||
BrewD : {
|
||||
title : 'Brew-Delta',
|
||||
description : 'test super amazing brew for 5e. Geared for Rangers.',
|
||||
authors : ['userC'],
|
||||
systems : [],
|
||||
views : 1,
|
||||
published : true
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
populateDB : (brewCollection)=>{
|
||||
PopulatedBrews = {};
|
||||
return Promise.all(_.map(brewCollection, (brewData, id) => {
|
||||
return BrewData.create(brewData)
|
||||
.then((brew)=>{
|
||||
PopulatedBrews[id] = brew;
|
||||
});
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
get : (brewId) => {
|
||||
return PopulatedBrews[brewId]
|
||||
},
|
||||
|
||||
chaiPlugin : (chai, utils) => {
|
||||
chai.Assertion.addMethod('brews', function(...brewIds){
|
||||
new chai.Assertion(this._obj).to.be.instanceof(Array);
|
||||
const valid = _.every(brewIds, (brewId) => {
|
||||
const storedBrew = PopulatedBrews[brewId];
|
||||
if(!storedBrew) return false;
|
||||
return _.some(this._obj, (brew)=>{
|
||||
return brew.shareId == storedBrew.shareId &&
|
||||
brew.title == storedBrew.title &&
|
||||
brew.views == storedBrew.views;
|
||||
});
|
||||
});
|
||||
this.assert(
|
||||
valid,
|
||||
`expect #{this} to have brews ${brewIds.join(', ')}`,
|
||||
`expect #{this} to not have brews ${brewIds.join(', ')}`
|
||||
)
|
||||
});
|
||||
|
||||
chai.Assertion.addMethod('brew', function(brewId){
|
||||
new chai.Assertion(this._obj).to.be.instanceof(Object);
|
||||
const brew = this._obj;
|
||||
const storedBrew = PopulatedBrews[brewId];
|
||||
|
||||
const valid = storedBrew &&
|
||||
brew.shareId == storedBrew.shareId &&
|
||||
brew.title == storedBrew.title &&
|
||||
brew.views == storedBrew.views;
|
||||
|
||||
this.assert(
|
||||
valid,
|
||||
`expect #{this} to be brew ${brewId}`,
|
||||
`expect #{this} to not be brew ${brewId}`
|
||||
)
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -15,8 +15,6 @@ const requestHandler = (req, res) => {
|
||||
};
|
||||
|
||||
|
||||
console.log(config.get('admin:key'));
|
||||
|
||||
const test_user = {
|
||||
username : 'cool guy'
|
||||
};
|
||||
@@ -106,7 +104,7 @@ describe('Middleware', () => {
|
||||
app.use(mw.admin);
|
||||
app.use(requestHandler)
|
||||
return request(app).get('/')
|
||||
.query({ admin_key : config.get('admin:key') })
|
||||
.set('x-homebrew-admin', config.get('admin:key'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const req = res.body;
|
||||
@@ -119,7 +117,7 @@ describe('Middleware', () => {
|
||||
app.get(requestHandler);
|
||||
app.use(Error.expressHandler);
|
||||
return request(app).get('/')
|
||||
.query({ admin_key : 'BADUSER' })
|
||||
.set('x-homebrew-admin', 'BADADMIN')
|
||||
.send()
|
||||
.expect(401);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
const Test = require('./test.init.js');
|
||||
const _ = require('lodash');
|
||||
|
||||
const DB = require('db.js');
|
||||
const BrewData = require('brew.data.js');
|
||||
const BrewGen = require('./brew.gen.js');
|
||||
//const Error = require('error.js');
|
||||
|
||||
|
||||
|
||||
describe('Brew Search', () => {
|
||||
before('Connect DB', DB.connect);
|
||||
before('Clear DB', BrewData.removeAll);
|
||||
before('Populate brews', ()=>{
|
||||
return BrewGen.populateDB(BrewGen.static());
|
||||
});
|
||||
|
||||
|
||||
describe('Searching', ()=>{
|
||||
it('should return a total and a brew array', ()=>{
|
||||
return BrewData.search()
|
||||
.then((result) => {
|
||||
result.total.should.be.a('number');
|
||||
result.brews.should.be.an('array');
|
||||
})
|
||||
});
|
||||
|
||||
it('should be able to search for all brews', ()=>{
|
||||
return BrewData.search()
|
||||
.then((result) => {
|
||||
const brewCount = _.size(BrewGen.static());
|
||||
result.total.should.be.equal(brewCount);
|
||||
result.brews.length.should.be.equal(brewCount);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('Pagniation', () => {
|
||||
it('should return the exact number of brews based on limit', () => {
|
||||
return BrewData.search({}, {
|
||||
limit : 2
|
||||
})
|
||||
.then((result) => {
|
||||
result.total.should.be.equal(_.size(BrewGen.static()));
|
||||
result.brews.length.should.be.equal(2);
|
||||
})
|
||||
});
|
||||
|
||||
it('should return the correct pages when specified', () => {
|
||||
return BrewData.search({}, {
|
||||
limit : 2,
|
||||
page : 1,
|
||||
sort : { views : 1 }
|
||||
})
|
||||
.then((result) => {
|
||||
result.brews.should.have.brews('BrewA', 'BrewB');
|
||||
})
|
||||
});
|
||||
|
||||
it('should return a partial list if on the last page', () => {
|
||||
return BrewData.search({}, {
|
||||
limit : 3,
|
||||
page : 1
|
||||
})
|
||||
.then((result) => {
|
||||
result.brews.length.should.be.equal(1);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Sorting', ()=>{
|
||||
it('should sort ASC', () => {
|
||||
return BrewData.search({}, {
|
||||
sort : { views : 1 }
|
||||
})
|
||||
.then((result) => {
|
||||
result.brews[0].should.be.brew('BrewC');
|
||||
result.brews[1].should.be.brew('BrewD');
|
||||
result.brews[2].should.be.brew('BrewB');
|
||||
result.brews[3].should.be.brew('BrewA');
|
||||
})
|
||||
});
|
||||
it('should sort DESC', () => {
|
||||
return BrewData.search({}, {
|
||||
sort : { views : -1 }
|
||||
})
|
||||
.then((result) => {
|
||||
result.brews[0].should.be.brew('BrewA');
|
||||
result.brews[1].should.be.brew('BrewB');
|
||||
result.brews[2].should.be.brew('BrewD');
|
||||
result.brews[3].should.be.brew('BrewC');
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('Permissions', () => {
|
||||
it('should only fetch published brews', () => {
|
||||
return BrewData.search({}, {}, false)
|
||||
.then((result) => {
|
||||
result.total.should.be.equal(2);
|
||||
result.brews.should.have.brews('BrewB', 'BrewD');
|
||||
})
|
||||
});
|
||||
it('fetched brews should not have text or editId', () => {
|
||||
return BrewData.search({}, {}, false)
|
||||
.then((result) => {
|
||||
result.brews[0].should.not.have.property('text');
|
||||
result.brews[0].should.not.have.property('editId');
|
||||
})
|
||||
});
|
||||
it('if full access, brews should have editid, but no text', () => {
|
||||
return BrewData.search({}, {}, true)
|
||||
.then((result) => {
|
||||
result.brews[0].should.not.have.property('text');
|
||||
result.brews[0].should.have.property('editId');
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
describe('Term Search', ()=>{
|
||||
it('should search brews based on title', () => {
|
||||
return BrewData.termSearch('Charlie')
|
||||
.then((result) => {
|
||||
result.total.should.be.equal(1);
|
||||
result.brews.should.have.brews('BrewC');
|
||||
})
|
||||
});
|
||||
|
||||
it('should search brews based on description', () => {
|
||||
return BrewData.termSearch('fancy')
|
||||
.then((result) => {
|
||||
result.total.should.be.equal(2);
|
||||
result.brews.should.have.brews('BrewA', 'BrewB');
|
||||
})
|
||||
});
|
||||
|
||||
it('should search brews based on multiple terms', () => {
|
||||
return BrewData.termSearch('ranger 5e')
|
||||
.then((result) => {
|
||||
result.total.should.be.equal(1);
|
||||
result.brews.should.have.brews('BrewD');
|
||||
})
|
||||
});
|
||||
|
||||
it('should perform an AND operation on the provided terms', () => {
|
||||
return BrewData.termSearch('Brew Delta GARBAGE')
|
||||
.then((result) => {
|
||||
result.total.should.be.equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('should search brews based on a combination of both', () => {
|
||||
return BrewData.termSearch('Brew Beta fancy')
|
||||
.then((result) => {
|
||||
result.total.should.be.equal(1);
|
||||
result.brews.should.have.brews('BrewB');
|
||||
});
|
||||
});
|
||||
it('should not worry about the case of the terms', () => {
|
||||
return BrewData.termSearch('FANCY')
|
||||
.then((result) => {
|
||||
result.total.should.be.equal(2);
|
||||
result.brews.should.have.brews('BrewA', 'BrewB');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('User Search', ()=>{
|
||||
it('should return brews just for a single user', () => {
|
||||
return BrewData.userSearch('userA')
|
||||
.then((result) => {
|
||||
result.total.should.be.equal(3);
|
||||
result.brews.should.have.brews('BrewA', 'BrewB', 'BrewC');
|
||||
});
|
||||
});
|
||||
it('should return nothing if provided a non-exsistent user', () => {
|
||||
return BrewData.userSearch('userXYZ')
|
||||
.then((result) => {
|
||||
result.total.should.be.equal(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -7,10 +7,18 @@ const config = require('nconf')
|
||||
.file('environment', { file: `config/${process.env.NODE_ENV}.json` })
|
||||
.file('defaults', { file: 'config/default.json' });
|
||||
|
||||
const should = require('chai').use(require('chai-as-promised')).should();
|
||||
const Chai = require('chai')
|
||||
.use(require('chai-as-promised'))
|
||||
.use(require('chai-subset'))
|
||||
.use(require('./brew.gen.js').chaiPlugin);
|
||||
|
||||
const log = require('loglevel');
|
||||
log.setLevel(config.get('log_level'));
|
||||
|
||||
const jwt = require('jwt-simple');
|
||||
module.exports = {
|
||||
should: should
|
||||
should: Chai.should(),
|
||||
getSessionToken : (userInfo) => {
|
||||
return jwt.encode(userInfo, config.get('jwt_secret'));
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user