Permalink
Please sign in to comment.
Showing
with
463 additions
and 2,382 deletions.
- +4 −0 .babelrc
- +4 −0 .gitignore
- +29 −13 .jshintrc
- +8 −0 .npmignore
- +8 −0 contributing.md
- +0 −41 lib/feathers.js
- +0 −57 lib/mixins/event.js
- +0 −19 lib/mixins/normalizer.js
- +0 −31 lib/mixins/promise.js
- +0 −7 lib/providers/index.js
- +0 −72 lib/providers/rest/index.js
- +0 −81 lib/providers/rest/wrappers.js
- +0 −54 lib/providers/socket/primus.js
- +0 −51 lib/providers/socket/socketio.js
- +16 −10 package.json
- +12 −11 readme.md
- +35 −40 {lib → src}/application.js
- +25 −0 src/feathers.js
- +57 −0 src/mixins/event.js
- +4 −8 {lib → src}/mixins/index.js
- +17 −0 src/mixins/normalizer.js
- +28 −0 src/mixins/promise.js
- +112 −118 test/application.test.js
- +18 −16 test/distributed.test.js
- +48 −59 test/mixins/event.test.js
- +18 −24 test/mixins/normalizer.test.js
- +20 −40 test/mixins/promise.test.js
- +0 −552 test/providers/primus.test.js
- +0 −418 test/providers/rest.test.js
- +0 −112 test/providers/service-fixture.js
- +0 −548 test/providers/socketio.test.js
4
.babelrc
@@ -0,0 +1,4 @@ | ||
+{ | ||
+ "plugins": [ "add-module-exports" ], | ||
+ "presets": [ "es2015" ] | ||
+} |
4
.gitignore
42
.jshintrc
@@ -1,14 +1,30 @@ | ||
{ | ||
- "globals": { | ||
- "it": true, | ||
- "describe": true, | ||
- "before": true, | ||
- "beforeEach": true, | ||
- "after": true, | ||
- "afterEach": true, | ||
- "exports": true | ||
- }, | ||
- "unused": true, | ||
- "undef": true, | ||
- "node": true | ||
-} | ||
+ "node": true, | ||
+ "esnext": true, | ||
+ "bitwise": true, | ||
+ "camelcase": true, | ||
+ "curly": true, | ||
+ "eqeqeq": true, | ||
+ "immed": true, | ||
+ "indent": 2, | ||
+ "latedef": "nofunc", | ||
+ "newcap": false, | ||
+ "noarg": true, | ||
+ "quotmark": "single", | ||
+ "regexp": true, | ||
+ "undef": true, | ||
+ "unused": true, | ||
+ "strict": false, | ||
+ "trailing": true, | ||
+ "smarttabs": true, | ||
+ "white": false, | ||
+ "node": true, | ||
+ "globals": { | ||
+ "it": true, | ||
+ "describe": true, | ||
+ "before": true, | ||
+ "beforeEach": true, | ||
+ "after": true, | ||
+ "afterEach": true | ||
+ } | ||
+} |
8
.npmignore
@@ -0,0 +1,8 @@ | ||
+./.editorconfig | ||
+./.jshintrc | ||
+./.travis.yml | ||
+./.babelrc | ||
+.idea/ | ||
+src/ | ||
+test/ | ||
+!lib/ |
8
contributing.md
41
lib/feathers.js
@@ -1,41 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-var _ = require('lodash'); | ||
-var express = require('express'); | ||
-var Proto = require('uberproto'); | ||
-var Application = require('./application'); | ||
-var providers = require('./providers'); | ||
-var errors = require('feathers-errors'); | ||
- | ||
-/** | ||
- * Create a Feathers application that extends Express. | ||
- * | ||
- * @return {Function} | ||
- * @api public | ||
- */ | ||
- | ||
-function createApplication() { | ||
- var app = express(); | ||
- Proto.mixin(Application, app); | ||
- app.init(); | ||
- return app; | ||
-} | ||
- | ||
-/** | ||
- * Expose `createApplication()`. | ||
- */ | ||
-module.exports = createApplication; | ||
- | ||
-/** | ||
- * Framework version. | ||
- */ | ||
-exports.version = require('../package.json').version; | ||
- | ||
-// Add the providers (REST and SocketIO) | ||
-_.defaults(module.exports, providers); | ||
- | ||
-// Add the error handling | ||
-_.defaults(module.exports, errors); | ||
- | ||
-// Expose all express methods (like express.engine()) | ||
-_.defaults(module.exports, express); |
57
lib/mixins/event.js
@@ -1,57 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-var _ = require('lodash'); | ||
-var rubberduck = require('rubberduck'); | ||
-var EventEmitter = require('events').EventEmitter; | ||
-var hookObject = require('feathers-commons').hooks.hookObject; | ||
-var eventMappings = { | ||
- create: 'created', | ||
- update: 'updated', | ||
- remove: 'removed', | ||
- patch: 'patched' | ||
-}; | ||
- | ||
-module.exports = function (service) { | ||
- var isEmitter = typeof service.on === 'function' && | ||
- typeof service.emit === 'function'; | ||
- var emitter = service._rubberDuck = rubberduck.emitter(service); | ||
- | ||
- if (typeof service.mixin === 'function') { | ||
- if(!isEmitter) { | ||
- service.mixin(EventEmitter.prototype); | ||
- } | ||
- } | ||
- | ||
- service._serviceEvents = _.isArray(service.events) ? service.events.slice() : []; | ||
- | ||
- // Pass the Rubberduck error event through | ||
- // TODO deal with error events properly | ||
- emitter.on('error', function (errors) { | ||
- service.emit('serviceError', errors[0]); | ||
- }); | ||
- | ||
- _.each(eventMappings, function (event, method) { | ||
- var alreadyEmits = service._serviceEvents.indexOf(event) !== -1; | ||
- | ||
- if (typeof service[method] === 'function' && !alreadyEmits) { | ||
- // The Rubberduck event name (e.g. afterCreate, afterUpdate or afterDestroy) | ||
- var eventName = 'after' + method.charAt(0).toUpperCase() + method.substring(1); | ||
- service._serviceEvents.push(event); | ||
- // Punch the given method | ||
- emitter.punch(method, -1); | ||
- // Pass the event and error event through | ||
- emitter.on(eventName, function (results, args) { | ||
- if (!results[0]) { // callback without error | ||
- var hook = hookObject(method, 'after', args); | ||
- var data = Array.isArray(results[1]) ? results[1] : [ results[1] ]; | ||
- | ||
- data.forEach(function(current) { | ||
- service.emit(event, current, hook); | ||
- }); | ||
- } else { | ||
- service.emit('serviceError', results[0]); | ||
- } | ||
- }); | ||
- } | ||
- }); | ||
-}; |
19
lib/mixins/normalizer.js
@@ -1,19 +0,0 @@ | ||
-var _ = require('lodash'); | ||
-var getArguments = require('feathers-commons').getArguments; | ||
- | ||
-module.exports = function (service) { | ||
- if (typeof service.mixin === 'function') { | ||
- var mixin = {}; | ||
- | ||
- _.each(this.methods, function(method) { | ||
- if(typeof service[method] === 'function') { | ||
- mixin[method] = function() { | ||
- var args = getArguments(method, arguments); | ||
- return this._super.apply(this, args); | ||
- }; | ||
- } | ||
- }); | ||
- | ||
- service.mixin(mixin); | ||
- } | ||
-}; |
31
lib/mixins/promise.js
@@ -1,31 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-var _ = require('lodash'); | ||
- | ||
-var wrapper = function () { | ||
- var result = this._super.apply(this, arguments); | ||
- var callback = arguments[arguments.length - 1]; | ||
- | ||
- if(typeof result !== 'undefined' && _.isFunction(result.then) && _.isFunction(callback)) { | ||
- result.then(function(data) { | ||
- callback(null, data); | ||
- }, function(error) { | ||
- callback(error); | ||
- }); | ||
- } | ||
- return result; | ||
-}; | ||
- | ||
-module.exports = function (service) { | ||
- if (typeof service.mixin === 'function') { | ||
- var mixin = {}; | ||
- | ||
- _.each(this.methods, function(method) { | ||
- if(typeof service[method] === 'function') { | ||
- mixin[method] = wrapper; | ||
- } | ||
- }); | ||
- | ||
- service.mixin(mixin); | ||
- } | ||
-}; |
7
lib/providers/index.js
@@ -1,7 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-module.exports = { | ||
- rest: require('./rest'), | ||
- socketio: require('./socket/socketio'), | ||
- primus: require('./socket/primus') | ||
-}; |
72
lib/providers/rest/index.js
@@ -1,72 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-var wrappers = require('./wrappers'); | ||
-var debug = require('debug')('feathers:rest'); | ||
- | ||
-module.exports = function (config) { | ||
- config = config || {}; | ||
- | ||
- var handler = config.handler || function (req, res) { | ||
- res.format({ | ||
- 'application/json': function () { | ||
- res.json(res.data); | ||
- } | ||
- }); | ||
- }; | ||
- | ||
- if (typeof config === 'function') { | ||
- handler = config; | ||
- } | ||
- | ||
- return function () { | ||
- var app = this; | ||
- | ||
- app.enable('feathers rest'); | ||
- | ||
- debug('Setting up default middleware for REST handler'); | ||
- | ||
- app.use(function (req, res, next) { | ||
- req.feathers = {}; | ||
- next(); | ||
- }); | ||
- | ||
- app.rest = wrappers; | ||
- | ||
- // Register the REST provider | ||
- app.providers.push(function (path, service, options) { | ||
- if (app.disabled('feathers rest')) { | ||
- return; | ||
- } | ||
- | ||
- var middleware = (options || {}).middleware || {}; | ||
- var before = middleware.before || []; | ||
- var after = middleware.after || []; | ||
- | ||
- var uri = path.indexOf('/') === 0 ? path : '/' + path; | ||
- var baseRoute = app.route(uri); | ||
- var idRoute = app.route(uri + '/:id'); | ||
- | ||
- debug('Adding REST provider for service `' + path + '` at base route `' + uri + '`'); | ||
- | ||
- // GET / -> service.find(cb, params) | ||
- baseRoute.get.apply(baseRoute, before.concat(app.rest.find(service), after, handler)); | ||
- // POST / -> service.create(data, params, cb) | ||
- baseRoute.post.apply(baseRoute, before.concat(app.rest.create(service), after, handler)); | ||
- // PATCH / -> service.patch(null, data, params) | ||
- baseRoute.patch.apply(baseRoute, before.concat(app.rest.patch(service), after, handler)); | ||
- // PUT / -> service.update(null, data, params) | ||
- baseRoute.put.apply(baseRoute, before.concat(app.rest.update(service), after, handler)); | ||
- // DELETE / -> service.remove(null, params) | ||
- baseRoute.delete.apply(baseRoute, before.concat(app.rest.remove(service), after, handler)); | ||
- | ||
- // GET /:id -> service.get(id, params, cb) | ||
- idRoute.get.apply(idRoute, before.concat(app.rest.get(service), after, handler)); | ||
- // PUT /:id -> service.update(id, data, params, cb) | ||
- idRoute.put.apply(idRoute, before.concat(app.rest.update(service), after, handler)); | ||
- // PATCH /:id -> service.patch(id, data, params, callback) | ||
- idRoute.patch.apply(idRoute, before.concat(app.rest.patch(service), after, handler)); | ||
- // DELETE /:id -> service.remove(id, params, cb) | ||
- idRoute.delete.apply(idRoute, before.concat(app.rest.remove(service), after, handler)); | ||
- }); | ||
- }; | ||
-}; |
81
lib/providers/rest/wrappers.js
@@ -1,81 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-var _ = require('lodash'); | ||
-var debug = require('debug')('feathers:rest'); | ||
-var errors = require('feathers-errors'); | ||
-var status = { | ||
- created: 201, | ||
- noContent: 204, | ||
- methodNotAllowed: 405 | ||
-}; | ||
- | ||
-// A function that returns the middleware for a given method and service | ||
-// `getArgs` is a function that should return additional leading service arguments | ||
-function getHandler (method, getArgs, service) { | ||
- return function (req, res, next) { | ||
- // Check if the method exists on the service at all. Send 405 (Method not allowed) if not | ||
- if (typeof service[method] !== 'function') { | ||
- debug('Method `' + method + '` not allowed on `' + req.url + '`'); | ||
- res.status(status.methodNotAllowed); | ||
- return next(new errors.types.MethodNotAllowed('Method `' + method + '` is not supported by this endpoint.')); | ||
- } | ||
- | ||
- // Run the getArgs callback, if available, for additional parameters | ||
- var args = getArgs(req, res, next); | ||
- // Grab the service parameters. Use req.feathers and set the query to req.query | ||
- var params = _.extend({ query: req.query || {} }, _.omit(req.params || {}, 'id'), req.feathers); | ||
- // The service success callback which sets res.data or calls next() with the error | ||
- var callback = function (error, data) { | ||
- if (error) { | ||
- debug('Error in REST handler: `' + (error.message || error) + '`'); | ||
- return next(error); | ||
- } | ||
- | ||
- res.data = data; | ||
- | ||
- if(!data) { | ||
- debug('No content returned for `' + req.url + '`'); | ||
- res.status(status.noContent); | ||
- } else if(method === 'create') { | ||
- res.status(status.created); | ||
- } | ||
- | ||
- return next(); | ||
- }; | ||
- | ||
- debug('REST handler calling `' + method + '` from `' + req.url + '`'); | ||
- service[method].apply(service, args.concat([ params, callback ])); | ||
- }; | ||
-} | ||
- | ||
-// Returns no leading parameters | ||
-function reqNone () { | ||
- return []; | ||
-} | ||
- | ||
-// Returns the leading parameters for a `get` or `remove` request (the id) | ||
-function reqId (req) { | ||
- return [ req.params.id || null ]; | ||
-} | ||
- | ||
-// Returns the leading parameters for an `update` or `patch` request (id, data) | ||
-function reqUpdate (req) { | ||
- return [ req.params.id || null, req.body ]; | ||
-} | ||
- | ||
-// Returns the leading parameters for a `create` request (data) | ||
-function reqCreate (req) { | ||
- return [ req.body ]; | ||
-} | ||
- | ||
-// Returns wrapped middleware for a service method. | ||
-// Doing some fancy ES 5 .bind argument currying for .getHandler() | ||
-// Basically what you are getting for each is a function(service) {} | ||
-module.exports = { | ||
- find: getHandler.bind(null, 'find', reqNone), | ||
- get: getHandler.bind(null, 'get', reqId), | ||
- create: getHandler.bind(null, 'create', reqCreate), | ||
- update: getHandler.bind(null, 'update', reqUpdate), | ||
- patch: getHandler.bind(null, 'patch', reqUpdate), | ||
- remove: getHandler.bind(null, 'remove', reqId) | ||
-}; |
54
lib/providers/socket/primus.js
@@ -1,54 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-var Proto = require('uberproto'); | ||
-var Primus = require('primus'); | ||
-var Emitter = require('primus-emitter'); | ||
-var debug = require('debug')('feathers:primus'); | ||
-var commons = require('feathers-commons').socket; | ||
- | ||
-module.exports = function(config, configurer) { | ||
- return function() { | ||
- var app = this; | ||
- | ||
- app.enable('feathers primus'); | ||
- | ||
- // Monkey patch app.setup(server) | ||
- Proto.mixin({ | ||
- service: commons.service, | ||
- | ||
- setup: function(server) { | ||
- if (this.disabled('feathers primus')) { | ||
- return this._super.apply(this, arguments); | ||
- } | ||
- | ||
- debug('Setting up Primus'); | ||
- | ||
- var primus = this.primus = new Primus(server, config); | ||
- | ||
- primus.use('emitter', Emitter); | ||
- | ||
- if (typeof configurer === 'function') { | ||
- debug('Calling Primus configuration function'); | ||
- configurer.call(this, primus); | ||
- } | ||
- | ||
- var result = this._super.apply(this, arguments); | ||
- | ||
- commons.setup.call(this, { | ||
- method: 'send', | ||
- connection: function() { | ||
- return primus; | ||
- }, | ||
- clients: function() { | ||
- return primus; | ||
- }, | ||
- params: function(spark) { | ||
- return spark.request.feathers; | ||
- } | ||
- }); | ||
- | ||
- return result; | ||
- } | ||
- }, app); | ||
- }; | ||
-}; |
51
lib/providers/socket/socketio.js
@@ -1,51 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-var socketio = require('socket.io'); | ||
-var Proto = require('uberproto'); | ||
-var debug = require('debug')('feathers:socket.io'); | ||
-var commons = require('feathers-commons').socket; | ||
- | ||
-module.exports = function (config) { | ||
- return function () { | ||
- var app = this; | ||
- | ||
- app.enable('feathers socketio'); | ||
- | ||
- // Monkey patch app.setup(server) | ||
- Proto.mixin({ | ||
- service: commons.service, | ||
- | ||
- setup: function (server) { | ||
- if (this.disabled('feathers socketio')) { | ||
- return this._super.apply(this, arguments); | ||
- } | ||
- | ||
- var io = this.io = socketio.listen(server); | ||
- | ||
- if (typeof config === 'function') { | ||
- debug('Calling SocketIO configuration function'); | ||
- config.call(this, io); | ||
- } | ||
- | ||
- var result = this._super.apply(this, arguments); | ||
- | ||
- debug('Setting up SocketIO'); | ||
- | ||
- commons.setup.call(this, { | ||
- method: 'emit', | ||
- connection: function() { | ||
- return io.sockets; | ||
- }, | ||
- clients: function() { | ||
- return io.sockets.sockets; | ||
- }, | ||
- params: function(socket) { | ||
- return socket.feathers; | ||
- } | ||
- }); | ||
- | ||
- return result; | ||
- } | ||
- }, app); | ||
- }; | ||
-}; |
26
package.json
23
readme.md
75
lib/application.js → src/application.js
25
src/feathers.js
@@ -0,0 +1,25 @@ | ||
+if(!global._babelPolyfill) { require('babel-polyfill'); } | ||
+ | ||
+import _ from 'lodash'; | ||
+import express from 'express'; | ||
+import Proto from 'uberproto'; | ||
+import Application from './application'; | ||
+ | ||
+/** | ||
+ * Create a Feathers application that extends Express. | ||
+ * | ||
+ * @return {Function} | ||
+ * @api public | ||
+ */ | ||
+export default function createApplication() { | ||
+ const app = express(); | ||
+ Proto.mixin(Application, app); | ||
+ app.init(); | ||
+ return app; | ||
+} | ||
+ | ||
+// Framework version | ||
+createApplication.version = require('../package.json').version; | ||
+ | ||
+// Expose all express methods (like express.engine()) | ||
+_.defaults(createApplication, express); |
57
src/mixins/event.js
@@ -0,0 +1,57 @@ | ||
+import _ from 'lodash'; | ||
+import rubberduck from 'rubberduck'; | ||
+import { EventEmitter } from 'events'; | ||
+import { hooks } from 'feathers-commons'; | ||
+ | ||
+const hookObject = hooks.hookObject; | ||
+const eventMappings = { | ||
+ create: 'created', | ||
+ update: 'updated', | ||
+ remove: 'removed', | ||
+ patch: 'patched' | ||
+}; | ||
+ | ||
+function upperCase(name) { | ||
+ return name.charAt(0).toUpperCase() + name.substring(1); | ||
+} | ||
+ | ||
+export default function(service) { | ||
+ const isEmitter = typeof service.on === 'function' && | ||
+ typeof service.emit === 'function'; | ||
+ const emitter = service._rubberDuck = rubberduck.emitter(service); | ||
+ | ||
+ if(typeof service.mixin === 'function' && !isEmitter) { | ||
+ service.mixin(EventEmitter.prototype); | ||
+ } | ||
+ | ||
+ service._serviceEvents = _.isArray(service.events) ? service.events.slice() : []; | ||
+ | ||
+ // Pass the Rubberduck error event through | ||
+ // TODO deal with error events properly | ||
+ emitter.on('error', function (errors) { | ||
+ service.emit('serviceError', errors[0]); | ||
+ }); | ||
+ | ||
+ _.each(eventMappings, (event, method) => { | ||
+ const alreadyEmits = service._serviceEvents.indexOf(event) !== -1; | ||
+ | ||
+ if (typeof service[method] === 'function' && !alreadyEmits) { | ||
+ // The Rubberduck event name (e.g. afterCreate, afterUpdate or afterDestroy) | ||
+ var eventName = `after${upperCase(method)}`; | ||
+ service._serviceEvents.push(event); | ||
+ // Punch the given method | ||
+ emitter.punch(method, -1); | ||
+ // Pass the event and error event through | ||
+ emitter.on(eventName, function (results, args) { | ||
+ if (!results[0]) { // callback without error | ||
+ const hook = hookObject(method, 'after', args); | ||
+ const data = Array.isArray(results[1]) ? results[1] : [ results[1] ]; | ||
+ | ||
+ data.forEach(current => service.emit(event, current, hook)); | ||
+ } else { | ||
+ service.emit('serviceError', results[0]); | ||
+ } | ||
+ }); | ||
+ } | ||
+ }); | ||
+} |
12
lib/mixins/index.js → src/mixins/index.js
17
src/mixins/normalizer.js
@@ -0,0 +1,17 @@ | ||
+import { getArguments } from 'feathers-commons'; | ||
+ | ||
+export default function (service) { | ||
+ if (typeof service.mixin === 'function') { | ||
+ const mixin = {}; | ||
+ | ||
+ this.methods.forEach(method => { | ||
+ if(typeof service[method] === 'function') { | ||
+ mixin[method] = function() { | ||
+ return this._super.apply(this, getArguments(method, arguments)); | ||
+ }; | ||
+ } | ||
+ }); | ||
+ | ||
+ service.mixin(mixin); | ||
+ } | ||
+} |
28
src/mixins/promise.js
@@ -0,0 +1,28 @@ | ||
+function isPromise(result) { | ||
+ return typeof result !== 'undefined' && | ||
+ typeof result.then === 'function'; | ||
+} | ||
+ | ||
+function wrapper() { | ||
+ const result = this._super.apply(this, arguments); | ||
+ const callback = arguments[arguments.length - 1]; | ||
+ | ||
+ if(typeof callback === 'function' && isPromise(result)) { | ||
+ result.then(data => callback(null, data), error => callback(error)); | ||
+ } | ||
+ return result; | ||
+} | ||
+ | ||
+export default function (service) { | ||
+ if (typeof service.mixin === 'function') { | ||
+ const mixin = {}; | ||
+ | ||
+ this.methods.forEach(method => { | ||
+ if(typeof service[method] === 'function') { | ||
+ mixin[method] = wrapper; | ||
+ } | ||
+ }); | ||
+ | ||
+ service.mixin(mixin); | ||
+ } | ||
+} |
230
test/application.test.js
34
test/distributed.test.js
107
test/mixins/event.test.js
42
test/mixins/normalizer.test.js
60
test/mixins/promise.test.js
552
test/providers/primus.test.js
@@ -1,552 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-var assert = require('assert'); | ||
-var _ = require('lodash'); | ||
- | ||
-var feathers = require('../../lib/feathers'); | ||
-var fixture = require('./service-fixture'); | ||
-var todoService = fixture.Service; | ||
-var verify = fixture.verify; | ||
- | ||
-describe('Primus provider', function () { | ||
- var server, socket, app, | ||
- socketParams = { | ||
- user: { name: 'David' }, | ||
- provider: 'websockets' | ||
- }; | ||
- | ||
- before(function () { | ||
- app = feathers() | ||
- .configure(feathers.primus({ | ||
- transformer: 'websockets' | ||
- }, function(primus) { | ||
- socket = new primus.Socket('http://localhost:7888'); | ||
- | ||
- primus.authorize(function (req, done) { | ||
- req.feathers = socketParams; | ||
- done(); | ||
- }); | ||
- })) | ||
- .use('todo', todoService); | ||
- | ||
- server = app.listen(7888, function(){ | ||
- app.use('tasks', todoService); | ||
- }); | ||
- }); | ||
- | ||
- after(function (done) { | ||
- socket.socket.close(); | ||
- server.close(done); | ||
- }); | ||
- | ||
- it('runs primus before setup (#131)', function(done) { | ||
- var counter = 0; | ||
- var app = feathers() | ||
- .configure(feathers.primus({ | ||
- transformer: 'websockets' | ||
- }, function() { | ||
- assert.equal(counter, 0); | ||
- counter++; | ||
- })) | ||
- .use('/todos', { | ||
- find: function(params, callback) { | ||
- callback(null, []); | ||
- }, | ||
- setup: function(app) { | ||
- assert.ok(app.primus); | ||
- assert.equal(counter, 1, 'SocketIO configuration ran first'); | ||
- } | ||
- }); | ||
- | ||
- var srv = app.listen(9119); | ||
- srv.on('listening', function() { | ||
- srv.close(done); | ||
- }); | ||
- }); | ||
- | ||
- it('Passes handshake as service parameters.', function(done) { | ||
- var service = app.service('todo'); | ||
- var old = { | ||
- find: service.find, | ||
- create: service.create, | ||
- update: service.update, | ||
- remove: service.remove | ||
- }; | ||
- | ||
- service.find = function(params) { | ||
- assert.deepEqual(_.omit(params, 'query'), socketParams, 'Handshake parameters passed on proper position'); | ||
- old.find.apply(this, arguments); | ||
- }; | ||
- | ||
- service.create = function(data, params) { | ||
- assert.deepEqual(_.omit(params, 'query'), socketParams, 'Passed handshake parameters'); | ||
- old.create.apply(this, arguments); | ||
- }; | ||
- | ||
- service.update = function(id, data, params) { | ||
- assert.deepEqual(params, _.extend({ | ||
- query: { | ||
- test: 'param' | ||
- } | ||
- }, socketParams), 'Passed handshake parameters as query'); | ||
- old.update.apply(this, arguments); | ||
- }; | ||
- | ||
- socket.send('todo::create', {}, {}, function () { | ||
- socket.send('todo::update', 1, {}, { test: 'param' }, function() { | ||
- _.extend(service, old); | ||
- done(); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- it('Missing parameters in socket call works. (#88)', function(done) { | ||
- var service = app.service('todo'); | ||
- var old = { | ||
- find: service.find | ||
- }; | ||
- | ||
- service.find = function(params) { | ||
- assert.deepEqual(_.omit(params, 'query'), socketParams, 'Handshake parameters passed on proper position'); | ||
- old.find.apply(this, arguments); | ||
- }; | ||
- | ||
- socket.send('todo::find', function () { | ||
- _.extend(service, old); | ||
- done(); | ||
- }); | ||
- }); | ||
- | ||
- describe('Services', function() { | ||
- it('invalid arguments cause an error', function (done) { | ||
- socket.send('todo::find', 1, {}, function(error) { | ||
- assert.equal(error.message, 'Too many arguments for \'find\' service method'); | ||
- done(); | ||
- }); | ||
- }); | ||
- | ||
- describe('CRUD', function () { | ||
- | ||
- it('::find', function (done) { | ||
- socket.send('todo::find', {}, function (error, data) { | ||
- verify.find(data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::get', function (done) { | ||
- socket.send('todo::get', 'laundry', {}, function (error, data) { | ||
- verify.get('laundry', data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::create', function (done) { | ||
- var original = { | ||
- name: 'creating' | ||
- }; | ||
- | ||
- socket.send('todo::create', original, {}, function (error, data) { | ||
- verify.create(original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::create without parameters and callback', function (done) { | ||
- var original = { | ||
- name: 'creating' | ||
- }; | ||
- | ||
- socket.send('todo::create', original); | ||
- | ||
- socket.once('todo created', function(data) { | ||
- verify.create(original, data); | ||
- | ||
- done(); | ||
- }); | ||
- }); | ||
- | ||
- it('::update', function (done) { | ||
- var original = { | ||
- name: 'updating' | ||
- }; | ||
- | ||
- socket.send('todo::update', 23, original, {}, function (error, data) { | ||
- verify.update(23, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::update many', function (done) { | ||
- var original = { | ||
- name: 'updating', | ||
- many: true | ||
- }; | ||
- | ||
- socket.send('todo::update', null, original, {}, function (error, data) { | ||
- verify.update(null, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::patch', function (done) { | ||
- var original = { | ||
- name: 'patching' | ||
- }; | ||
- | ||
- socket.send('todo::patch', 25, original, {}, function (error, data) { | ||
- verify.patch(25, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::patch many', function (done) { | ||
- var original = { | ||
- name: 'patching', | ||
- many: true | ||
- }; | ||
- | ||
- socket.send('todo::patch', null, original, {}, function (error, data) { | ||
- verify.patch(null, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::remove', function (done) { | ||
- socket.send('todo::remove', 11, {}, function (error, data) { | ||
- verify.remove(11, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::remove many', function (done) { | ||
- socket.send('todo::remove', null, {}, function (error, data) { | ||
- verify.remove(null, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- describe('Events', function () { | ||
- it('created', function (done) { | ||
- var original = { | ||
- name: 'created event' | ||
- }; | ||
- | ||
- socket.once('todo created', function (data) { | ||
- verify.create(original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.send('todo::create', original, {}, function () {}); | ||
- }); | ||
- | ||
- it('updated', function (done) { | ||
- var original = { | ||
- name: 'updated event' | ||
- }; | ||
- | ||
- socket.once('todo updated', function (data) { | ||
- verify.update(10, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.send('todo::update', 10, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('patched', function(done) { | ||
- var original = { | ||
- name: 'patched event' | ||
- }; | ||
- | ||
- socket.once('todo patched', function (data) { | ||
- verify.patch(12, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.send('todo::patch', 12, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('removed', function (done) { | ||
- socket.once('todo removed', function (data) { | ||
- verify.remove(333, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.send('todo::remove', 333, {}, function () {}); | ||
- }); | ||
- }); | ||
- | ||
- describe('Event filtering', function() { | ||
- it('.created', function (done) { | ||
- var service = app.service('todo'); | ||
- var original = { description: 'created event test' }; | ||
- var oldCreated = service.created; | ||
- | ||
- service.created = function(data, params, callback) { | ||
- assert.ok(service === this); | ||
- assert.deepEqual(params, socketParams); | ||
- verify.create(original, data); | ||
- | ||
- callback(null, _.extend({ processed: true }, data)); | ||
- }; | ||
- | ||
- socket.send('todo::create', original, {}, function() {}); | ||
- | ||
- socket.once('todo created', function (data) { | ||
- service.created = oldCreated; | ||
- // Make sure Todo got processed | ||
- verify.create(_.extend({ processed: true }, original), data); | ||
- done(); | ||
- }); | ||
- }); | ||
- | ||
- it('.updated', function (done) { | ||
- // TODO this is not testing the right thing | ||
- // but we will get better event filtering in v2 anyway | ||
- var original = { | ||
- name: 'updated event' | ||
- }; | ||
- | ||
- socket.once('todo updated', function (data) { | ||
- verify.update(10, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.send('todo::update', 10, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('.removed', function (done) { | ||
- var service = app.service('todo'); | ||
- var oldRemoved = service.removed; | ||
- | ||
- service.removed = function(data, params, callback) { | ||
- assert.ok(service === this); | ||
- assert.deepEqual(params, socketParams); | ||
- | ||
- if(data.id === 23) { | ||
- // Only dispatch with given id | ||
- return callback(null, data); | ||
- } | ||
- | ||
- callback(null, false); | ||
- }; | ||
- | ||
- socket.send('todo::remove', 1, {}, function() {}); | ||
- socket.send('todo::remove', 23, {}, function() {}); | ||
- | ||
- socket.on('todo removed', function (data) { | ||
- service.removed = oldRemoved; | ||
- assert.equal(data.id, 23); | ||
- done(); | ||
- }); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- describe('Dynamic services', function() { | ||
- describe('CRUD', function () { | ||
- it('::find', function (done) { | ||
- socket.send('tasks::find', {}, function (error, data) { | ||
- verify.find(data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::get', function (done) { | ||
- socket.send('tasks::get', 'laundry', {}, function (error, data) { | ||
- verify.get('laundry', data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::create', function (done) { | ||
- var original = { | ||
- name: 'creating' | ||
- }; | ||
- | ||
- socket.send('tasks::create', original, {}, function (error, data) { | ||
- verify.create(original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::update', function (done) { | ||
- var original = { | ||
- name: 'updating' | ||
- }; | ||
- | ||
- socket.send('tasks::update', 23, original, {}, function (error, data) { | ||
- verify.update(23, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::patch', function (done) { | ||
- var original = { | ||
- name: 'patching' | ||
- }; | ||
- | ||
- socket.send('tasks::patch', 25, original, {}, function (error, data) { | ||
- verify.patch(25, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::remove', function (done) { | ||
- socket.send('tasks::remove', 11, {}, function (error, data) { | ||
- verify.remove(11, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- describe('Events', function () { | ||
- it('created', function (done) { | ||
- var original = { | ||
- name: 'created event' | ||
- }; | ||
- | ||
- socket.once('tasks created', function (data) { | ||
- verify.create(original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.send('tasks::create', original, {}, function () {}); | ||
- }); | ||
- | ||
- it('updated', function (done) { | ||
- var original = { | ||
- name: 'updated event' | ||
- }; | ||
- | ||
- socket.once('tasks updated', function (data) { | ||
- verify.update(10, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.send('tasks::update', 10, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('patched', function(done) { | ||
- var original = { | ||
- name: 'patched event' | ||
- }; | ||
- | ||
- socket.once('tasks patched', function (data) { | ||
- verify.patch(12, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.send('tasks::patch', 12, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('removed', function (done) { | ||
- socket.once('tasks removed', function (data) { | ||
- verify.remove(333, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.send('tasks::remove', 333, {}, function () {}); | ||
- }); | ||
- | ||
- it('custom events', function(done) { | ||
- var service = app.service('todo'); | ||
- var original = { | ||
- name: 'created event' | ||
- }; | ||
- var old = service.create; | ||
- | ||
- service.create = function(data) { | ||
- this.emit('log', { message: 'Custom log event', data: data }); | ||
- service.create = old; | ||
- return old.apply(this, arguments); | ||
- }; | ||
- | ||
- socket.once('todo log', function(data) { | ||
- assert.deepEqual(data, { message: 'Custom log event', data: original }); | ||
- done(); | ||
- }); | ||
- | ||
- socket.send('todo::create', original, {}, function () {}); | ||
- }); | ||
- }); | ||
- | ||
- describe('Event filtering', function() { | ||
- it('.created', function (done) { | ||
- var service = app.service('tasks'); | ||
- var original = { description: 'created event test' }; | ||
- var oldCreated = service.created; | ||
- | ||
- service.created = function(data, params, callback) { | ||
- assert.deepEqual(params, socketParams); | ||
- verify.create(original, data); | ||
- | ||
- callback(null, _.extend({ processed: true }, data)); | ||
- }; | ||
- | ||
- socket.send('tasks::create', original, {}, function() {}); | ||
- | ||
- socket.once('tasks created', function (data) { | ||
- service.created = oldCreated; | ||
- // Make sure Todo got processed | ||
- verify.create(_.extend({ processed: true }, original), data); | ||
- done(); | ||
- }); | ||
- }); | ||
- | ||
- it('.updated', function (done) { | ||
- var original = { | ||
- name: 'updated event' | ||
- }; | ||
- | ||
- socket.once('tasks updated', function (data) { | ||
- verify.update(10, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.send('tasks::update', 10, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('.removed', function (done) { | ||
- var service = app.service('tasks'); | ||
- var oldRemoved = service.removed; | ||
- | ||
- service.removed = function(data, params, callback) { | ||
- assert.deepEqual(params, socketParams); | ||
- | ||
- if(data.id === 23) { | ||
- // Only dispatch with given id | ||
- return callback(null, data); | ||
- } | ||
- | ||
- callback(null, false); | ||
- }; | ||
- | ||
- socket.send('tasks::remove', 1, {}, function() {}); | ||
- socket.send('tasks::remove', 23, {}, function() {}); | ||
- | ||
- socket.on('tasks removed', function (data) { | ||
- service.removed = oldRemoved; | ||
- assert.equal(data.id, 23); | ||
- done(); | ||
- }); | ||
- }); | ||
- }); | ||
- }); | ||
-}); |
418
test/providers/rest.test.js
@@ -1,418 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-var request = require('request'); | ||
-var assert = require('assert'); | ||
-var feathers = require('../../lib/feathers'); | ||
-var bodyParser = require('body-parser'); | ||
- | ||
-var fixture = require('./service-fixture'); | ||
-var todoService = fixture.Service; | ||
-var verify = fixture.verify; | ||
- | ||
-describe('REST provider', function () { | ||
- describe('CRUD', function () { | ||
- var server, app; | ||
- | ||
- before(function () { | ||
- app = feathers().configure(feathers.rest()) | ||
- .use(bodyParser.json()) | ||
- .use('codes', { | ||
- get: function(id, params, callback) { | ||
- callback(); | ||
- }, | ||
- | ||
- create: function(data, params, callback) { | ||
- callback(null, data); | ||
- } | ||
- }) | ||
- .use('todo', todoService); | ||
- | ||
- server = app.listen(4777, function(){ | ||
- app.use('tasks', todoService); | ||
- }); | ||
- }); | ||
- | ||
- after(function (done) { | ||
- server.close(done); | ||
- }); | ||
- | ||
- describe('Services', function() { | ||
- | ||
- it('GET .find', function (done) { | ||
- request('http://localhost:4777/todo', function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.find(JSON.parse(body)); | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('GET .get', function (done) { | ||
- request('http://localhost:4777/todo/dishes', function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.get('dishes', JSON.parse(body)); | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('POST .create', function (done) { | ||
- var original = { | ||
- description: 'POST .create' | ||
- }; | ||
- | ||
- request({ | ||
- url: 'http://localhost:4777/todo', | ||
- method: 'post', | ||
- body: JSON.stringify(original), | ||
- headers: { | ||
- 'Content-Type': 'application/json' | ||
- } | ||
- }, function (error, response, body) { | ||
- assert.ok(response.statusCode === 201, 'Got CREATED status code'); | ||
- verify.create(original, JSON.parse(body)); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('PUT .update', function (done) { | ||
- var original = { | ||
- description: 'PUT .update' | ||
- }; | ||
- | ||
- request({ | ||
- url: 'http://localhost:4777/todo/544', | ||
- method: 'put', | ||
- body: JSON.stringify(original), | ||
- headers: { | ||
- 'Content-Type': 'application/json' | ||
- } | ||
- }, function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.update(544, original, JSON.parse(body)); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('PUT .update many', function (done) { | ||
- var original = { | ||
- description: 'PUT .update', | ||
- many: true | ||
- }; | ||
- | ||
- request({ | ||
- url: 'http://localhost:4777/todo', | ||
- method: 'put', | ||
- body: JSON.stringify(original), | ||
- headers: { | ||
- 'Content-Type': 'application/json' | ||
- } | ||
- }, function (error, response, body) { | ||
- var data = JSON.parse(body); | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.update(null, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('PATCH .patch', function (done) { | ||
- var original = { | ||
- description: 'PATCH .patch' | ||
- }; | ||
- | ||
- request({ | ||
- url: 'http://localhost:4777/todo/544', | ||
- method: 'patch', | ||
- body: JSON.stringify(original), | ||
- headers: { | ||
- 'Content-Type': 'application/json' | ||
- } | ||
- }, function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.patch(544, original, JSON.parse(body)); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('PATCH .patch many', function (done) { | ||
- var original = { | ||
- description: 'PATCH .patch', | ||
- many: true | ||
- }; | ||
- | ||
- request({ | ||
- url: 'http://localhost:4777/todo', | ||
- method: 'patch', | ||
- body: JSON.stringify(original), | ||
- headers: { | ||
- 'Content-Type': 'application/json' | ||
- } | ||
- }, function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.patch(null, original, JSON.parse(body)); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('DELETE .remove', function (done) { | ||
- request({ | ||
- url: 'http://localhost:4777/tasks/233', | ||
- method: 'delete' | ||
- }, function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.remove(233, JSON.parse(body)); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('DELETE .remove many', function (done) { | ||
- request({ | ||
- url: 'http://localhost:4777/tasks', | ||
- method: 'delete' | ||
- }, function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.remove(null, JSON.parse(body)); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- describe('Dynamic Services', function() { | ||
- it('GET .find', function (done) { | ||
- request('http://localhost:4777/tasks', function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.find(JSON.parse(body)); | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('GET .get', function (done) { | ||
- request('http://localhost:4777/tasks/dishes', function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.get('dishes', JSON.parse(body)); | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('POST .create', function (done) { | ||
- var original = { | ||
- description: 'Dynamic POST .create' | ||
- }; | ||
- | ||
- request({ | ||
- url: 'http://localhost:4777/tasks', | ||
- method: 'post', | ||
- body: JSON.stringify(original), | ||
- headers: { | ||
- 'Content-Type': 'application/json' | ||
- } | ||
- }, function (error, response, body) { | ||
- assert.ok(response.statusCode === 201, 'Got CREATED status code'); | ||
- verify.create(original, JSON.parse(body)); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('PUT .update', function (done) { | ||
- var original = { | ||
- description: 'Dynamic PUT .update' | ||
- }; | ||
- | ||
- request({ | ||
- url: 'http://localhost:4777/tasks/544', | ||
- method: 'put', | ||
- body: JSON.stringify(original), | ||
- headers: { | ||
- 'Content-Type': 'application/json' | ||
- } | ||
- }, function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.update(544, original, JSON.parse(body)); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('PATCH .patch', function (done) { | ||
- var original = { | ||
- description: 'Dynamic PATCH .patch' | ||
- }; | ||
- | ||
- request({ | ||
- url: 'http://localhost:4777/tasks/544', | ||
- method: 'patch', | ||
- body: JSON.stringify(original), | ||
- headers: { | ||
- 'Content-Type': 'application/json' | ||
- } | ||
- }, function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.patch(544, original, JSON.parse(body)); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('DELETE .remove', function (done) { | ||
- request({ | ||
- url: 'http://localhost:4777/tasks/233', | ||
- method: 'delete' | ||
- }, function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- verify.remove(233, JSON.parse(body)); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- describe('HTTP status codes', function() { | ||
- var app; | ||
- var server; | ||
- | ||
- before(function() { | ||
- app = feathers().configure(feathers.rest()).use('todo', { | ||
- get: function (id, params, callback) { | ||
- callback(null, { description: 'You have to do ' + id }); | ||
- }, | ||
- | ||
- find: function(params, callback) { | ||
- callback(); | ||
- } | ||
- }); | ||
- | ||
- /* jshint ignore:start */ | ||
- // Error handler | ||
- app.use(function (error, req, res, next) { | ||
- assert.equal(error.message, 'Method `create` is not supported by this endpoint.'); | ||
- res.json({ message: error.message }); | ||
- }); | ||
- /* jshint ignore:end */ | ||
- | ||
- server = app.listen(4780); | ||
- }); | ||
- | ||
- after(function(done) { | ||
- server.close(done); | ||
- }); | ||
- | ||
- it('throws a 405 for undefined service methods (#99)', function (done) { | ||
- request('http://localhost:4780/todo/dishes', function (error, response, body) { | ||
- assert.ok(response.statusCode === 200, 'Got OK status code for .get'); | ||
- assert.deepEqual(JSON.parse(body), { description: 'You have to do dishes' }, 'Got expected object'); | ||
- request({ | ||
- method: 'post', | ||
- url: 'http://localhost:4780/todo' | ||
- }, function (error, response, body) { | ||
- assert.ok(response.statusCode === 405, 'Got 405 for .create'); | ||
- assert.deepEqual(JSON.parse(body), { message: 'Method `create` is not supported by this endpoint.' }, 'Error serialized as expected'); | ||
- done(); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- it('throws a 404 for undefined route', function(done) { | ||
- request('http://localhost:4780/todo/foo/bar', function (error, response) { | ||
- assert.ok(response.statusCode === 404, 'Got Not Found code'); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('empty response sets 204 status codes', function(done) { | ||
- request('http://localhost:4780/todo', function (error, response) { | ||
- assert.ok(response.statusCode === 204, 'Got empty status code'); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- it('sets service parameters', function (done) { | ||
- var service = { | ||
- get: function (id, params, callback) { | ||
- callback(null, params); | ||
- } | ||
- }; | ||
- | ||
- var server = feathers().configure(feathers.rest()) | ||
- .use(function (req, res, next) { | ||
- assert.ok(req.feathers, 'Feathers object initialized'); | ||
- req.feathers.test = 'Happy'; | ||
- next(); | ||
- }) | ||
- .use('service', service) | ||
- .listen(4778); | ||
- | ||
- request('http://localhost:4778/service/bla?some=param&another=thing', function (error, response, body) { | ||
- var expected = { | ||
- test: 'Happy', | ||
- query: { | ||
- some: 'param', | ||
- another: 'thing' | ||
- } | ||
- }; | ||
- | ||
- assert.ok(response.statusCode === 200, 'Got OK status code'); | ||
- assert.deepEqual(JSON.parse(body), expected, 'Got params object back'); | ||
- server.close(done); | ||
- }); | ||
- }); | ||
- | ||
- it('disables REST and lets you set the handler manually', function(done) { | ||
- var app = feathers({ rest: false }); | ||
- | ||
- app.configure(feathers.rest(function restFormatter(req, res) { | ||
- res.format({ | ||
- 'text/plain': function() { | ||
- res.end('The todo is: ' + res.data.description); | ||
- } | ||
- }); | ||
- })) | ||
- .use('/todo', { | ||
- get: function (id, params, callback) { | ||
- callback(null, { description: 'You have to do ' + id }); | ||
- } | ||
- }); | ||
- | ||
- var server = app.listen(4776); | ||
- request('http://localhost:4776/todo/dishes', function (error, response, body) { | ||
- assert.equal(body, 'The todo is: You have to do dishes'); | ||
- server.close(done); | ||
- }); | ||
- }); | ||
- | ||
- it('Lets you configure your own middleware before the handler (#40)', function(done) { | ||
- var data = { description: 'Do dishes!', id: 'dishes' }; | ||
- var app = feathers(); | ||
- | ||
- app.use(function defaultContentTypeMiddleware (req, res, next) { | ||
- req.headers['content-type'] = req.headers['content-type'] || 'application/json'; | ||
- next(); | ||
- }) | ||
- .configure(feathers.rest()) | ||
- .use(bodyParser.json()) | ||
- .use('/todo', { | ||
- create: function (data, params, callback) { | ||
- callback(null, data); | ||
- } | ||
- }); | ||
- | ||
- var server = app.listen(4775); | ||
- request({ | ||
- method: 'POST', | ||
- url: 'http://localhost:4775/todo', | ||
- body: JSON.stringify(data) | ||
- }, function (error, response, body) { | ||
- assert.deepEqual(JSON.parse(body), data); | ||
- server.close(done); | ||
- }); | ||
- }); | ||
-}); |
112
test/providers/service-fixture.js
@@ -1,112 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-var _ = require('lodash'); | ||
-var assert = require('assert'); | ||
- | ||
-var findAllData = [{ | ||
- id: 0, | ||
- description: 'You have to do something' | ||
-}, { | ||
- id: 1, | ||
- description: 'You have to do laundry' | ||
-}]; | ||
- | ||
-exports.Service = { | ||
- events: [ 'log' ], | ||
- | ||
- find: function (params, callback) { | ||
- callback(null, findAllData); | ||
- }, | ||
- | ||
- get: function (name, params, callback) { | ||
- callback(null, { | ||
- id: name, | ||
- description: "You have to do " + name + "!" | ||
- }); | ||
- }, | ||
- | ||
- create: function (data, params, callback) { | ||
- var result = _.clone(data); | ||
- result.id = 42; | ||
- result.status = 'created'; | ||
- | ||
- if(Array.isArray(data)) { | ||
- result.many = true; | ||
- } | ||
- | ||
- callback(null, result); | ||
- }, | ||
- | ||
- update: function (id, data, params, callback) { | ||
- var result = _.clone(data); | ||
- result.id = id; | ||
- result.status = 'updated'; | ||
- | ||
- if(id === null) { | ||
- result.many = true; | ||
- } | ||
- | ||
- callback(null, result); | ||
- }, | ||
- | ||
- patch: function (id, data, params, callback) { | ||
- var result = _.clone(data); | ||
- result.id = id; | ||
- result.status = 'patched'; | ||
- | ||
- if(id === null) { | ||
- result.many = true; | ||
- } | ||
- | ||
- callback(null, result); | ||
- }, | ||
- | ||
- remove: function (id, params, callback) { | ||
- var result = { | ||
- id: id | ||
- }; | ||
- | ||
- callback(null, result); | ||
- } | ||
-}; | ||
- | ||
-exports.verify = { | ||
- find: function (data) { | ||
- assert.deepEqual(findAllData, data, 'Data as expected'); | ||
- }, | ||
- | ||
- get: function (id, data) { | ||
- assert.equal(data.id, id, 'Got id in data'); | ||
- assert.equal(data.description, 'You have to do ' + id + '!', 'Got description'); | ||
- }, | ||
- | ||
- create: function (original, current) { | ||
- var expected = _.extend({}, original, { | ||
- id: 42, | ||
- status: 'created' | ||
- }); | ||
- assert.deepEqual(expected, current, 'Data ran through .create as expected'); | ||
- }, | ||
- | ||
- update: function (id, original, current) { | ||
- var expected = _.extend({}, original, { | ||
- id: id, | ||
- status: 'updated' | ||
- }); | ||
- assert.deepEqual(expected, current, 'Data ran through .update as expected'); | ||
- }, | ||
- | ||
- patch: function (id, original, current) { | ||
- var expected = _.extend({}, original, { | ||
- id: id, | ||
- status: 'patched' | ||
- }); | ||
- assert.deepEqual(expected, current, 'Data ran through .patch as expected'); | ||
- }, | ||
- | ||
- remove: function (id, data) { | ||
- assert.deepEqual({ | ||
- id: id | ||
- }, data, '.remove called'); | ||
- } | ||
-}; |
548
test/providers/socketio.test.js
@@ -1,548 +0,0 @@ | ||
-'use strict'; | ||
- | ||
-var _ = require('lodash'); | ||
-var feathers = require('../../lib/feathers'); | ||
-var io = require('socket.io-client'); | ||
-var assert = require('assert'); | ||
- | ||
-var fixture = require('./service-fixture'); | ||
-var todoService = fixture.Service; | ||
-var verify = fixture.verify; | ||
- | ||
-describe('SocketIO provider', function () { | ||
- var server, socket, app, | ||
- socketParams = { | ||
- user: { name: 'David' }, | ||
- provider: 'socketio' | ||
- }; | ||
- | ||
- before(function () { | ||
- app = feathers() | ||
- .configure(feathers.socketio(function(io) { | ||
- io.use(function (socket, next) { | ||
- socket.feathers = socketParams; | ||
- next(); | ||
- }); | ||
- })) | ||
- .use('todo', todoService); | ||
- | ||
- server = app.listen(7886, function(){ | ||
- app.use('tasks', todoService); | ||
- }); | ||
- | ||
- socket = io.connect('http://localhost:7886'); | ||
- }); | ||
- | ||
- after(function (done) { | ||
- socket.disconnect(); | ||
- server.close(done); | ||
- }); | ||
- | ||
- it('runs io before setup (#131)', function(done) { | ||
- var counter = 0; | ||
- var app = feathers() | ||
- .configure(feathers.socketio(function() { | ||
- assert.equal(counter, 0); | ||
- counter++; | ||
- })) | ||
- .use('/todos', { | ||
- find: function(params, callback) { | ||
- callback(null, []); | ||
- }, | ||
- setup: function(app) { | ||
- assert.ok(app.io); | ||
- assert.equal(counter, 1, 'SocketIO configuration ran first'); | ||
- } | ||
- }); | ||
- | ||
- var srv = app.listen(8887); | ||
- srv.on('listening', function() { | ||
- srv.close(done); | ||
- }); | ||
- }); | ||
- | ||
- it('passes handshake as service parameters', function(done) { | ||
- var service = app.service('todo'); | ||
- var old = { | ||
- find: service.find, | ||
- create: service.create, | ||
- update: service.update, | ||
- remove: service.remove | ||
- }; | ||
- | ||
- service.find = function(params) { | ||
- assert.deepEqual(_.omit(params, 'query'), socketParams, 'Handshake parameters passed on proper position'); | ||
- old.find.apply(this, arguments); | ||
- }; | ||
- | ||
- service.create = function(data, params) { | ||
- assert.deepEqual(_.omit(params, 'query'), socketParams, 'Passed handshake parameters'); | ||
- old.create.apply(this, arguments); | ||
- }; | ||
- | ||
- service.update = function(id, data, params) { | ||
- assert.deepEqual(params, _.extend({ | ||
- query: { | ||
- test: 'param' | ||
- } | ||
- }, socketParams), 'Passed handshake parameters as query'); | ||
- old.update.apply(this, arguments); | ||
- }; | ||
- | ||
- socket.emit('todo::create', {}, {}, function () { | ||
- socket.emit('todo::update', 1, {}, { test: 'param' }, function() { | ||
- _.extend(service, old); | ||
- done(); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- it('missing parameters in socket call works (#88)', function(done) { | ||
- var service = app.service('todo'); | ||
- var old = { | ||
- find: service.find | ||
- }; | ||
- | ||
- service.find = function(params) { | ||
- assert.deepEqual(_.omit(params, 'query'), socketParams, 'Handshake parameters passed on proper position'); | ||
- old.find.apply(this, arguments); | ||
- }; | ||
- | ||
- socket.emit('todo::find', function () { | ||
- _.extend(service, old); | ||
- done(); | ||
- }); | ||
- }); | ||
- | ||
- describe('Services', function() { | ||
- it('invalid arguments cause an error', function (done) { | ||
- socket.emit('todo::find', 1, {}, function(error) { | ||
- assert.equal(error.message, 'Too many arguments for \'find\' service method'); | ||
- done(); | ||
- }); | ||
- }); | ||
- | ||
- describe('CRUD', function () { | ||
- it('::find', function (done) { | ||
- socket.emit('todo::find', {}, function (error, data) { | ||
- verify.find(data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::get', function (done) { | ||
- socket.emit('todo::get', 'laundry', {}, function (error, data) { | ||
- verify.get('laundry', data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::create', function (done) { | ||
- var original = { | ||
- name: 'creating' | ||
- }; | ||
- | ||
- socket.emit('todo::create', original, {}, function (error, data) { | ||
- verify.create(original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::create without parameters and callback', function (done) { | ||
- var original = { | ||
- name: 'creating' | ||
- }; | ||
- | ||
- socket.emit('todo::create', original); | ||
- | ||
- socket.once('todo created', function(data) { | ||
- verify.create(original, data); | ||
- | ||
- done(); | ||
- }); | ||
- }); | ||
- | ||
- it('::update', function (done) { | ||
- var original = { | ||
- name: 'updating' | ||
- }; | ||
- | ||
- socket.emit('todo::update', 23, original, {}, function (error, data) { | ||
- verify.update(23, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::update many', function (done) { | ||
- var original = { | ||
- name: 'updating', | ||
- many: true | ||
- }; | ||
- | ||
- socket.emit('todo::update', null, original, {}, function (error, data) { | ||
- verify.update(null, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::patch', function (done) { | ||
- var original = { | ||
- name: 'patching' | ||
- }; | ||
- | ||
- socket.emit('todo::patch', 25, original, {}, function (error, data) { | ||
- verify.patch(25, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::patch many', function (done) { | ||
- var original = { | ||
- name: 'patching', | ||
- many: true | ||
- }; | ||
- | ||
- socket.emit('todo::patch', null, original, {}, function (error, data) { | ||
- verify.patch(null, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::remove', function (done) { | ||
- socket.emit('todo::remove', 11, {}, function (error, data) { | ||
- verify.remove(11, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::remove many', function (done) { | ||
- socket.emit('todo::remove', null, {}, function (error, data) { | ||
- verify.remove(null, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- describe('Events', function () { | ||
- it('created', function (done) { | ||
- var original = { | ||
- name: 'created event' | ||
- }; | ||
- | ||
- socket.once('todo created', function (data) { | ||
- verify.create(original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.emit('todo::create', original, {}, function () {}); | ||
- }); | ||
- | ||
- it('updated', function (done) { | ||
- var original = { | ||
- name: 'updated event' | ||
- }; | ||
- | ||
- socket.once('todo updated', function (data) { | ||
- verify.update(10, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.emit('todo::update', 10, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('patched', function(done) { | ||
- var original = { | ||
- name: 'patched event' | ||
- }; | ||
- | ||
- socket.once('todo patched', function (data) { | ||
- verify.patch(12, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.emit('todo::patch', 12, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('removed', function (done) { | ||
- socket.once('todo removed', function (data) { | ||
- verify.remove(333, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.emit('todo::remove', 333, {}, function () {}); | ||
- }); | ||
- | ||
- it('custom events', function(done) { | ||
- var service = app.service('todo'); | ||
- var original = { | ||
- name: 'created event' | ||
- }; | ||
- var old = service.create; | ||
- | ||
- service.create = function(data) { | ||
- this.emit('log', { message: 'Custom log event', data: data }); | ||
- service.create = old; | ||
- return old.apply(this, arguments); | ||
- }; | ||
- | ||
- socket.once('todo log', function(data) { | ||
- assert.deepEqual(data, { message: 'Custom log event', data: original }); | ||
- done(); | ||
- }); | ||
- | ||
- socket.emit('todo::create', original, {}, function () {}); | ||
- }); | ||
- }); | ||
- | ||
- describe('Event filtering', function() { | ||
- it('.created', function (done) { | ||
- var service = app.service('todo'); | ||
- var original = { description: 'created event test' }; | ||
- var oldCreated = service.created; | ||
- | ||
- service.created = function(data, params, callback) { | ||
- assert.deepEqual(params, socketParams); | ||
- verify.create(original, data); | ||
- | ||
- callback(null, _.extend({ processed: true }, data)); | ||
- }; | ||
- | ||
- socket.emit('todo::create', original, {}, function() {}); | ||
- | ||
- socket.once('todo created', function (data) { | ||
- service.created = oldCreated; | ||
- // Make sure Todo got processed | ||
- verify.create(_.extend({ processed: true }, original), data); | ||
- done(); | ||
- }); | ||
- }); | ||
- | ||
- it('.updated', function (done) { | ||
- var original = { | ||
- name: 'updated event' | ||
- }; | ||
- | ||
- socket.once('todo updated', function (data) { | ||
- verify.update(10, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.emit('todo::update', 10, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('.removed', function (done) { | ||
- var service = app.service('todo'); | ||
- var oldRemoved = service.removed; | ||
- | ||
- service.removed = function(data, params, callback) { | ||
- assert.deepEqual(params, socketParams); | ||
- | ||
- if(data.id === 23) { | ||
- // Only dispatch with given id | ||
- return callback(null, data); | ||
- } | ||
- | ||
- callback(null, false); | ||
- }; | ||
- | ||
- socket.emit('todo::remove', 1, {}, function() {}); | ||
- socket.emit('todo::remove', 23, {}, function() {}); | ||
- | ||
- socket.on('todo removed', function (data) { | ||
- service.removed = oldRemoved; | ||
- assert.equal(data.id, 23); | ||
- done(); | ||
- }); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- describe('Dynamic Services', function() { | ||
- describe('CRUD', function () { | ||
- it('::find', function (done) { | ||
- socket.emit('tasks::find', {}, function (error, data) { | ||
- verify.find(data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::get', function (done) { | ||
- socket.emit('tasks::get', 'laundry', {}, function (error, data) { | ||
- verify.get('laundry', data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::create', function (done) { | ||
- var original = { | ||
- name: 'creating' | ||
- }; | ||
- | ||
- socket.emit('tasks::create', original, {}, function (error, data) { | ||
- verify.create(original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::update', function (done) { | ||
- var original = { | ||
- name: 'updating' | ||
- }; | ||
- | ||
- socket.emit('tasks::update', 23, original, {}, function (error, data) { | ||
- verify.update(23, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::patch', function (done) { | ||
- var original = { | ||
- name: 'patching' | ||
- }; | ||
- | ||
- socket.emit('tasks::patch', 25, original, {}, function (error, data) { | ||
- verify.patch(25, original, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- | ||
- it('::remove', function (done) { | ||
- socket.emit('tasks::remove', 11, {}, function (error, data) { | ||
- verify.remove(11, data); | ||
- | ||
- done(error); | ||
- }); | ||
- }); | ||
- }); | ||
- | ||
- describe('Events', function () { | ||
- it('created', function (done) { | ||
- var original = { | ||
- name: 'created event' | ||
- }; | ||
- | ||
- socket.once('tasks created', function (data) { | ||
- verify.create(original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.emit('tasks::create', original, {}, function () {}); | ||
- }); | ||
- | ||
- it('updated', function (done) { | ||
- var original = { | ||
- name: 'updated event' | ||
- }; | ||
- | ||
- socket.once('tasks updated', function (data) { | ||
- verify.update(10, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.emit('tasks::update', 10, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('patched', function(done) { | ||
- var original = { | ||
- name: 'patched event' | ||
- }; | ||
- | ||
- socket.once('tasks patched', function (data) { | ||
- verify.patch(12, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.emit('tasks::patch', 12, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('removed', function (done) { | ||
- socket.once('tasks removed', function (data) { | ||
- verify.remove(333, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.emit('tasks::remove', 333, {}, function () {}); | ||
- }); | ||
- }); | ||
- | ||
- describe('Event Filtering', function() { | ||
- it('.created', function (done) { | ||
- var service = app.service('tasks'); | ||
- var original = { description: 'created event test' }; | ||
- var oldCreated = service.created; | ||
- | ||
- service.created = function(data, params, callback) { | ||
- assert.ok(service === this); | ||
- assert.deepEqual(params, socketParams); | ||
- verify.create(original, data); | ||
- | ||
- callback(null, _.extend({ processed: true }, data)); | ||
- }; | ||
- | ||
- socket.emit('tasks::create', original, {}, function() {}); | ||
- | ||
- socket.once('tasks created', function (data) { | ||
- service.created = oldCreated; | ||
- // Make sure Todo got processed | ||
- verify.create(_.extend({ processed: true }, original), data); | ||
- done(); | ||
- }); | ||
- }); | ||
- | ||
- it('.updated', function (done) { | ||
- // TODO this is not testing the right thing | ||
- // but we will get better event filtering in v2 anyway | ||
- var original = { | ||
- name: 'updated event' | ||
- }; | ||
- | ||
- socket.once('tasks updated', function (data) { | ||
- verify.update(10, original, data); | ||
- done(); | ||
- }); | ||
- | ||
- socket.emit('tasks::update', 10, original, {}, function () {}); | ||
- }); | ||
- | ||
- it('.removed', function (done) { | ||
- var service = app.service('tasks'); | ||
- var oldRemoved = service.removed; | ||
- | ||
- service.removed = function(data, params, callback) { | ||
- assert.ok(service === this); | ||
- assert.deepEqual(params, socketParams); | ||
- | ||
- if(data.id === 23) { | ||
- // Only dispatch with given id | ||
- return callback(null, data); | ||
- } | ||
- | ||
- callback(null, false); | ||
- }; | ||
- | ||
- socket.emit('tasks::remove', 1, {}, function() {}); | ||
- socket.emit('tasks::remove', 23, {}, function() {}); | ||
- | ||
- socket.on('tasks removed', function (data) { | ||
- service.removed = oldRemoved; | ||
- assert.equal(data.id, 23); | ||
- done(); | ||
- }); | ||
- }); | ||
- }); | ||
- }); | ||
-}); |
0 comments on commit
f66c7d5