From 9bebefe53aa41629f00d3b2caf1ef62e31317021 Mon Sep 17 00:00:00 2001 From: Zachary Golba Date: Wed, 18 May 2016 18:53:41 -0400 Subject: [PATCH] fix: middleware functions added in 'beforeAction' not executing --- src/packages/application/index.js | 5 +- src/packages/controller/index.js | 176 +++++++++++++------ test/integration/controller.js | 20 +++ test/test-app/app/controllers/application.js | 6 +- test/test-app/app/controllers/authors.js | 6 + test/test-app/app/controllers/posts.js | 6 + 6 files changed, 165 insertions(+), 54 deletions(-) diff --git a/src/packages/application/index.js b/src/packages/application/index.js index 737dc642..35dadc0f 100644 --- a/src/packages/application/index.js +++ b/src/packages/application/index.js @@ -75,7 +75,8 @@ class Application extends Base { serializer.serializers = serializers; }); - const appController = controllers.get('application').create({ + let appController = controllers.get('application'); + appController = new appController({ store, domain, serializers, @@ -88,7 +89,7 @@ class Application extends Base { if (key !== 'application') { const model = store.modelFor(singularize(key)); - controller = controller.create({ + controller = new controller({ store, model, domain, diff --git a/src/packages/controller/index.js b/src/packages/controller/index.js index 93a8d59b..66cbdc4b 100644 --- a/src/packages/controller/index.js +++ b/src/packages/controller/index.js @@ -1,13 +1,14 @@ import Promise from 'bluebird'; -import Base from '../base'; - import formatInclude from './utils/format-include'; import createPageLinks from './utils/create-page-links'; import action from './decorators/action'; -class Controller extends Base { +const { isArray } = Array; +const { defineProperties } = Object; + +class Controller { store; model; domain; @@ -16,73 +17,146 @@ class Controller extends Base { attributes; serializer; serializers; + parentController; - sort = []; - filter = []; params = []; beforeAction = []; defaultPerPage = 25; - constructor({ model, serializer, parentController, ...props }) { + _sort = []; + _filter = []; + + constructor({ + store, + model, + domain, + serializer, + serializers = new Map(), + parentController + }) { let attributes = []; + let relationships = []; + + if (model && serializer) { + const { primaryKey, attributeNames, relationshipNames } = model; + const { attributes: serializedAttributes } = serializer; + const serializedRelationships = [ + ...serializer.hasOne, + ...serializer.hasMany + ]; + + attributes = attributeNames.filter(attr => { + return attr === primaryKey || serializedAttributes.indexOf(attr) >= 0; + }); + + relationships = relationshipNames.filter(relationship => { + return serializedRelationships.indexOf(relationship) >= 0; + }); + } - super(); + defineProperties(this, { + model: { + value: model, + writable: false, + enumerable: true, + configurable: false + }, - if (model) { - props = { - ...props, - model, - modelName: model.modelName - }; + serializer: { + value: serializer, + writable: false, + enumerable: true, + configurable: false + }, - attributes = model.attributeNames; + store: { + value: store, + writable: false, + enumerable: false, + configurable: false + }, - if (!this.sort.length) { - props.sort = attributes; - } + domain: { + value: domain, + writable: false, + enumerable: false, + configurable: false + }, + + modelName: { + value: model ? model.modelName : null, + writable: false, + enumerable: false, + configurable: false + }, + + attributes: { + value: attributes, + writable: false, + enumerable: false, + configurable: false + }, + + relationships: { + value: relationships, + writable: false, + enumerable: false, + configurable: false + }, + + serializers: { + value: serializers, + writable: false, + enumerable: false, + configurable: false + }, - if (!this.filter.length) { - props.filter = attributes; + parentController: { + value: parentController, + writable: false, + enumerable: false, + configurable: false } + }); + + return this; + } + + get sort() { + const { attributes, _sort: sort } = this; + + return sort.length ? sort : attributes; + } + + set sort(value = []) { + if (isArray(value)) { + this._sort = value; } + } - if (serializer) { - props = { - ...props, - serializer, - - attributes: ['id', ...serializer.attributes] - .filter(attr => { - return attributes.indexOf(attr) >= 0; - }), - - relationships: [ - ...serializer.hasOne, - ...serializer.hasMany - ] - }; + get filter() { + const { attributes, _filter: filter } = this; + + return filter.length ? filter : attributes; + } + + set filter(value = []) { + if (isArray(value)) { + this._filter = value; } + } + + get middleware() { + const { beforeAction, parentController } = this; if (parentController) { - props = { - ...props, - parentController, - - middleware: [ - ...parentController.middleware, - ...this.beforeAction - ] - }; + return [ + ...parentController.middleware, + ...beforeAction + ]; } else { - props = { - ...props, - middleware: this.beforeAction - }; + return beforeAction; } - - this.setProps(props); - - return this; } @action diff --git a/test/integration/controller.js b/test/integration/controller.js index 2f570e00..becfc40d 100644 --- a/test/integration/controller.js +++ b/test/integration/controller.js @@ -465,4 +465,24 @@ describe('Integration: class Controller', () => { expect(subject.status).to.equal(204); }); }); + + describe('Regression: #middleware (https://github.com/postlight/lux/issues/94)', () => { + let subject; + + before(async () => { + subject = await fetch(`${host}/posts`); + }); + + it('includes middleware from it\'s parentController', () => { + expect( + subject.headers.get('X-Powered-By') + ).to.equal('Lux'); + }); + + it('executes middleware from it\'s parentController', () => { + expect( + subject.headers.get('X-Controller') + ).to.equal('Posts'); + }); + }); }); diff --git a/test/test-app/app/controllers/application.js b/test/test-app/app/controllers/application.js index 041f944f..02fdedc9 100644 --- a/test/test-app/app/controllers/application.js +++ b/test/test-app/app/controllers/application.js @@ -1,7 +1,11 @@ import { Controller } from '../../../../dist'; class ApplicationController extends Controller { - + beforeAction = [ + function (req, res) { + res.setHeader('X-Powered-By', 'Lux'); + } + ]; } export default ApplicationController; diff --git a/test/test-app/app/controllers/authors.js b/test/test-app/app/controllers/authors.js index b65fce82..f303b5a0 100644 --- a/test/test-app/app/controllers/authors.js +++ b/test/test-app/app/controllers/authors.js @@ -4,6 +4,12 @@ class AuthorsController extends Controller { params = [ 'name' ]; + + beforeAction = [ + function (req, res) { + res.setHeader('X-Controller', 'Authors'); + } + ]; } export default AuthorsController; diff --git a/test/test-app/app/controllers/posts.js b/test/test-app/app/controllers/posts.js index 3949c07b..99b114c7 100644 --- a/test/test-app/app/controllers/posts.js +++ b/test/test-app/app/controllers/posts.js @@ -6,6 +6,12 @@ class PostsController extends Controller { 'body', 'isPublic' ]; + + beforeAction = [ + function (req, res) { + res.setHeader('X-Controller', 'Posts'); + } + ]; } export default PostsController;