tests(middleware-cors): improve mocks, add headers specs
MODIFY
packages/middleware-cors/src/middleware.spec.ts
packages/middleware-cors/src/middleware.spec.ts
-import { HttpRequest, HttpResponse } from '@marblejs/core';
+import { HttpMethod, HttpRequest, HttpResponse } from '@marblejs/core';
import { of } from 'rxjs';
import { cors$ } from './middleware';
-import { OutgoingMessage } from 'http';
describe('CORS middleware', () => {
+ const createMockResponse = () =>
+ (({
+ writeHead: jest.fn(),
+ setHeader: jest.fn(),
+ getHeader: jest.fn(),
+ end: jest.fn(),
+ } as unknown) as HttpResponse);
+
+ const createMockRequest = (
+ method: HttpMethod = 'GET',
+ headers: any = { origin: 'fake-origin' },
+ ) =>
+ (({
+ method,
+ headers: { ...headers },
+ } as unknown) as HttpRequest);
+
describe('Access-Control-Allow-Origin', () => {
- test('cors$ allow if it matches given allowed string', done => {
+ describe('String arg', () => {
+ test('should allow wildcard', done => {
// given
- const allowOrigin = 'fake-origin';
- const mockedRequest = ({
- headers: { origin: allowOrigin },
- } as unknown) as HttpRequest;
+ const allowOrigin = '*';
+ const req = createMockRequest();
- const res = (new OutgoingMessage() as unknown) as HttpResponse;
- const spy = jest.spyOn(res, 'setHeader');
- const req$ = of(mockedRequest);
+ const res = createMockResponse();
+ const req$ = of(req);
// when
- const middleware$ = cors$({ origin: allowOrigin })(req$, res, undefined);
+ const middleware$ = cors$({ origin: allowOrigin })(
+ req$,
+ res,
+ undefined,
+ );
// then
middleware$.subscribe(
() => {
- expect(spy).toBeCalledWith(
+ expect(res.setHeader).toBeCalledWith(
'Access-Control-Allow-Origin',
allowOrigin,
);
- expect(res.getHeader('Access-Control-Allow-Origin')).toEqual(
- allowOrigin,
+ done();
+ },
+ err => {
+ fail(err);
+ done();
+ },
+ );
+ });
+
+ test('should allow if it matches given allowed string', done => {
+ // given
+ const origin = 'fake-origin';
+ const req = createMockRequest('GET', { origin });
+
+ const res = createMockResponse();
+ const req$ = of(req);
+
+ // when
+ const middleware$ = cors$({
+ origin,
+ })(req$, res, undefined);
+
+ // then
+ middleware$.subscribe(
+ () => {
+ expect(res.setHeader).toBeCalledWith(
+ 'Access-Control-Allow-Origin',
+ 'fake-origin',
);
done();
},
@@ -39,26 +83,27 @@ describe('CORS middleware', () => {
);
});
- test("cors$ disallow if it doesn't match given allowed string", done => {
+ test("should disallow if it doesn't match given allowed string", done => {
// given
- const reqOrigin = 'fake-origin';
+ const origin = 'fake-origin';
const allowOrigin = 'fake-allowed-origin';
- const mockedRequest = ({
- headers: { origin: reqOrigin },
- } as unknown) as HttpRequest;
+ const mockedRequest = createMockRequest('GET', { origin });
- const res = (new OutgoingMessage() as unknown) as HttpResponse;
- const spy = jest.spyOn(res, 'setHeader');
+ const res = createMockResponse();
const req$ = of(mockedRequest);
// when
- const middleware$ = cors$({ origin: allowOrigin })(req$, res, undefined);
+ const middleware$ = cors$({
+ origin: allowOrigin,
+ })(req$, res, undefined);
// then
middleware$.subscribe(
() => {
- expect(spy).not.toBeCalled();
- expect(res.hasHeader('Access-Control-Allow-Origin')).toBeFalsy();
+ expect(res.setHeader).not.toBeCalledWith(
+ 'Access-Control-Allow-Origin',
+ 'fake-origin',
+ );
done();
},
err => {
@@ -67,27 +112,30 @@ describe('CORS middleware', () => {
},
);
});
+ });
- test('cors$ allow if it matches at least one allowed origins', done => {
+ describe('Array arg', () => {
+ test("should disallow if it doesn't match any allowed origins", done => {
// given
- const reqOrigin = 'fake-allowed-origin';
+ const origin = 'fake-origin';
const allowOrigin = ['fake-allowed-origin', 'other-fake-origin'];
- const mockedRequest = ({
- headers: { origin: reqOrigin },
- } as unknown) as HttpRequest;
+ const req = createMockRequest('GET', { origin });
- const res = (new OutgoingMessage() as unknown) as HttpResponse;
- const spy = jest.spyOn(res, 'setHeader');
- const req$ = of(mockedRequest);
+ const res = createMockResponse();
+ const req$ = of(req);
// when
- const middleware$ = cors$({ origin: allowOrigin })(req$, res, undefined);
+ const middleware$ = cors$({
+ origin: allowOrigin,
+ })(req$, res, undefined);
// then
middleware$.subscribe(
() => {
- expect(spy).toBeCalledWith('Access-Control-Allow-Origin', reqOrigin);
- expect(res.getHeader('Access-Control-Allow-Origin')).toBe(reqOrigin);
+ expect(res.setHeader).not.toBeCalledWith(
+ 'Access-Control-Allow-Origin',
+ 'fake-origin',
+ );
done();
},
err => {
@@ -97,26 +145,27 @@ describe('CORS middleware', () => {
);
});
- test("cors$ disallow if it doesn't match any allowed origins", done => {
+ test('should allow if it matches at least one allowed origins', done => {
// given
- const reqOrigin = 'fake-origin';
- const allowOrigin = ['fake-allowed-origin', 'other-fake-origin'];
- const mockedRequest = ({
- headers: { origin: reqOrigin },
- } as unknown) as HttpRequest;
+ const origin = 'fake-origin';
+ const allowOrigin = [origin, 'other-fake-origin'];
+ const mockedRequest = createMockRequest('GET', { origin });
- const res = (new OutgoingMessage() as unknown) as HttpResponse;
- const spy = jest.spyOn(res, 'setHeader');
+ const res = createMockResponse();
const req$ = of(mockedRequest);
// when
- const middleware$ = cors$({ origin: allowOrigin })(req$, res, undefined);
+ const middleware$ = cors$({
+ origin: allowOrigin,
+ })(req$, res, undefined);
// then
middleware$.subscribe(
() => {
- expect(spy).not.toBeCalled();
- expect(res.hasHeader('Access-Control-Allow-Origin')).toBeFalsy();
+ expect(res.setHeader).toBeCalledWith(
+ 'Access-Control-Allow-Origin',
+ 'fake-origin',
+ );
done();
},
err => {
@@ -125,27 +174,30 @@ describe('CORS middleware', () => {
},
);
});
+ });
- test('cors$ allow if it matches regexp origin', done => {
+ describe('Regexp Arg', () => {
+ test('should allow if it matches regexp origin', done => {
// given
- const reqOrigin = 'fake-allowed-origin';
+ const origin = 'fake-allowed-origin';
const allowOrigin = /^(fake-)*/;
- const mockedRequest = ({
- headers: { origin: reqOrigin },
- } as unknown) as HttpRequest;
+ const req = createMockRequest('GET', { origin });
- const res = (new OutgoingMessage() as unknown) as HttpResponse;
- const spy = jest.spyOn(res, 'setHeader');
- const req$ = of(mockedRequest);
+ const res = createMockResponse();
+ const req$ = of(req);
// when
- const middleware$ = cors$({ origin: allowOrigin })(req$, res, undefined);
+ const middleware$ = cors$({
+ origin: allowOrigin,
+ })(req$, res, undefined);
// then
middleware$.subscribe(
() => {
- expect(spy).toBeCalledWith('Access-Control-Allow-Origin', reqOrigin);
- expect(res.getHeader('Access-Control-Allow-Origin')).toBe(reqOrigin);
+ expect(res.setHeader).toBeCalledWith(
+ 'Access-Control-Allow-Origin',
+ 'fake-allowed-origin',
+ );
done();
},
err => {
@@ -155,26 +207,175 @@ describe('CORS middleware', () => {
);
});
- test("cors$ disallow if it doesn't match allowed regexp origin", done => {
+ test("should disallow if it doesn't match allowed regexp origin", done => {
// given
- const reqOrigin = 'fake-origin';
- const allowOrigin = /^(allowed-origin)/;
- const mockedRequest = ({
- headers: { origin: reqOrigin },
- } as unknown) as HttpRequest;
-
- const res = (new OutgoingMessage() as unknown) as HttpResponse;
- const spy = jest.spyOn(res, 'setHeader');
- const req$ = of(mockedRequest);
+ const origin = 'fake-origin';
+ const allowOrigin = /^[0-9]/;
+ const req = createMockRequest('GET', { origin });
+
+ const res = createMockResponse();
+ const req$ = of(req);
+
+ // when
+ const middleware$ = cors$({
+ origin: allowOrigin,
+ })(req$, res, undefined);
+
+ // then
+ middleware$.subscribe(
+ () => {
+ expect(res.setHeader).not.toBeCalledWith(
+ 'Access-Control-Allow-Origin',
+ 'fake-origin',
+ );
+ done();
+ },
+ err => {
+ fail(err);
+ done();
+ },
+ );
+ });
+ });
+ });
+
+ describe('Access-Control-Allow-Methods', () => {
+ test('OPTIONS should allow given request methods', done => {
+ // given
+ const req = createMockRequest('OPTIONS');
+ const req$ = of(req);
+
+ const allowMethods = ['GET', 'OPTIONS', 'POST'] as HttpMethod[];
+ const res = createMockResponse();
+
+ // when
+ const middleware$ = cors$({
+ methods: allowMethods,
+ })(req$, res, undefined);
+
+ // then
+ middleware$.subscribe(
+ () => {
+ expect(res.setHeader).toBeCalledWith(
+ 'Access-Control-Allow-Methods',
+ 'GET, OPTIONS, POST',
+ );
+ done();
+ },
+ err => {
+ fail(err);
+ done();
+ },
+ );
+ });
+ });
+
+ describe('Access-Control-Allow-Headers', () => {
+ test('OPTIONS should allow wildcard', done => {
+ // given
+ const req = createMockRequest('OPTIONS');
+ const req$ = of(req);
+
+ const allowHeaders = '*';
+ const res = createMockResponse();
+
+ // when
+ const middleware$ = cors$({
+ allowHeaders,
+ })(req$, res, undefined);
+
+ // then
+ middleware$.subscribe(
+ () => {
+ expect(res.setHeader).toBeCalledWith(
+ 'Access-Control-Allow-Headers',
+ '*',
+ );
+ done();
+ },
+ err => {
+ fail(err);
+ done();
+ },
+ );
+ });
+
+ test('OPTIONS should allow given allowed headers', done => {
+ // given
+ const req = createMockRequest('OPTIONS');
+ const req$ = of(req);
+
+ const allowHeaders = ['Content-Length', 'X-Header', 'Authorization'];
+ const res = createMockResponse();
+
+ // when
+ const middleware$ = cors$({
+ allowHeaders,
+ })(req$, res, undefined);
+
+ // then
+ middleware$.subscribe(
+ () => {
+ expect(res.setHeader).toBeCalledWith(
+ 'Access-Control-Allow-Headers',
+ 'Content-Length, X-Header, Authorization',
+ );
+ done();
+ },
+ err => {
+ fail(err);
+ done();
+ },
+ );
+ });
+ });
+
+ describe('Access-Control-Allow-Credentials', () => {
+ test('should allow credentials', done => {
+ // given
+ const req = createMockRequest('OPTIONS');
+ const req$ = of(req);
+ const res = createMockResponse();
// when
- const middleware$ = cors$({ origin: allowOrigin })(req$, res, undefined);
+ const middleware$ = cors$({
+ withCredentials: true,
+ })(req$, res, undefined);
// then
middleware$.subscribe(
() => {
- expect(spy).not.toBeCalled();
- expect(res.hasHeader('Access-Control-Allow-Origin')).toBeFalsy();
+ expect(res.setHeader).toBeCalledWith(
+ 'Access-Control-Allow-Credentials',
+ 'true',
+ );
+ done();
+ },
+ err => {
+ fail(err);
+ done();
+ },
+ );
+ });
+
+ test('should disallow credentials', done => {
+ // given
+ const req = createMockRequest('OPTIONS');
+ const req$ = of(req);
+ const res = createMockResponse();
+
+ // when
+ const middleware$ = cors$({
+ withCredentials: false,
+ })(req$, res, undefined);
+
+ // then
+ middleware$.subscribe(
+ () => {
+ expect(res.setHeader).not.toBeCalledWith(
+ 'Access-Control-Allow-Credentials',
+ 'true',
+ );
done();
},
err => {

tests(middleware-cors): improve mocks, add headers specs