Skip to content

Commit

Permalink
feat(core): create responses from views (#3)
Browse files Browse the repository at this point in the history
* wip: add view type

* feat(core): create responses from views

* chore(tests): AAA
  • Loading branch information
imdhemy authored Dec 26, 2024
1 parent 9bb0692 commit d52a67f
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/core/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import { IApplication, IRouteMetadata, TRouterMethod } from './types';
import Koa from 'koa';
import Router from '@koa/router';
import { getRoutes } from './route';
import { viewMiddleware } from './view-middleware';

export function create(): IApplication {
const app = new Koa();
app.use(viewMiddleware);

const router = new Router();

getRoutes().forEach((route: IRouteMetadata) => {
Expand Down
11 changes: 11 additions & 0 deletions src/core/types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import { Server } from 'http';
import { Middleware } from '@koa/router';
import { Response } from 'koa';

export interface IApplication {
listen(port?: number): Server;
}

export interface View {
status?: Response['status'];
headers?: Response['headers'];
body?: Response['body'];
socket?: Response['socket'];
redirect?: Response['redirect'];
attachment?: Response['attachment'];
}

export interface Handler extends Middleware {
(): Promise<View> | View;
}

export type THttpMethod =
Expand Down
31 changes: 31 additions & 0 deletions src/core/view-middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Context, Next } from 'koa';

export async function viewMiddleware(ctx: Context, next: Next) {
const view = await next();

if (view) {
if (view.status) {
ctx.response.status = view.status;
}

if (view.headers) {
ctx.response.headers = view.headers;
}

if (view.body) {
ctx.response.body = view.body;
}

if (view.socket) {
ctx.response.socket = view.socket;
}

if (view.redirect) {
ctx.response.redirect(view.redirect);
}

if (view.attachment) {
ctx.response.attachment(view.attachment);
}
}
}
63 changes: 63 additions & 0 deletions tests/core/view-middleware.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { Context, Next } from 'koa';
import { viewMiddleware } from '../../src/core/view-middleware';

describe('View Middleware', () => {
let ctx: Context;

beforeEach(() => {
ctx = {
response: {},
} as Context;
});

test('it should set response status', async () => {
const next: Next = vi.fn().mockResolvedValue({ status: 200 });

await viewMiddleware(ctx, next);

expect(ctx.response.status).toBe(200);
});

test('it should set response headers', async () => {
const next: Next = vi.fn().mockResolvedValue({ headers: { 'Content-Type': 'application/json' } });

await viewMiddleware(ctx, next);

expect(ctx.response.headers).toEqual({ 'Content-Type': 'application/json' });
});

test('it should set response body', async () => {
const next: Next = vi.fn().mockResolvedValue({ body: 'Hello, World!' });

await viewMiddleware(ctx, next);

expect(ctx.response.body).toBe('Hello, World!');
});

test('it should set response socket', async () => {
const next: Next = vi.fn().mockResolvedValue({ socket: 'socket' });

await viewMiddleware(ctx, next);

expect(ctx.response.socket).toBe('socket');
});

test('it should redirect if view has redirect', async () => {
const next: Next = vi.fn().mockResolvedValue({ redirect: '/home' });
ctx.response.redirect = vi.fn();

await viewMiddleware(ctx, next);

expect(ctx.response.redirect).toHaveBeenCalledWith('/home');
});

test('it should attach if view has attachment', async () => {
const next: Next = vi.fn().mockResolvedValue({ attachment: 'file.txt' });
ctx.response.attachment = vi.fn();

await viewMiddleware(ctx, next);

expect(ctx.response.attachment).toHaveBeenCalledWith('file.txt');
});
});
2 changes: 2 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export default defineConfig({
exclude: [
...configDefaults.exclude,
'**/playground/**',
'**/tests/**',
'**/types.ts',
],
},
},
Expand Down

0 comments on commit d52a67f

Please sign in to comment.