Skip to content
This repository has been archived by the owner on Jan 11, 2022. It is now read-only.

feat: Upgrade to Babel 7; Migrate to Jest #2

Merged
merged 4 commits into from
Mar 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
{
"presets": ["env", "stage-0"],
"plugins": ["transform-decorators-legacy"],
"env": {
"test": {
"plugins": ["istanbul"]
}
}
"presets": ["@babel/env"],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }]
]
}
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
language: node_js
node_js:
- '10'
- '8'
- '6'
after_success: npm run coverage
13 changes: 13 additions & 0 deletions __tests__/__snapshots__/index.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`decorators @controller without basepath 1`] = `"@controller declaration for \`NoBasePath\` is missing a basepath."`;

exports[`decorators mount invalid controller 1`] = `"Invalid requires a router property. Make sure you decorated your class with @controller(basepath)"`;

exports[`requests @post 1`] = `
Object {
"name": "Johnny Tsunami",
}
`;

exports[`utils prettyPath 1`] = `"Path \`noleadingslash\` must begin with a slash."`;
File renamed without changes.
140 changes: 140 additions & 0 deletions __tests__/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import '@babel/polyfill';
import supertest from 'supertest';
import express, { Router } from 'express';
import bodyParser from 'body-parser';
import TestController from './fixture';
import { mount, controller } from '../lib';
import { prettyPath } from '../lib/utils';

const app = express();
const router = new Router();
mount(router, [TestController]);
app.use(bodyParser.json());
app.use(router);
const server = supertest(app);

describe('utils', () => {
test('prettyPath', () => {
expect(prettyPath('/')).toEqual('/');
expect(prettyPath('//dubz//')).toEqual('/dubz');
expect(prettyPath('/trailz/')).toEqual('/trailz');
expect(() => prettyPath('noleadingslash')).toThrowErrorMatchingSnapshot();
});
});

describe('decorators', () => {
test('mount', () => {
const router = new Router();
mount(router, [TestController]);

// hacky
expect(router.stack[0].handle.stack.length).toEqual(8);
});

test('mount invalid controller', () => {
class Invalid {}

const router = new Router();

expect(() => mount(router, [Invalid])).toThrowErrorMatchingSnapshot();
});

test('@controller', () => {
expect(TestController.__router).toBeDefined();
});

test('@controller without routes', () => {
@controller('/')
class NoRoutes {}

expect(NoRoutes.__router).toBeDefined();
});

test('@controller without basepath', () => {
expect(() => {
@controller()
class NoBasePath {}
}).toThrowErrorMatchingSnapshot();
});
});

describe('requests', () => {
test('@param', async () => {
const param = 'jambalaya';
const res = await server.get(`/route-parameter/${param}`);

expect(res.body.param).toEqual(param);
});

test('@route', async () => {
await server.get(`/route`).expect(200);
});

test('@get', async () => {
await server.get('/').expect(200);
});

test('@post', async () => {
const res = await server
.post('/post')
.set('Content-Type', 'application/json')
.send({
name: 'Johnny Tsunami',
})
.expect(200);

expect(res.body).toMatchSnapshot();
});

test('@validate post', async () => {
await server
.post('/validate-post')
.send({})
.expect(400);

await server
.post('/validate-post')
.send({
name: 'Hiyo',
})
.expect(200);
});

test('@validate get', async () => {
const resFailure = await server.get('/validate-get').expect(400);

const resSuccess = await server
.get('/validate-get?include=[1,2,3]')
.send({
name: 'Hiyo',
})
.expect(200);
});

test('@contentType', async () => {
await server
.post('/post')
.set('Content-Type', 'text/plain')
.expect(400);

await server
.post('/post')
.send({
name: 'Hiyo',
})
.set('Content-Type', 'application/json')
.expect(200);
});

test('middlewares', async () => {
const controllerMwRes = await server.get('/controller-middleware');

expect(controllerMwRes.body.inControllerMiddleware).toBeTruthy();
expect(controllerMwRes.body.inRouteMiddleware).toBeFalsy();

const routeMwRes = await server.get('/route-middleware');

expect(routeMwRes.body.inControllerMiddleware).toBeTruthy();
expect(routeMwRes.body.inRouteMiddleware).toBeTruthy();
});
});
6 changes: 4 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@ module.exports.controller = (basepath, middleware = []) => {
if (target.__params) {
target.__params.forEach(({ id, handler }) => {
router.param(id, (req, res, next, ...rest) => {
Promise.resolve(handler.call(target, req, res, next, ...rest)).catch(next);
Promise.resolve(handler.call(target, req, res, next, ...rest)).catch(
next
);
});
});
}

if (target.__routes) {
target.__routes.forEach(route => {
const handler = target.prototype[route.key]
const handler = target.prototype[route.key];
router[route.method](
prettyPath(basepath + route.path),
...middleware,
Expand Down
106 changes: 46 additions & 60 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,62 +1,48 @@
{
"name": "express-marshal",
"version": "0.3.4",
"description": "Helpful decorators to wire up Express controllers",
"license": "MIT",
"repository": "kylealwyn/express-marshal",
"author": {
"name": "Kyle Alwyn",
"email": "kyle.j.alwyn@gmail.com",
"url": "https://kylealwyn.com"
},
"engines": {
"node": ">=6"
},
"scripts": {
"test": "nyc ava",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"coverage:html": "nyc report --reporter=html",
"format": "prettier --single-quote --trailing-comma es5 --write '{lib,test}/**/*.js'"
},
"main": "lib/index.js",
"files": [
"lib"
],
"keywords": [
"express",
"decorators",
"es2015"
],
"ava": {
"files": [
"test/index.js"
],
"source": [
"**/*.{js}"
],
"require": [
"babel-register",
"babel-polyfill"
],
"babel": "inherit"
},
"dependencies": {
"express": "^4.0.0",
"joi": "^11.0.0"
},
"devDependencies": {
"ava": "^0.20.0",
"babel-core": "^6.26.0",
"babel-plugin-istanbul": "^4.1.5",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babel-preset-stage-0": "^6.24.1",
"babel-register": "^6.26.0",
"body-parser": "^1.18.2",
"coveralls": "^3.0.0",
"nyc": "^11.0.0",
"prettier": "^1.10.2",
"supertest": "^3.0.0"
}
"name": "express-marshal",
"version": "0.3.4",
"description": "Helpful decorators to wire up Express controllers",
"license": "MIT",
"repository": "kylealwyn/express-marshal",
"author": {
"name": "Kyle Alwyn",
"email": "kjalwyn@gmail.com",
"url": "https://kylealwyn.com"
},
"engines": {
"node": ">=8"
},
"scripts": {
"test": "jest",
"format": "prettier --single-quote --trailing-comma es5 --write '{lib,__tests__}/**/*.js'"
},
"main": "lib/index.js",
"files": [
"lib"
],
"keywords": [
"express",
"decorators",
"es2015"
],
"dependencies": {
"express": "^4.16.4",
"joi": "^14.3.1"
},
"devDependencies": {
"@babel/core": "^7.3.4",
"@babel/plugin-proposal-decorators": "^7.3.0",
"@babel/polyfill": "^7.2.5",
"@babel/preset-env": "^7.3.4",
"@babel/register": "^7.0.0",
"body-parser": "^1.18.3",
"coveralls": "^3.0.3",
"jest": "^24.5.0",
"prettier": "^1.16.4",
"supertest": "^3.4.2"
},
"jest": {
"testMatch": ["<rootDir>/__tests__/index.js"],
"collectCoverageFrom": ["<rootDir>/lib/**/*"]
}
}
Loading