diff --git a/package.json b/package.json index e553ba5..951b9a6 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,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/server/brew.data.js b/server/brew.data.js index 217c8cf..d8281e1 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,8 @@ const BrewSchema = mongoose.Schema({ } }); +BrewSchema.index({ title: "text", description: "text" }); + BrewSchema.methods.increaseView = function(){ this.views = this.views + 1; return this.save(); @@ -93,19 +96,53 @@ const BrewData = { return BrewData.get({ editId }); }, - search : (query, pagniation, sorting, permissions) => { + search : (searchTerms, pagination, sorting, fullAccess = true) => { + let query = {}; + if(searchTerms){ + query = {$text: { + //Wrap terms in quots to perform an AND operator + $search: _.map(searchTerms.split(' '), (term)=>{ + return `\"${term}\"`; + }).join(' '), + $caseSensitive : false + }}; + } + + pagination = _.defaults(pagination, { + limit : 25, + page : 0 + }); + sorting = _.defaults(sorting, { + 'views' : 1 + }); + let filter = { + //editId : 0, + text : 0 + }; - //search with query, add in `published = false` - // filter out editId and text + if(!fullAccess){ + filter.editId = 0; + query.published = false; + } - //if admin, removed published=false, remove filtering editId + const searchQuery = Brew + .find(query) + .sort(sorting) + .select(filter) + .limit(pagination.limit) + .skip(pagination.page * pagination.limit) + .exec(); + const countQuery = Brew.count(query).exec(); - //defaults with page and count - //returns a non-text version of brews - //assume sanatized ? - return Promise.resolve([]); + return Promise.all([searchQuery, countQuery]) + .then((result) => { + return { + brews : result[0], + total : result[1] + } + }); }, diff --git a/test/search.test.js b/test/search.test.js index 091f2df..56352dd 100644 --- a/test/search.test.js +++ b/test/search.test.js @@ -18,11 +18,11 @@ const brews = { authors : [], systems : [], views : 12, - published : true + published : false }, BrewB : { title : 'BrewB', - description : 'fancy', + description : 'very fancy', authors : [], systems : [], views : 7, @@ -38,7 +38,7 @@ const brews = { }, BrewD : { title : 'BrewD', - description : 'test', + description : 'test super amazing brew for 5e. Geared for Rangers.', authors : [], systems : [], views : 1, @@ -59,43 +59,82 @@ describe('Brew Search', () => { describe('Searching', ()=>{ it('should be able to search for all brews', ()=>{ - - + return BrewData.search() + .then((result) => { + result.total.should.be.equal(_.size(brews)); + result.brews.length.should.be.equal(_.size(brews)); + }) }); - it('should find brews based on title and/or description', () => { - - //result.count.should.be.equal(2) - //result.brews.should.deep.include.members(ids(['BrewA', 'BrewB']); + it('should search brews based on title', () => { + return BrewData.search('BrewC') + .then((result) => { + result.total.should.be.equal(1); + result.brews.should.containSubset(ids(['BrewC'])); + }) }); - it('should return the total number of brews and page info for query', ()=>{ + it('should search brews based on description', () => { + return BrewData.search('fancy') + .then((result) => { + result.total.should.be.equal(2); + result.brews.should.containSubset(ids(['BrewA', 'BrewB'])); + }) + }); + + it('should search brews based on multiple terms', () => { + return BrewData.search('ranger 5e') + .then((result) => { + result.total.should.be.equal(1); + result.brews.should.containSubset(ids(['BrewD'])); + }) + }); + + it('should perform an AND operation on the provided terms', () => { + return BrewData.search('BrewD GARBAGE') + .then((result) => { + result.total.should.be.equal(0); + }); + }); + + it('should search brews based on a combination of both', () => { + return BrewData.search('BrewB fancy') + .then((result) => { + result.total.should.be.equal(1); + result.brews.should.containSubset(ids(['BrewB'])); + }); + }); + + it.skip('should be able to search for a specific system', ()=>{ + + }); + it.skip('should be able to search for a specifc user', ()=>{ }); }) describe('Permissions', () => { - it('should only fetch published brews', () => { + it.skip('should only fetch published brews', () => { }); - it('fetched brews should not have text or editId', () => { + it.skip('fetched brews should not have text or editId', () => { }); - it('if admin, fetches also non-published brews, with editid', () => { + it.skip('if admin, fetches also non-published brews, with editid', () => { }); - it('if author, fetches also non-published brews, with editid', ()=>{ + it.skip('if author, fetches also non-published brews, with editid', ()=>{ }); }); describe('Pagniation', () => { - it('should return the exact number of brews based on limit', () => { + it.skip('should return the exact number of brews based on limit', () => { }); }); - desscribe('Sorting', ()=>{ + describe('Sorting', ()=>{ }); diff --git a/test/test.init.js b/test/test.init.js index 7dda4f8..2c8c8ec 100644 --- a/test/test.init.js +++ b/test/test.init.js @@ -7,7 +7,11 @@ 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 should = require('chai') + .use(require('chai-as-promised')) + .use(require('chai-subset')) + .should(); + const log = require('loglevel'); log.setLevel(config.get('log_level'));