Skip to content

Commit e4a9dc5

Browse files
committed
Merge branch 'master' into beta
2 parents dc4c1f5 + 817b341 commit e4a9dc5

File tree

4 files changed

+163
-23
lines changed

4 files changed

+163
-23
lines changed

lib/internals/findRoute.spec.ts

+69-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,20 @@ class Handler {
99
return { list: true };
1010
}
1111

12-
@Get('/:id')
12+
@Get('/:id(\\d+)')
1313
public details() {
1414
return { details: true };
1515
}
16+
17+
@Get('/item')
18+
public item() {
19+
return { item: true };
20+
}
21+
22+
@Get('/item/child-item')
23+
public childItem() {
24+
return { childItem: true };
25+
}
1626
}
1727

1828
describe('findRoute', () => {
@@ -21,13 +31,35 @@ describe('findRoute', () => {
2131

2232
expect(keys).toHaveLength(1);
2333
expect(method).toMatchObject({
24-
path: '/:id',
34+
path: expect.stringContaining('/:id'),
2535
propertyKey: 'details',
2636
verb: 'GET'
2737
});
2838
});
2939

30-
it('Should return the main / route when "path-to-regexp" is not installed.', () => {
40+
it('Should return the "item" method', () => {
41+
const [keys, , method] = findRoute(Handler, 'GET', '/item');
42+
43+
expect(keys).toHaveLength(0);
44+
expect(method).toMatchObject({
45+
path: '/item',
46+
propertyKey: 'item',
47+
verb: 'GET'
48+
});
49+
});
50+
51+
it('Should return the "childItem" method', () => {
52+
const [keys, , method] = findRoute(Handler, 'GET', '/item/child-item');
53+
54+
expect(keys).toHaveLength(0);
55+
expect(method).toMatchObject({
56+
path: '/item/child-item',
57+
propertyKey: 'childItem',
58+
verb: 'GET'
59+
});
60+
});
61+
62+
it('Should return the main / route instead of "details" method when "path-to-regexp" is not installed.', () => {
3163
const spy = jest
3264
.spyOn(lp, 'loadPackage')
3365
.mockImplementation((name: string) => (name === 'path-to-regexp' ? false : require(name)));
@@ -42,4 +74,38 @@ describe('findRoute', () => {
4274
verb: 'GET'
4375
});
4476
});
77+
78+
it('Should return the "item" method when "path-to-regexp" is not installed.', () => {
79+
const spy = jest
80+
.spyOn(lp, 'loadPackage')
81+
.mockImplementation((name: string) => (name === 'path-to-regexp' ? false : require(name)));
82+
83+
const [keys, , method] = findRoute(Handler, 'GET', '/item');
84+
85+
spy.mockRestore();
86+
87+
expect(keys).toHaveLength(0);
88+
expect(method).toMatchObject({
89+
path: '/item',
90+
propertyKey: 'item',
91+
verb: 'GET'
92+
});
93+
});
94+
95+
it('Should return the "child-item" method when "path-to-regexp" is not installed.', () => {
96+
const spy = jest
97+
.spyOn(lp, 'loadPackage')
98+
.mockImplementation((name: string) => (name === 'path-to-regexp' ? false : require(name)));
99+
100+
const [keys, , method] = findRoute(Handler, 'GET', '/item/child-item');
101+
102+
spy.mockRestore();
103+
104+
expect(keys).toHaveLength(0);
105+
expect(method).toMatchObject({
106+
path: '/item/child-item',
107+
propertyKey: 'childItem',
108+
verb: 'GET'
109+
});
110+
});
45111
});

lib/internals/findRoute.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ export function findRoute(
1010
const methods: Array<HandlerMethod> = Reflect.getMetadata(HTTP_METHOD_TOKEN, cls);
1111

1212
const { pathToRegexp } = loadPackage('path-to-regexp');
13-
if (path !== '/' && !pathToRegexp) {
14-
return [[], undefined, methods.find(f => f.path === '/' && f.verb === verb)];
13+
if (!pathToRegexp) {
14+
const method = methods.find(f => f.path === path && f.verb === verb);
15+
return [[], undefined, method ?? methods.find(f => f.path === '/' && f.verb === verb)];
1516
}
1617

1718
const keys: Key[] = [];

test/e2e-basic-routing.test.ts

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import 'reflect-metadata';
2+
import request from 'supertest';
3+
import { createHandler, Get, Param, ParseNumberPipe } from '../lib';
4+
import * as lp from '../lib/internals/loadPackage';
5+
import { setupServer } from './setupServer';
6+
7+
const ARTICLES = [
8+
{ id: 1, title: 'Article 1' },
9+
{ id: 2, title: 'Article 2' }
10+
];
11+
const COMMENTS = [{ text: 'Comment 1' }, { text: 'Comment 2' }];
12+
13+
class ArticleHandler {
14+
@Get('/')
15+
public articles(): Record<string, any>[] {
16+
return ARTICLES;
17+
}
18+
19+
@Get('/:id(\\d+)')
20+
public article(@Param('id', ParseNumberPipe) id: number) {
21+
return ARTICLES.find(article => article.id === id);
22+
}
23+
24+
@Get('/comments')
25+
public articleComments(): Record<string, any>[] {
26+
return COMMENTS;
27+
}
28+
29+
@Get('/comments/favorites')
30+
public favoriteArticleComments(): Record<string, any>[] {
31+
return [COMMENTS[0]];
32+
}
33+
}
34+
35+
describe('E2E - Basic routing', () => {
36+
let server: ReturnType<typeof setupServer>;
37+
beforeAll(() => (server = setupServer(createHandler(ArticleHandler))));
38+
afterAll(() => {
39+
if ('close' in server && typeof server.close === 'function') {
40+
server.close();
41+
}
42+
});
43+
44+
it('Should execute "articles".', () => request(server).get('/api/articles').expect(200, ARTICLES));
45+
46+
it('Should execute "article".', () => request(server).get('/api/articles/1').expect(200, ARTICLES[0]));
47+
48+
it('Should execute "articleComments".', () => request(server).get('/api/articles/comments').expect(200, COMMENTS));
49+
50+
it('Should execute "favoriteArticleComments".', () =>
51+
request(server).get('/api/articles/comments/favorites').expect(200, [COMMENTS[0]]));
52+
});
53+
54+
describe('E2E - Basic routing (without "path-to-regexp")', () => {
55+
let server: ReturnType<typeof setupServer>;
56+
beforeAll(() => {
57+
jest
58+
.spyOn(lp, 'loadPackage')
59+
.mockImplementation((name: string) => (name === 'path-to-regexp' ? false : require(name)));
60+
61+
server = setupServer(createHandler(ArticleHandler));
62+
});
63+
afterAll(() => {
64+
jest.restoreAllMocks();
65+
66+
if ('close' in server && typeof server.close === 'function') {
67+
server.close();
68+
}
69+
});
70+
71+
it('Should execute "articles" when "path-to-regexp" is not installed.', () =>
72+
request(server).get('/api/articles').expect(200, ARTICLES));
73+
74+
it('Should execute "articles" instead of "article" method when "path-to-regexp" is not installed.', () =>
75+
request(server).get('/api/articles/1').expect(200, ARTICLES));
76+
77+
it('Should execute "articleComments" when "path-to-regexp" is not installed.', () =>
78+
request(server).get('/api/articles/comments').expect(200, COMMENTS));
79+
80+
it('Should execute "favoriteArticleComments" when "path-to-regexp" is not installed.', () =>
81+
request(server).get('/api/articles/comments/favorites').expect(200, [COMMENTS[0]]));
82+
});

website/yarn.lock

100755100644
+9-18
Original file line numberDiff line numberDiff line change
@@ -5741,10 +5741,10 @@ nan@^2.12.1:
57415741
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
57425742
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
57435743

5744-
nanoid@^3.1.20, nanoid@^3.1.22:
5745-
version "3.1.22"
5746-
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844"
5747-
integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==
5744+
nanoid@^3.1.23:
5745+
version "3.1.23"
5746+
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
5747+
integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
57485748

57495749
nanomatch@^1.2.9:
57505750
version "1.2.13"
@@ -6579,22 +6579,13 @@ postcss-zindex@^5.0.0:
65796579
has "^1.0.3"
65806580
uniqs "^2.0.0"
65816581

6582-
postcss@^8.2.10, postcss@^8.2.4, postcss@^8.2.9:
6583-
version "8.2.13"
6584-
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.13.tgz#dbe043e26e3c068e45113b1ed6375d2d37e2129f"
6585-
integrity sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ==
6582+
postcss@^8.2.10, postcss@^8.2.4, postcss@^8.2.8, postcss@^8.2.9:
6583+
version "8.2.15"
6584+
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.15.tgz#9e66ccf07292817d226fc315cbbf9bc148fbca65"
6585+
integrity sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==
65866586
dependencies:
65876587
colorette "^1.2.2"
6588-
nanoid "^3.1.22"
6589-
source-map "^0.6.1"
6590-
6591-
postcss@^8.2.8:
6592-
version "8.2.8"
6593-
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.8.tgz#0b90f9382efda424c4f0f69a2ead6f6830d08ece"
6594-
integrity sha512-1F0Xb2T21xET7oQV9eKuctbM9S7BC0fetoHCc4H13z0PT6haiRLP4T0ZY4XWh7iLP0usgqykT6p9B2RtOf4FPw==
6595-
dependencies:
6596-
colorette "^1.2.2"
6597-
nanoid "^3.1.20"
6588+
nanoid "^3.1.23"
65986589
source-map "^0.6.1"
65996590

66006591
prepend-http@^2.0.0:

0 commit comments

Comments
 (0)