diff --git a/client/admin/adminSearch/adminSearch.jsx b/client/admin/adminSearch/adminSearch.jsx
index 1f95153..15d0972 100644
--- a/client/admin/adminSearch/adminSearch.jsx
+++ b/client/admin/adminSearch/adminSearch.jsx
@@ -11,7 +11,7 @@ const AdminSearch = React.createClass({
},
render: function(){
return
- AdminSearch Component Ready.
+
Admin Search
}
});
diff --git a/package.json b/package.json
index e553ba5..02d5ab8 100644
--- a/package.json
+++ b/package.json
@@ -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"
diff --git a/scripts/populate.js b/scripts/populate.js
new file mode 100644
index 0000000..7a392af
--- /dev/null
+++ b/scripts/populate.js
@@ -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);
diff --git a/server/brew.api.js b/server/brew.api.js
index d7e30bf..d0565b4 100644
--- a/server/brew.api.js
+++ b/server/brew.api.js
@@ -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
diff --git a/server/brew.data.js b/server/brew.data.js
index 367d33b..c6e92ee 100644
--- a/server/brew.data.js
+++ b/server/brew.data.js
@@ -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;
\ No newline at end of file
+const BrewSearch = require('./brew.search.js')(Brew);
+
+module.exports = _.merge(BrewData, BrewSearch);
\ No newline at end of file
diff --git a/server/brew.search.js b/server/brew.search.js
new file mode 100644
index 0000000..a75b768
--- /dev/null
+++ b/server/brew.search.js
@@ -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;
+};
\ No newline at end of file
diff --git a/server/db.js b/server/db.js
index a9c5400..d0756bf 100644
--- a/server/db.js
+++ b/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
}
\ No newline at end of file
diff --git a/server/middleware.js b/server/middleware.js
index cc2a535..fb4c424 100644
--- a/server/middleware.js
+++ b/server/middleware.js
@@ -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)
diff --git a/shared/homebrewery/brewEditor/metadataEditor/metadataEditor.less b/shared/homebrewery/brewEditor/metadataEditor/metadataEditor.less
index c3141f0..2f9812d 100644
--- a/shared/homebrewery/brewEditor/metadataEditor/metadataEditor.less
+++ b/shared/homebrewery/brewEditor/metadataEditor/metadataEditor.less
@@ -76,4 +76,7 @@
font-size: 0.8em;
line-height : 1.5em;
}
+ .thumbnail.field{
+
+ }
}
\ No newline at end of file
diff --git a/test/admin.test.js b/test/admin.test.js
index 6d2ccce..b2590ca 100644
--- a/test/admin.test.js
+++ b/test/admin.test.js
@@ -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);
});
});
diff --git a/test/api.test.js b/test/api.test.js
index 822683c..0ba5fdb 100644
--- a/test/api.test.js
+++ b/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');
});
});
});
diff --git a/test/brew.gen.js b/test/brew.gen.js
new file mode 100644
index 0000000..c7d59b3
--- /dev/null
+++ b/test/brew.gen.js
@@ -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}`
+ )
+ });
+ }
+};
\ No newline at end of file
diff --git a/test/middleware.test.js b/test/middleware.test.js
index 44c822d..c407516 100644
--- a/test/middleware.test.js
+++ b/test/middleware.test.js
@@ -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);
});
diff --git a/test/search.test.js b/test/search.test.js
index e69de29..6649500 100644
--- a/test/search.test.js
+++ b/test/search.test.js
@@ -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);
+ });
+ });
+ });
+});
\ No newline at end of file
diff --git a/test/test.init.js b/test/test.init.js
index 7dda4f8..ab1567a 100644
--- a/test/test.init.js
+++ b/test/test.init.js
@@ -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'));
+ }
};