Skip to content

Commit

Permalink
generate more tests, add uuid validation
Browse files Browse the repository at this point in the history
  • Loading branch information
icepeng committed Feb 14, 2017
1 parent 6439334 commit db49e09
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 15 deletions.
8 changes: 4 additions & 4 deletions generators/api/templates/repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ export class <%= interfaceName %>Repo {
empty = () =>
this.db.none('TRUNCATE TABLE "<%= tableName %>" CASCADE');

add = (params: <%= interfaceName %>): Promise<string> =>
add = (params: <%= interfaceName %>): Promise<<%= interfaceName %>> =>
this.db.one('INSERT INTO "<%= tableName %>"(<%= columns %>) '
+ 'VALUES(<%= values %>) '
+ 'RETURNING id', params, (<%= modelName %>: <%= interfaceName %>) => <%= modelName %>.id)
+ 'RETURNING *', params, (<%= modelName %>: <%= interfaceName %>) => <%= modelName %>)

remove = (id: string): Promise<any> =>
this.db.result('DELETE FROM "<%= tableName %>" WHERE id = $1', id, (r: any) => r.rowCount);

edit = (id: string, params: <%= interfaceName %>): Promise<any> => {
params.id = id;
return this.db.result('UPDATE <%= tableName %> '
return this.db.oneOrNone('UPDATE "<%= tableName %>" '
+ 'SET (<%= columns %>) = '
+ '(<%= values %>) '
+ 'WHERE id = ${id}' , params, (r: any) => r.rowCount);
+ 'WHERE id = ${id} RETURNING *' , params, (<%= modelName %>: <%= interfaceName %>) => <%= modelName %>);
}

find = (id: string): Promise<<%= interfaceName %>> =>
Expand Down
28 changes: 19 additions & 9 deletions generators/api/templates/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ export class <%= interfaceName %>Router {

public async add(req: Request, res: Response, next: NextFunction) {
try {
const <%= modelName %>: <%= interfaceName %> = req.body;
await Model.<%= modelName %>.add(<%= modelName %>);
const input: <%= interfaceName %> = req.body;
const <%= modelName %> = await Model.<%= modelName %>.add(input);
res.status(200).send({
message: 'Success',
<%= modelName %>,
});
} catch (err) {
next(err);
Expand All @@ -62,7 +63,7 @@ export class <%= interfaceName %>Router {
message: 'Success',
});
} else {
res.status(400).send({
res.status(404).send({
message: 'No <%= modelName %> found with the given id.',
});
}
Expand All @@ -74,13 +75,15 @@ export class <%= interfaceName %>Router {
public async edit(req: Request, res: Response, next: NextFunction) {
try {
const query = req.params.id;
const <%= modelName %>: <%= interfaceName %> = req.body;
if (await Model.<%= modelName %>.edit(query, <%= modelName %>)) {
const input: <%= interfaceName %> = req.body;
const <%= modelName %> = await Model.<%= modelName %>.edit(query, input);
if (<%= modelName %>) {
res.status(200).send({
message: 'Success',
<%= modelName %>,
});
} else {
res.status(400).send({
res.status(404).send({
message: 'No <%= modelName %> found with the given id.',
});
}
Expand All @@ -97,12 +100,19 @@ export class <%= interfaceName %>Router {
next();
}

private uuidValidator(req: Request, res: Response, next: NextFunction) {
const id = req.params.id;
const schema = Joi.string().guid();
Joi.assert(id, schema);
next();
}

run() {
this.router.get('/', this.getAll);
this.router.get('/:id', this.getOne);
this.router.get('/:id', this.uuidValidator, this.getOne);
this.router.post('/', this.inputValidator, this.add);
this.router.delete('/:id', this.remove);
this.router.put('/:id', this.inputValidator, this.edit);
this.router.delete('/:id', this.uuidValidator, this.remove);
this.router.put('/:id', [this.uuidValidator, this.inputValidator], this.edit);
}

}
Expand Down
168 changes: 168 additions & 0 deletions generators/api/templates/spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import * as mocha from 'mocha';
import * as chai from 'chai';
import chaiHttp = require('chai-http');
import { Model, <%= interfaceName %> } from '../../model';

import app from '../';

chai.use(chaiHttp);
const expect = chai.expect;

describe('GET api/v1/<%= pluralName %>', () => {
before(() => {
return Model.query('BEGIN')
.then(() => chai.request(app)
.post('/api/v1/<%= pluralName %>')
.send({
// add test input here
}));
});

it('responds with JSON array', () => {
return chai.request(app).get('/api/v1/<%= pluralName %>')
Expand All @@ -30,4 +39,163 @@ describe('GET api/v1/<%= pluralName %>', () => {
});
});

after(() => {
return Model.query('ROLLBACK');
});
});

describe('GET api/v1/<%= pluralName %>/:id', () => {
let <%= modelName %>ID: string;

before(() => {
return Model.query('BEGIN')
.then(() => chai.request(app)
.post('/api/v1/<%= pluralName %>')
.send({
// add test input here
})
.then(res => {
<%= modelName %>ID = res.body.<%= modelName %>.id;
}));
});

it('responds with JSON object', () => {
return chai.request(app).get(`/api/v1/<%= pluralName %>/${<%= modelName %>ID}`)
.then(res => {
expect(res.status).to.equal(200);
expect(res).to.be.json;
expect(res.body.<%= modelName %>).to.be.an('object');
});
});

it('should include <%= interfaceName %>', () => {
return chai.request(app).get(`/api/v1/<%= pluralName %>/${<%= modelName %>ID}`)
.then(res => {
const <%= interfaceName %> = res.body.<%= modelName %>;
expect(<%= interfaceName %>).to.exist;
expect(<%= interfaceName %>).to.have.all.keys([
'id',
'create_time',
<%- keys %> ]);
});
});

after(() => {
return Model.query('ROLLBACK');
});
});

describe('POST api/v1/<%= pluralName %>', () => {
before(() => {
return Model.query('BEGIN');
});

it('responds with JSON object', () => {
return chai.request(app).post('/api/v1/<%= pluralName %>').send({
// add test input here
}).then(res => {
expect(res.status).to.equal(200);
expect(res).to.be.json;
expect(res.body.<%= modelName %>).to.be.an('object');
});
});

it('should include <%= interfaceName %>', () => {
return chai.request(app).post('/api/v1/<%= pluralName %>').send({
// add test input here
}).then(res => {
const <%= interfaceName %> = res.body.<%= modelName %>;
expect(<%= interfaceName %>).to.exist;
expect(<%= interfaceName %>).to.have.all.keys([
'id',
'create_time',
<%- keys %> ]);
});
});

after(() => {
return Model.query('ROLLBACK');
});
});

describe('DELETE api/v1/<%= pluralName %>/:id', () => {
let <%= modelName %>ID: string;

beforeEach(() => {
return Model.query('BEGIN')
.then(() => chai.request(app)
.post('/api/v1/<%= pluralName %>')
.send({
// add test input here
})
.then(res => {
<%= modelName %>ID = res.body.<%= modelName %>.id;
}));
});

it('responds with 200', () => {
return chai.request(app).del(`/api/v1/<%= pluralName %>/${<%= modelName %>ID}`)
.then(res => {
expect(res.status).to.equal(200);
expect(res).to.be.json;
});
});

it('should return 404 when <%= modelName %> not exist', () => {
return chai.request(app).del(`/api/v1/<%= pluralName %>/ae1ba13d-867e-474e-ab00-8f3762ecf00b`)
.then(res => {
throw res;
})
.catch(res => {
expect(res.status).to.equal(404);
});
});

afterEach(() => {
return Model.query('ROLLBACK');
});
});

describe('PUT api/v1/<%= pluralName %>/:id', () => {
let <%= modelName %>ID: string;

before(() => {
return Model.query('BEGIN')
.then(() => chai.request(app)
.post('/api/v1/<%= pluralName %>')
.send({
// add test input here
})
.then(res => {
<%= modelName %>ID = res.body.<%= modelName %>.id;
}));
});

it('responds with JSON object', () => {
return chai.request(app).put(`/api/v1/<%= pluralName %>/${<%= modelName %>ID}`).send({
// add test input here
}).then(res => {
expect(res.status).to.equal(200);
expect(res).to.be.json;
expect(res.body.<%= modelName %>).to.be.an('object');
});
});

it('should include edited <%= modelName %>', () => {
return chai.request(app).put(`/api/v1/<%= pluralName %>/${<%= modelName %>ID}`).send({
// add test input here
}).then(res => {
const <%= interfaceName %> = res.body.<%= modelName %>;
expect(<%= interfaceName %>).to.exist;
expect(<%= interfaceName %>).to.have.all.keys([
'id',
'create_time',
<%- keys %> ]);
// check edited values here
});
});

after(() => {
return Model.query('ROLLBACK');
});
});
3 changes: 3 additions & 0 deletions generators/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ module.exports = Generator.extend({
this.fs.copy(
this.templatePath('gulpfile.js'),
this.destinationPath('gulpfile.js'));
this.fs.copy(
this.templatePath('.editorconfig'),
this.destinationPath('.editorconfig'));
this.fs.copy(
this.templatePath('tsconfig.json'),
this.destinationPath('tsconfig.json'));
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "generator-express-pgp-typescript",
"version": "0.1.3",
"version": "0.2.0-alpha.1",
"description": "express pg-promise generator with typescript",
"homepage": "",
"author": {
Expand All @@ -25,7 +25,6 @@
"eslint-plugin-jsx-a11y": "^3.0.2 || ^4.0.0",
"eslint-plugin-react": "^6.9.0",
"fs-extra": "^2.0.0",
"sinon": "^1.17.7",
"yeoman-generator": "^1.0.0",
"yosay": "^1.2.1"
},
Expand All @@ -45,6 +44,7 @@
"gulp-mocha": "^3.0.1",
"gulp-nsp": "^2.1.0",
"gulp-plumber": "^1.0.0",
"sinon": "^1.17.7",
"yeoman-assert": "^2.2.1",
"yeoman-test": "^1.6.0"
},
Expand Down
1 change: 1 addition & 0 deletions test/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ describe('generator-express-pgp-typescript:app', () => {
'tslint.json',
'package.json',
'yarn.lock',
'.editorconfig',
]);
});
});

0 comments on commit db49e09

Please sign in to comment.