diff --git a/server/integration/http/routes/src/app.controller.ts b/server/integration/http/routes/src/app.controller.ts index 2299e9f..08d21b2 100644 --- a/server/integration/http/routes/src/app.controller.ts +++ b/server/integration/http/routes/src/app.controller.ts @@ -1,5 +1,5 @@ import { Controller, HttpStatus } from '@server'; -import { Delete, Get, Head, Options, Patch, Post, Put } from '@server/http'; +import { Delete, Get, Head, Options, Patch, Post, Put, Render } from '@server/http'; @Controller() export class AppController { @@ -28,7 +28,24 @@ export class AppController { } @Put('put', HttpStatus.ACCEPTED) - Put() { + put() { return 'put'; } + + @Get('*', 404) + status404() { + return 'not-found'; + } + + @Get('render') + @Render('view') + tryRender() { + return { message: 'Hello World' }; + } + + @Get('render-missing') + @Render('missing') + tryRenderMissing() { + return { message: 'Hello World' }; + } } diff --git a/server/integration/http/routes/src/view.ejs b/server/integration/http/routes/src/view.ejs new file mode 100644 index 0000000..efeb4b2 --- /dev/null +++ b/server/integration/http/routes/src/view.ejs @@ -0,0 +1,21 @@ + + + + + + + + POST + + + + <%= message %> + + + diff --git a/server/integration/http/routes/test/express.spec.ts b/server/integration/http/routes/test/express.spec.ts index c8e5330..26651f5 100644 --- a/server/integration/http/routes/test/express.spec.ts +++ b/server/integration/http/routes/test/express.spec.ts @@ -1,6 +1,7 @@ import { Application, HttpStatus, Module } from '@server'; import { ExpressAdapter } from '@server/express'; import { HttpModule } from '@server/http'; +import { join } from 'path'; import * as request from 'supertest'; import { AppModule } from '../src/app.module'; @@ -21,6 +22,9 @@ describe('Express :: Routes', () => { app = await Application.create(TestModule); module = await app.inject(HttpModule); + module.set('view engine', 'ejs'); + module.set('views', join(__dirname, '..', 'src')); + await module.listen(); }); @@ -67,4 +71,30 @@ describe('Express :: Routes', () => { .put('/put') .expect(HttpStatus.ACCEPTED, 'put'); }); + + it('registers `*` request', async () => { + return request(module.getHttpServer()) + .get('/does-not-exist') + .expect(HttpStatus.NOT_FOUND, 'not-found'); + }); + + describe('Render', () => { + it('renders view', async () => { + return request(module.getHttpServer()) + .get('/render') + .expect((req) => { + expect(req.status).toBe(HttpStatus.OK); + expect(req.text).toContain('Hello World'); + }); + }); + + it('renders non-existing view', async () => { + return request(module.getHttpServer()) + .get('/render-missing') + .expect((req) => { + expect(req.status).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(req.body.message).toBeDefined(); + }); + }); + }); }); diff --git a/server/integration/http/routes/test/fastify.spec.ts b/server/integration/http/routes/test/fastify.spec.ts index 1d0f86a..f477e6b 100644 --- a/server/integration/http/routes/test/fastify.spec.ts +++ b/server/integration/http/routes/test/fastify.spec.ts @@ -1,6 +1,8 @@ +import * as FastifyView from '@fastify/view'; import { Application, HttpStatus, Module } from '@server'; import { FastifyAdapter } from '@server/fastify'; import { HttpModule } from '@server/http'; +import { join } from 'path'; import * as request from 'supertest'; import { AppModule } from '../src/app.module'; @@ -21,6 +23,13 @@ describe('Fastify :: Routes', () => { app = await Application.create(TestModule); module = await app.inject(HttpModule); + module.use(FastifyView, { + engine: { + ejs: require('ejs'), + }, + root: join(__dirname, '..', 'src'), + }); + await module.listen(); }); @@ -67,4 +76,30 @@ describe('Fastify :: Routes', () => { .put('/put') .expect(HttpStatus.ACCEPTED, 'put'); }); + + it('registers `*` request', async () => { + return request(module.getHttpServer()) + .get('/does-not-exist') + .expect(HttpStatus.NOT_FOUND, 'not-found'); + }); + + describe('Render', () => { + it('renders view', async () => { + return request(module.getHttpServer()) + .get('/render') + .expect((req) => { + expect(req.status).toBe(HttpStatus.OK); + expect(req.text).toContain('Hello World'); + }); + }); + + it('renders non-existing view', async () => { + return request(module.getHttpServer()) + .get('/render-missing') + .expect((req) => { + expect(req.status).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(req.body.message).toBeDefined(); + }); + }); + }); }); diff --git a/server/integration/http/routes/test/koa.spec.ts b/server/integration/http/routes/test/koa.spec.ts index 1fad37f..6bb1d8a 100644 --- a/server/integration/http/routes/test/koa.spec.ts +++ b/server/integration/http/routes/test/koa.spec.ts @@ -1,6 +1,8 @@ import { Application, HttpStatus, Module } from '@server'; import { HttpModule } from '@server/http'; import { KoaAdapter } from '@server/koa'; +import * as koaViews from 'koa-views'; +import { join } from 'path'; import * as request from 'supertest'; import { AppModule } from '../src/app.module'; @@ -21,6 +23,11 @@ describe('Koa :: Routes', () => { app = await Application.create(TestModule); module = await app.inject(HttpModule); + module.use(koaViews(join(__dirname, '..', 'src'), { + autoRender: false, + extension: 'ejs', + })); + await module.listen(); }); @@ -67,4 +74,30 @@ describe('Koa :: Routes', () => { .put('/put') .expect(HttpStatus.ACCEPTED, 'put'); }); + + it('registers `*` request', async () => { + return request(module.getHttpServer()) + .get('/does-not-exist') + .expect(HttpStatus.NOT_FOUND, 'not-found'); + }); + + describe('Render', () => { + it('renders view', async () => { + return request(module.getHttpServer()) + .get('/render') + .expect((req) => { + expect(req.status).toBe(HttpStatus.OK); + expect(req.text).toContain('Hello World'); + }); + }); + + it('renders non-existing view', async () => { + return request(module.getHttpServer()) + .get('/render-missing') + .expect((req) => { + expect(req.status).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(req.body.message).toBeDefined(); + }); + }); + }); }); diff --git a/server/package-lock.json b/server/package-lock.json index c67abc1..4ab8701 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,12 +1,12 @@ { "name": "@decorators/server", - "version": "1.0.0-beta.12", + "version": "1.0.0-beta.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@decorators/server", - "version": "1.0.0-beta.12", + "version": "1.0.0-beta.13", "license": "MIT", "devDependencies": { "@decorators/di": "../di", diff --git a/server/package.json b/server/package.json index 3673c7c..e2984ff 100644 --- a/server/package.json +++ b/server/package.json @@ -142,5 +142,5 @@ ] } }, - "version": "1.0.0-beta.12" + "version": "1.0.0-beta.13" } diff --git a/server/src/platforms/fastify/fastify-adapter.ts b/server/src/platforms/fastify/fastify-adapter.ts index 3556c1a..3375048 100644 --- a/server/src/platforms/fastify/fastify-adapter.ts +++ b/server/src/platforms/fastify/fastify-adapter.ts @@ -40,7 +40,9 @@ export class FastifyAdapter implements HttpApplicationAdapter { render(_response: Fastify.FastifyReply, template: string, message: object) { return new Promise((resolve, reject) => (this.app as any).view(template, message, - (err: Error, html: string) => err ? reject(err) : resolve(html), + (err: Error, html: string) => err || html?.['stack'] + ? reject(new Error((err || html).toString())) + : resolve(html), )); } diff --git a/server/src/platforms/koa/koa-adapter.ts b/server/src/platforms/koa/koa-adapter.ts index 2ee0915..bfb9d81 100644 --- a/server/src/platforms/koa/koa-adapter.ts +++ b/server/src/platforms/koa/koa-adapter.ts @@ -42,9 +42,13 @@ export class KoaAdapter implements HttpApplicationAdapter { } async render(response: Koa.Response, template: string, message: object) { - const html = await response.ctx.render(template, message); + try { + const html = await response.ctx.render(template, message); - return html as unknown as string; + return html as unknown as string; + } catch (err) { + throw new Error(err.message); + } } reply(response: Koa.Response, message: unknown, statusCode?: number) {