Fixing tests after rebasing
MODIFY
example/src/app.ts
example/src/app.ts
import { bodyParser$, httpListener, logger$ } from '@marblejs/core';
import { api$ } from './controllers/api.controller';
-const middlewares = [
- logger$,
- bodyParser$,
-];
+const middlewares = [logger$, bodyParser$];
-const effects = [
- api$,
-];
+const effects = [api$];
export const app = httpListener({ middlewares, effects });

MODIFY
packages/core/src/http.interface.ts
packages/core/src/http.interface.ts
@@ -15,7 +15,16 @@ export interface HttpResponse extends http.ServerResponse {}
export type HttpHeaders = Record<string, string>;
-export type HttpMethod = 'POST' | 'PUT' | 'PATCH' | 'GET' | 'HEAD' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE';
+export type HttpMethod =
+ | 'POST'
+ | 'PUT'
+ | 'PATCH'
+ | 'GET'
+ | 'HEAD'
+ | 'DELETE'
+ | 'CONNECT'
+ | 'OPTIONS'
+ | 'TRACE';
export type Http = {
req: HttpRequest;
@@ -42,5 +51,5 @@ export enum HttpStatus {
NOT_IMPLEMENTED = 501,
BAD_GATEWAY = 502,
SERVICE_UNAVAILABLE = 503,
- GATEWAY_TIMEOUT = 504,
+ GATEWAY_TIMEOUT = 504
}

DELETE
packages/core/src/operators/matchPath.operator.ts
-import * as pathToRegexp from 'path-to-regexp';
-import { Observable } from 'rxjs';
-import { filter, tap } from 'rxjs/operators';
-import { HttpRequest, HttpRoute, RouteParameters } from '../http.interface';
-import { queryParamsFactory } from "./queryParamsFactory/queryParams.factory";
-import { urlParamsFactory } from "./urlParamsFactory/urlParams.factory";
-
-type MatcherOpts = {
- suffix?: string,
- combiner?: boolean,
-};
-
-const removeTrailingSlash = (path: string): string =>
- path.replace(/\/$/, '');
-
-const removeQueryParams = (path: string): string =>
- path.split('?')[0];
-
-const pathFactory = (matchers: string[], path: string, suffix?: string): string =>
- removeTrailingSlash(
- matchers.reduce((prev, cur) => prev + cur, '')
- + path + (suffix || '')
- );
-
-const urlFactory = (path: string): string =>
- removeQueryParams(path);
-
-const routeFactory = (req: HttpRequest, path: string): HttpRoute => {
- const match = pathFactory(req.matchers!, path);
- const url = urlFactory(req.url!);
- const params = pathToRegexp(match).exec(url);
- const routes = pathToRegexp.parse(match);
-
- return {
- url,
- params: urlParamsFactory(params, routes),
- query: queryParamsFactory(req.url!)
- };
-};
-
-export const matchPath = (path: string, opts: MatcherOpts = {}) => (source$: Observable<HttpRequest>) =>
- source$.pipe(
- tap(req => req.matchers = req.matchers || []),
- filter(req => {
- const match = pathFactory(req.matchers!, path, opts.suffix);
- const url = urlFactory(req.url!);
- return pathToRegexp(match).test(url);
- }),
- tap(req => req.route = {
- ...req.route,
- ...routeFactory(req, path),
- }),
- tap(req => opts.combiner && req.matchers!.push(path))
- );

MODIFY
packages/core/src/operators/matchPath/matchPath.operator.spec.ts
packages/core/src/operators/matchPath/matchPath.operator.spec.ts
-import { HttpRequest, RouteParameters, QueryParameters } from '../../http.interface';
+import {
+ HttpRequest,
+ RouteParameters,
+ QueryParameters
+} from '../../http.interface';
import { Marbles } from '../../util/marbles.spec-util';
import { matchPath } from './matchPath.operator';
-import { queryParamsFactory } from "../../operators/queryParamsFactory/queryParams.factory";
+import { queryParamsFactory } from './queryParams.factory';
import { urlParamsFactory } from './urlParams.factory';
const req = (url: string) => ({ url } as HttpRequest);
-const reqMatched = (url: string, queryString = '', matchers: string[] = [], params: RouteParameters = {}, query?: QueryParameters) => {
+const reqMatched = (
+ url: string,
+ queryString = '',
+ matchers: string[] = [],
+ params: RouteParameters = {},
+ query?: QueryParameters
+) => {
const urlWithQuery = !!queryString ? `${url}?${queryString}` : url;
return {
url: urlWithQuery,
matchers,
params,
- query: queryParamsFactory(urlWithQuery),
+ query: queryParamsFactory(urlWithQuery)
} as HttpRequest;
};
@@ -26,13 +36,13 @@ describe('matchPath operator', () => {
operators = [matchPath('/')];
Marbles.assert(operators, [
['-a-b---', { a: req('/'), b: req('/test') }],
- ['-a-----', { a: reqMatched('/') }],
+ ['-a-----', { a: reqMatched('/') }]
]);
operators = [matchPath('/test')];
Marbles.assert(operators, [
['-a-b---', { a: req('/'), b: req('/test') }],
- ['---b---', { b: reqMatched('/test') }],
+ ['---b---', { b: reqMatched('/test') }]
]);
});
@@ -40,49 +50,69 @@ describe('matchPath operator', () => {
operators = [matchPath('/test/:foo/bar')];
Marbles.assert(operators, [
['-a-b---', { a: req('/test/bar'), b: req('/test/url/bar') }],
- ['---b---', { b: reqMatched('/test/url/bar', null, [], { foo: 'url' }) }],
+ ['---b---', { b: reqMatched('/test/url/bar', null, [], { foo: 'url' }) }]
]);
});
it('matches path with query parameter', () => {
operators = [matchPath('/test')];
Marbles.assert(operators, [
- ['-a-b-c-', {
+ [
+ '-a-b-c-',
+ {
a: req('/test/bar'),
b: req('/test?foo=bar'),
- c: req('/test/?foo=bar'),
- }],
- ['---b-c-', {
+ c: req('/test/?foo=bar')
+ }
+ ],
+ [
+ '---b-c-',
+ {
b: reqMatched('/test', 'foo=bar'),
- c: reqMatched('/test/', 'foo=bar'),
- }],
+ c: reqMatched('/test/', 'foo=bar')
+ }
+ ]
]);
});
it('matches path with url and query parameter', () => {
operators = [matchPath('/test/:foo/bar')];
Marbles.assert(operators, [
- ['-a-b--', {
+ [
+ '-a-b--',
+ {
a: req('/test/bar'),
- b: req('/test/url/bar?foo=bar') }],
- ['---b--', {
- b: reqMatched('/test/url/bar', 'foo=bar', [], { foo: 'url' }) }],
+ b: req('/test/url/bar?foo=bar')
+ }
+ ],
+ [
+ '---b--',
+ {
+ b: reqMatched('/test/url/bar', 'foo=bar', [], { foo: 'url' })
+ }
+ ]
]);
});
it('matches path with additional suffix parameter', () => {
operators = [matchPath('/test', { suffix: '/:foo*' })];
Marbles.assert(operators, [
- ['-a-b-c-', {
+ [
+ '-a-b-c-',
+ {
a: req('/test'),
b: req('/test/bar'),
- c: req('/test/url/bar'),
- }],
- ['-a-b-c-', {
+ c: req('/test/url/bar')
+ }
+ ],
+ [
+ '-a-b-c-',
+ {
a: reqMatched('/test'),
b: reqMatched('/test/bar'),
- c: reqMatched('/test/url/bar'),
- }],
+ c: reqMatched('/test/url/bar')
+ }
+ ]
]);
});
@@ -90,14 +120,18 @@ describe('matchPath operator', () => {
operators = [matchPath('/test', { combiner: true })];
Marbles.assert(operators, [
['-a--', { a: req('/test') }],
- ['-a--', { a: reqMatched('/test', null, ['/test']) }],
+ ['-a--', { a: reqMatched('/test', null, ['/test']) }]
]);
- operators = [matchPath('/test/:id/foo', { combiner: true, suffix: '/:foo*' })];
+ operators = [
+ matchPath('/test/:id/foo', { combiner: true, suffix: '/:foo*' })
+ ];
Marbles.assert(operators, [
['-a--', { a: req('/test/2/foo') }],
- ['-a--', { a: reqMatched('/test/2/foo', null, ['/test/:id/foo'], { id: '2' }) }],
+ [
+ '-a--',
+ { a: reqMatched('/test/2/foo', null, ['/test/:id/foo'], { id: '2' }) }
+ ]
]);
});
-
});

MODIFY
packages/core/src/operators/matchPath/matchPath.operator.ts
packages/core/src/operators/matchPath/matchPath.operator.ts
@@ -4,20 +4,24 @@ import { filter, tap } from 'rxjs/operators';
import { HttpRequest } from '../../http.interface';
import { pathFactory, urlFactory } from './matchPath.factory';
import { urlParamsFactory } from './urlParams.factory';
+import { queryParamsFactory } from './queryParams.factory';
type MatcherOpts = {
- suffix?: string,
- combiner?: boolean,
+ suffix?: string;
+ combiner?: boolean;
};
-export const matchPath = (path: string, opts: MatcherOpts = {}) => (source$: Observable<HttpRequest>) =>
+export const matchPath = (path: string, opts: MatcherOpts = {}) => (
+ source$: Observable<HttpRequest>
+) =>
source$.pipe(
- tap(req => req.matchers = req.matchers || []),
+ tap(req => (req.matchers = req.matchers || [])),
filter(req => {
const match = pathFactory(req.matchers!, path, opts.suffix);
const url = urlFactory(req.url!);
return pathToRegexp(match).test(url);
}),
- tap(req => req.params = urlParamsFactory(req, path)),
+ tap(req => (req.params = urlParamsFactory(req, path))),
+ tap(req => (req.query = queryParamsFactory(req.url!))),
tap(req => opts.combiner && req.matchers!.push(path))
);

RENAME
packages/core/src/operators/queryParamsFactory/queryParams.factory.ts
packages/core/src/operators/matchPath/queryParams.factory.ts
import * as querystring from 'querystring';
import { QueryParameters } from '../../http.interface';
-const getNestedQueryParam = (key: string, paramValue: string | Object): string | Object => {
+const getNestedQueryParam = (
+ key: string,
+ paramValue: string | Object
+): string | Object => {
const nestedKeys = /\[.*\]/.exec(key);
- if(!nestedKeys) return ({ [key]: paramValue });
+ if (!nestedKeys) return { [key]: paramValue };
- const extractedKeys = nestedKeys[0].replace(/\[/g, '').split(']').filter(v => v.length > 0);
- const nestedQueryObject = extractedKeys.reduceRight((value, key) => ({ [key]: value }), paramValue);
+ const extractedKeys = nestedKeys[0]
+ .replace(/\[/g, '')
+ .split(']')
+ .filter(v => v.length > 0);
+ const nestedQueryObject = extractedKeys.reduceRight(
+ (value, key) => ({ [key]: value }),
+ paramValue
+ );
return { [key.replace(nestedKeys[0], '')]: nestedQueryObject };
-}
+};
const queryParamsArrayToObject = (queryParams: Object): QueryParameters => {
const queryParamsKey = Object.keys(queryParams);
- return Object.assign({}, ...queryParamsKey.map(key => getNestedQueryParam(key, queryParams[key])));
-}
+ return Object.assign(
+ {},
+ ...queryParamsKey.map(key => getNestedQueryParam(key, queryParams[key]))
+ );
+};
export const queryParamsFactory = (path: string): QueryParameters => {
if (!path || !path.includes('?')) return {};
const queryParamsString = path.split('?').pop();
-
const extractedQueryParams = querystring.parse(queryParamsString!);
return queryParamsArrayToObject(extractedQueryParams);
-}
+};

ADD
packages/core/src/operators/matchPath/queryParamsFactory.spec.ts
+import { queryParamsFactory } from './queryParams.factory';
+
+describe('queryParamsFactory', () => {
+ test('should return empty object when passed URL with no valid params', () => {
+ // given
+ const invalidURLS = ['http://test.com', 'http://test.com?', null];
+
+ invalidURLS.forEach(url => {
+ // when
+ const params = queryParamsFactory(url);
+
+ // then
+ expect(params).toEqual({});
+ });
+ });
+
+ test('should return empty string when no value for provided key', () => {
+ // given
+ const exampleURL = 'http://test.com?testParam';
+ const expectedParamsObj = { testParam: '' };
+
+ // when
+ const params = queryParamsFactory(exampleURL);
+
+ // then
+ expect(params).toEqual(expectedParamsObj);
+ });
+
+ test('should return object with multiple keys', () => {
+ // given
+ const exampleURL = 'http://test.com?testParam=test&testParam2=test2';
+ const expectedParamsObj = { testParam: 'test', testParam2: 'test2' };
+
+ // when
+ const params = queryParamsFactory(exampleURL);
+
+ // then
+ expect(params).toEqual(expectedParamsObj);
+ });
+
+ test('should return array when passed two times same parameter', () => {
+ // given
+ const exampleURL = 'http://test.com?testParam=test&testParam=123';
+ const expectedParamsObj = { testParam: ['test', '123'] };
+
+ // when
+ const params = queryParamsFactory(exampleURL);
+
+ // then
+ expect(params).toEqual(expectedParamsObj);
+ });
+
+ test('should return nested object', () => {
+ // given
+ const exampleURL = 'http://test.com?testParam[testNested]=test';
+ const expectedParamsObj = { testParam: { testNested: 'test' } };
+
+ // when
+ const params = queryParamsFactory(exampleURL);
+
+ // then
+ expect(params).toEqual(expectedParamsObj);
+ });
+});

DELETE
packages/core/src/operators/queryParamsFactory/queryParamsFactory.spec.ts
-import { queryParamsFactory } from "./queryParams.factory";
-
-
-describe("queryParamsFactory", () => {
- test("should return empty object when passed URL with no valid params", () => {
- // given
- const invalidURLS = ["http://test.com", "http://test.com?", null];
-
- invalidURLS.forEach(url => {
- // when
- const params = queryParamsFactory(url);
-
- // then
- expect(params).toEqual({});
- });
- });
-
- test("should return empty string when no value for provided key", () => {
- // given
- const exampleURL = "http://test.com?testParam";
- const expectedParamsObj = { testParam: "" };
-
- // when
- const params = queryParamsFactory(exampleURL);
-
- // then
- expect(params).toEqual(expectedParamsObj);
- });
-
- test("should return object with multiple keys", () => {
- // given
- const exampleURL = "http://test.com?testParam=test&testParam2=test2";
- const expectedParamsObj = { testParam: "test", testParam2: "test2" };
-
- // when
- const params = queryParamsFactory(exampleURL);
-
- // then
- expect(params).toEqual(expectedParamsObj);
- });
-
- test("should return array when passed two times same parameter", () => {
- // given
- const exampleURL = "http://test.com?testParam=test&testParam=123";
- const expectedParamsObj = { testParam: ["test", "123"] };
-
- // when
- const params = queryParamsFactory(exampleURL);
-
- // then
- expect(params).toEqual(expectedParamsObj);
- });
-
- test("should return nested object", () => {
- // given
- const exampleURL = "http://test.com?testParam[testNested]=test";
- const expectedParamsObj = { testParam: { testNested: "test" } };
-
- // when
- const params = queryParamsFactory(exampleURL);
-
- // then
- expect(params).toEqual(expectedParamsObj);
- });
-});

DELETE
packages/core/src/operators/urlParamsFactory/urlParams.factory.ts
-import * as pathToRegexp from 'path-to-regexp';
-import { RouteParameters } from '../../http.interface';
-
-export const urlParamsFactory = (params: RegExpMatchArray | null, routes: pathToRegexp.Token[]): RouteParameters => {
- if (!params || !routes) { return {}; }
-
- return routes
- .filter(route => route.hasOwnProperty('name'))
- .reduce((obj, route, index) => ({
- ...obj,
- [route['name']]: params[++index],
- }), {});
-};

Fixing tests after rebasing