Skip to content

Commit

Permalink
feat: export controller function's FULLPATH (#131) (#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 committed Nov 29, 2017
1 parent da4ba17 commit 4979b98
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 3 deletions.
9 changes: 6 additions & 3 deletions lib/loader/mixin/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const path = require('path');
const is = require('is-type-of');
const utility = require('utility');
const utils = require('../../utils');
const FULLPATH = require('../file_loader').FULLPATH;

module.exports = {

Expand Down Expand Up @@ -67,6 +68,7 @@ function wrapClass(Controller) {
// prevent to override sub method
if (is.function(d.value) && !ret.hasOwnProperty(key)) {
ret[key] = methodToMiddleware(Controller, key);
ret[key][FULLPATH] = Controller.prototype.fullPath + '#' + Controller.name + '.' + key + '()';
}
}
proto = Object.getPrototypeOf(proto);
Expand All @@ -85,18 +87,19 @@ function wrapClass(Controller) {
}

// wrap the method of the object, method can receive ctx as it's first argument
function wrapObject(obj, path) {
function wrapObject(obj, path, prefix) {
const keys = Object.keys(obj);
const ret = {};
for (const key of keys) {
if (is.function(obj[key])) {
const names = utility.getParamNames(obj[key]);
if (names[0] === 'next') {
throw new Error(`controller \`${key}\` should not use next as argument from file ${path}`);
throw new Error(`controller \`${prefix || ''}${key}\` should not use next as argument from file ${path}`);
}
ret[key] = functionToMiddleware(obj[key]);
ret[key][FULLPATH] = `${path}#${prefix || ''}${key}()`;
} else if (is.object(obj[key])) {
ret[key] = wrapObject(obj[key], path);
ret[key] = wrapObject(obj[key], path, `${prefix || ''}${key}.`);
}
}
return ret;
Expand Down
11 changes: 11 additions & 0 deletions test/fixtures/controller-app/app/controller/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ module.exports = {
ctx.body = yield ctx.service.home.info();
},

subObject: {
* callGeneratorFunction() {
this.body = yield this.service.home.info();
},
subSubObject: {
* callGeneratorFunction() {
this.body = yield this.service.home.info();
},
},
},

callAsyncFunction() {
return __awaiter(this, void 0, void 0, function* () {
this.body = yield this.service.home.info();
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/controller-app/app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ module.exports = app => {

app.get('/object-function', 'object.callFunction');
app.get('/object-generator-function', 'object.callGeneratorFunction');
app.get('/subObject-generator-function', 'object.subObject.callGeneratorFunction');
app.get('/subSubObject-generator-function', 'object.subObject.subSubObject.callGeneratorFunction');
app.get('/object-generator-function-arg', 'object.callGeneratorFunctionWithArg');
app.get('/object-async-function', 'object.callAsyncFunction');
app.get('/object-async-function-arg', 'object.callAsyncFunctionWithArg');
Expand Down
86 changes: 86 additions & 0 deletions test/loader/mixin/load_controller.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ describe('test/loader/mixin/load_controller.test.js', () => {
describe('when controller is generator function', () => {
it('should use it as middleware', () => {
assert(app.controller.generatorFunction);
assert(app.controller.generatorFunction.name === 'objectControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/generator_function.js');
assert(app.controller.generatorFunction[app.loader.FileLoader.FULLPATH] === classFilePath);

return request(app.callback())
.get('/generator-function')
Expand All @@ -49,6 +52,10 @@ describe('test/loader/mixin/load_controller.test.js', () => {
describe('when controller is object', () => {
it('should define method which is function', () => {
assert(app.controller.object.callFunction);
assert(app.controller.object.callFunction.name === 'objectControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/object.js');
assert(app.controller.object.callFunction[app.loader.FileLoader.FULLPATH] ===
classFilePath + '#callFunction()');

return request(app.callback())
.get('/object-function')
Expand All @@ -58,15 +65,49 @@ describe('test/loader/mixin/load_controller.test.js', () => {

it('should define method which is generator function', () => {
assert(app.controller.object.callGeneratorFunction);
assert(app.controller.object.callGeneratorFunction.name === 'objectControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/object.js');
assert(app.controller.object.callGeneratorFunction[app.loader.FileLoader.FULLPATH] ===
classFilePath + '#callGeneratorFunction()');

return request(app.callback())
.get('/object-generator-function')
.expect(200)
.expect('done');
});

it('should define method on subObject', () => {
assert(app.controller.object.subObject.callGeneratorFunction);
assert(app.controller.object.subObject.callGeneratorFunction.name === 'objectControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/object.js');
assert(app.controller.object.subObject.callGeneratorFunction[app.loader.FileLoader.FULLPATH] ===
classFilePath + '#subObject.callGeneratorFunction()');

return request(app.callback())
.get('/subObject-generator-function')
.expect(200)
.expect('done');
});

it('should define method on subObject.subSubObject', () => {
assert(app.controller.object.subObject.subSubObject.callGeneratorFunction);
assert(app.controller.object.subObject.subSubObject.callGeneratorFunction.name === 'objectControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/object.js');
assert(app.controller.object.subObject.subSubObject.callGeneratorFunction[app.loader.FileLoader.FULLPATH] ===
classFilePath + '#subObject.subSubObject.callGeneratorFunction()');

return request(app.callback())
.get('/subSubObject-generator-function')
.expect(200)
.expect('done');
});

it('should define method which is generator function with argument', () => {
assert(app.controller.object.callGeneratorFunctionWithArg);
assert(app.controller.object.callGeneratorFunctionWithArg.name === 'objectControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/object.js');
assert(app.controller.object.callGeneratorFunctionWithArg[app.loader.FileLoader.FULLPATH] ===
classFilePath + '#callGeneratorFunctionWithArg()');

return request(app.callback())
.get('/object-generator-function-arg')
Expand All @@ -76,6 +117,10 @@ describe('test/loader/mixin/load_controller.test.js', () => {

it('should define method which is async function', () => {
assert(app.controller.object.callAsyncFunction);
assert(app.controller.object.callAsyncFunction.name === 'objectControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/object.js');
assert(app.controller.object.callAsyncFunction[app.loader.FileLoader.FULLPATH] ===
classFilePath + '#callAsyncFunction()');

return request(app.callback())
.get('/object-async-function')
Expand All @@ -85,6 +130,10 @@ describe('test/loader/mixin/load_controller.test.js', () => {

it('should define method which is async function with argument', () => {
assert(app.controller.object.callAsyncFunctionWithArg);
assert(app.controller.object.callAsyncFunctionWithArg.name === 'objectControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/object.js');
assert(app.controller.object.callAsyncFunctionWithArg[app.loader.FileLoader.FULLPATH] ===
classFilePath + '#callAsyncFunctionWithArg()');

return request(app.callback())
.get('/object-async-function-arg')
Expand Down Expand Up @@ -116,6 +165,10 @@ describe('test/loader/mixin/load_controller.test.js', () => {
describe('when controller is class', () => {
it('should define method which is function', () => {
assert(app.controller.class.callFunction);
assert(app.controller.class.callFunction.name === 'classControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/class.js');
assert(app.controller.class.callFunction[app.loader.FileLoader.FULLPATH] ===
`${classFilePath}#HomeController.callFunction()`);

return request(app.callback())
.get('/class-function')
Expand All @@ -125,6 +178,10 @@ describe('test/loader/mixin/load_controller.test.js', () => {

it('should define method which is generator function', () => {
assert(app.controller.class.callGeneratorFunction);
assert(app.controller.class.callGeneratorFunction.name === 'classControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/class.js');
assert(app.controller.class.callGeneratorFunction[app.loader.FileLoader.FULLPATH] ===
`${classFilePath}#HomeController.callGeneratorFunction()`);

return request(app.callback())
.get('/class-generator-function')
Expand All @@ -134,6 +191,10 @@ describe('test/loader/mixin/load_controller.test.js', () => {

it('should define method which is generator function with ctx', () => {
assert(app.controller.class.callGeneratorFunctionWithArg);
assert(app.controller.class.callGeneratorFunctionWithArg.name === 'classControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/class.js');
assert(app.controller.class.callGeneratorFunctionWithArg[app.loader.FileLoader.FULLPATH] ===
`${classFilePath}#HomeController.callGeneratorFunctionWithArg()`);

return request(app.callback())
.get('/class-generator-function-arg')
Expand All @@ -143,6 +204,10 @@ describe('test/loader/mixin/load_controller.test.js', () => {

it('should define method which is async function', () => {
assert(app.controller.class.callAsyncFunction);
assert(app.controller.class.callAsyncFunction.name === 'classControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/class.js');
assert(app.controller.class.callAsyncFunction[app.loader.FileLoader.FULLPATH] ===
`${classFilePath}#HomeController.callAsyncFunction()`);

return request(app.callback())
.get('/class-async-function')
Expand All @@ -152,6 +217,10 @@ describe('test/loader/mixin/load_controller.test.js', () => {

it('should define method which is async function with ctx', () => {
assert(app.controller.class.callAsyncFunctionWithArg);
assert(app.controller.class.callAsyncFunctionWithArg.name === 'classControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/class.js');
assert(app.controller.class.callAsyncFunctionWithArg[app.loader.FileLoader.FULLPATH] ===
`${classFilePath}#HomeController.callAsyncFunctionWithArg()`);

return request(app.callback())
.get('/class-async-function-arg')
Expand All @@ -160,13 +229,24 @@ describe('test/loader/mixin/load_controller.test.js', () => {
});

it('should load class that is inherited from its super class', () => {
assert(app.controller.classInherited.callInheritedFunction.name === 'classControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/class_inherited.js');
assert(app.controller.classInherited.callInheritedFunction[app.loader.FileLoader.FULLPATH] ===
`${classFilePath}#HomeController.callInheritedFunction()`);

return request(app.callback())
.get('/class-inherited-function')
.expect(200)
.expect('inherited');
});

it('should load inherited class without overriding its own function', () => {
assert(app.controller.classInherited.callOverriddenFunction);
assert(app.controller.classInherited.callOverriddenFunction.name === 'classControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/class_inherited.js');
assert(app.controller.classInherited.callOverriddenFunction[app.loader.FileLoader.FULLPATH] ===
`${classFilePath}#HomeController.callOverriddenFunction()`);

return request(app.callback())
.get('/class-overridden-function')
.expect(200)
Expand All @@ -182,6 +262,12 @@ describe('test/loader/mixin/load_controller.test.js', () => {
});

it('should load class that is wrapped by function', () => {
assert(app.controller.classWrapFunction.get);
assert(app.controller.classWrapFunction.get.name === 'classControllerMiddleware');
const classFilePath = path.join(app.baseDir, 'app/controller/class_wrap_function.js');
assert(app.controller.classWrapFunction.get[app.loader.FileLoader.FULLPATH] ===
`${classFilePath}#HomeController.get()`);

return request(app.callback())
.get('/class-wrap-function')
.expect(200)
Expand Down

0 comments on commit 4979b98

Please sign in to comment.