UNPKG

thinky-rest

Version:

Create REST resources and controllers with thinky and Express or Restify

344 lines (329 loc) 11.9 kB
'use strict'; var Promise = require('bluebird'), TestFixture = require('./test-fixture'), request = require('request'), expect = require('chai').expect, _ = require('lodash'), rest = require('../lib'), schemas = require('./schemas'); var test = new TestFixture(); describe('Resource(search)', function() { before(function() { return test.initializeDatabase() .then(function() { test.models.User = test.db.createModel('users', schemas.User); test.models.UserWithIndex = test.db.createModel('usersWithIndex', schemas.User); test.models.UserWithIndex.ensureIndex('username'); test.userlist = [ { username: 'arthur', email: 'arthur@gmail.com' }, { username: 'james', email: 'james@gmail.com' }, { username: 'henry', email: 'henry@gmail.com' }, { username: 'william', email: 'william@gmail.com' }, { username: 'edward', email: 'edward@gmail.com' }, { username: 'arthur', email: 'aaaaarthur@gmail.com' } ]; return Promise.all([ test.models.User.tableReady(), test.models.UserWithIndex.tableReady() ]); }); }); after(function() { return test.dropDatabase(); }); beforeEach(function() { return test.initializeServer() .then(function() { return Promise.all([ test.models.User.ready(), test.models.UserWithIndex.ready() ]); }) .then(function() { return Promise.all([ test.models.User.save(_.cloneDeep(test.userlist)), test.models.UserWithIndex.save(_.cloneDeep(test.userlist)) ]); }) .then(function() { rest.initialize({ app: test.app, thinky: test.db }); }); }); afterEach(function(done) { test.clearDatabase() .then(function() { test.server.close(done); }); }); [ { name: 'with default options', query: 'gmail.com', expectedResults: [ { username: 'arthur', email: 'aaaaarthur@gmail.com' }, { username: 'arthur', email: 'arthur@gmail.com' }, { username: 'edward', email: 'edward@gmail.com' }, { username: 'henry', email: 'henry@gmail.com' }, { username: 'james', email: 'james@gmail.com' }, { username: 'william', email: 'william@gmail.com' } ] }, { name: 'only using the first provided search term', extraQuery: 'q=william&q=henry', expectedResults: [{ username: 'william', email: 'william@gmail.com' }] }, { name: 'using tag searching', query: 'username:he', expectedResults: [ { username: 'henry', email: 'henry@gmail.com' } ] }, { name: 'using tag searching (negated)', query: 'username:-he', expectedResults: [ { username: 'arthur', email: 'aaaaarthur@gmail.com' }, { username: 'arthur', email: 'arthur@gmail.com' }, { username: 'edward', email: 'edward@gmail.com' }, { username: 'james', email: 'james@gmail.com' }, { username: 'william', email: 'william@gmail.com' } ] }, { name: 'with custom search param', config: { search: { param: 'search' } }, query: 'william', expectedResults: [{ username: 'william', email: 'william@gmail.com' }] }, { name: 'with custom search operator', config: { search: { operator: '$eq' } }, query: 'william', expectedResults: [{ username: 'william', email: 'william@gmail.com' }] }, { name: 'in combination with filtered results', query: 'aaaa&username=arthur', expectedResults: [{ username: 'arthur', email: 'aaaaarthur@gmail.com' }] }, { name: 'with existing search criteria', preFlight: function(req, res, context) { context.criteria = { username: "arthur" }; return context.continue; }, query: '@gmail.com', expectedResults: [ { username: 'arthur', email: 'aaaaarthur@gmail.com' }, { username: 'arthur', email: 'arthur@gmail.com' } ] }, { name: 'using a secondary index if it exists', config: { model: function() { return test.models.UserWithIndex; } }, extraQuery: 'username=arthur', preFlight: function(req, res, context) { context.debug = true; return context.continue; }, postFlight: function(req, res, context) { expect(context.query._query._query[1][0][2]).to.eql({ index: 'username' }); return context.continue; }, expectedResults: [ { username: 'arthur', email: 'aaaaarthur@gmail.com' }, { username: 'arthur', email: 'arthur@gmail.com' } ] }, { name: 'using a secondary index if it exists (multiple queries/docs)', config: { model: function() { return test.models.UserWithIndex; } }, extraQuery: 'username=arthur&username=edward', preFlight: function(req, res, context) { context.debug = true; return context.continue; }, postFlight: function(req, res, context) { expect(context.query._query._query[1][0][2]).to.eql({ index: 'username' }); return context.continue; }, expectedResults: [ { username: 'arthur', email: 'aaaaarthur@gmail.com' }, { username: 'arthur', email: 'arthur@gmail.com' }, { username: 'edward', email: 'edward@gmail.com' } ] }, { name: 'without a cache busting token affecting results', extraQuery: '_=1454605315780', expectedResults: [ { username: 'arthur', email: 'aaaaarthur@gmail.com' }, { username: 'arthur', email: 'arthur@gmail.com' }, { username: 'edward', email: 'edward@gmail.com' }, { username: 'henry', email: 'henry@gmail.com' }, { username: 'james', email: 'james@gmail.com' }, { username: 'william', email: 'william@gmail.com' } ] }, { name: 'without a cache busting token affecting results (2)', query: 'gmail.com', extraQuery: '_=1454605315780', expectedResults: [ { username: 'arthur', email: 'aaaaarthur@gmail.com' }, { username: 'arthur', email: 'arthur@gmail.com' }, { username: 'edward', email: 'edward@gmail.com' }, { username: 'henry', email: 'henry@gmail.com' }, { username: 'james', email: 'james@gmail.com' }, { username: 'william', email: 'william@gmail.com' } ] }, { name: 'and not use an existing secondary index if the term is negated', config: { model: function() { return test.models.UserWithIndex; } }, extraQuery: 'username=-arthur', preFlight: function(req, res, context) { context.debug = true; return context.continue; }, postFlight: function(req, res, context) { expect(context.query._query._query[1][0][2]).to.be.undefined; return context.continue; }, expectedResults: [ { username: 'edward', email: 'edward@gmail.com' }, { username: 'henry', email: 'henry@gmail.com' }, { username: 'james', email: 'james@gmail.com' }, { username: 'william', email: 'william@gmail.com' } ] }, { name: 'and not use an existing secondary index if one of multiple terms are negated', config: { model: function() { return test.models.UserWithIndex; } }, extraQuery: 'username=-arthur&username=edward', preFlight: function(req, res, context) { context.debug = true; return context.continue; }, postFlight: function(req, res, context) { expect(context.query._query._query[1][0][2]).to.be.undefined; return context.continue; }, expectedResults: [ { username: 'edward', email: 'edward@gmail.com' }, { username: 'henry', email: 'henry@gmail.com' }, { username: 'james', email: 'james@gmail.com' }, { username: 'william', email: 'william@gmail.com' } ] }, { name: 'using a secondary index in combination with sort', config: { model: function() { return test.models.UserWithIndex; } }, extraQuery: 'username=arthur&sort=username', preFlight: function(req, res, context) { context.debug = true; return context.continue; }, postFlight: function(req, res, context) { expect(context.query._query._query[1][0][1][0][2]).to.eql({ index: 'username' }); return context.continue; }, expectedResults: [ { username: 'arthur', email: 'aaaaarthur@gmail.com' }, { username: 'arthur', email: 'arthur@gmail.com' } ] }, { name: 'using multiple instances of the same direct filter (single query)', extraQuery: 'username=arthur,william', expectedResults: [ { username: 'arthur', email: 'aaaaarthur@gmail.com' }, { username: 'arthur', email: 'arthur@gmail.com' }, { username: 'william', email: 'william@gmail.com' } ] }, { name: 'using multiple instances of the same direct filter (multiple queries)', extraQuery: 'username=arthur&username=william', expectedResults: [ { username: 'arthur', email: 'aaaaarthur@gmail.com' }, { username: 'arthur', email: 'arthur@gmail.com' }, { username: 'william', email: 'william@gmail.com' } ] }, { name: 'using a negated direct filter', extraQuery: 'username=-arthur', expectedResults: [ { username: 'edward', email: 'edward@gmail.com' }, { username: 'henry', email: 'henry@gmail.com' }, { username: 'james', email: 'james@gmail.com' }, { username: 'william', email: 'william@gmail.com' } ] }, { name: 'using a negated direct filter on multiple keys (single query)', extraQuery: 'username=-arthur,-edward', expectedResults: [ { username: 'henry', email: 'henry@gmail.com' }, { username: 'james', email: 'james@gmail.com' }, { username: 'william', email: 'william@gmail.com' } ] }, { name: 'using a negated direct filter on multiple keys (multiple queries)', extraQuery: 'username=-arthur&username=-edward', expectedResults: [ { username: 'henry', email: 'henry@gmail.com' }, { username: 'james', email: 'james@gmail.com' }, { username: 'william', email: 'william@gmail.com' } ] } ].forEach(function(testCase) { it('should search ' + testCase.name, function(done) { testCase.config = testCase.config || {}; if (!!testCase.config.model) testCase.config.model = testCase.config.model(); var resourceConfig = _.defaults(testCase.config, { model: test.models.User, endpoints: ['/users', '/users/:id'] }); var testResource = rest.resource(resourceConfig); var searchParam = testCase.config.search ? testCase.config.search.param || 'q' : 'q'; if (testCase.preFlight) testResource.list.fetch.before(testCase.preFlight); if (testCase.postFlight) testResource.list.send.before(testCase.postFlight); var url = test.baseUrl + resourceConfig.endpoints[0] + '?'; if (!!testCase.query) { url = url + searchParam + '=' + testCase.query; if (!!testCase.extraQuery) url = url + '&'; } if (!!testCase.extraQuery) url = url + testCase.extraQuery; request.get({ url: url }, function(err, response, body) { if (response.statusCode !== 200) console.log(body); expect(response.statusCode).to.equal(200); var records = JSON.parse(body).map(function(r) { delete r.id; return r; }); records = _.sortBy(records, 'email'); expect(records).to.eql(testCase.expectedResults); done(); }); }); }); });