Skip to content

Commit 612dbaa

Browse files
committed
test: enhance test coverage
1 parent ac1b1f0 commit 612dbaa

8 files changed

+165
-11
lines changed

lib/builders/url.builder.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,18 @@ describe('UrlBuilder', () => {
7474
// then
7575
expect(actual).toBe('https://example.com/api/user?keyword=search');
7676
});
77+
78+
test('should strip duplicated slash', () => {
79+
// given
80+
const host = '//example.com';
81+
const path = '//api///user';
82+
const args = [1];
83+
const urlBuilder = new UrlBuilder(host, path, args);
84+
85+
// when
86+
const actual = urlBuilder.build();
87+
88+
// then
89+
expect(actual).toBe('/example.com/api/user');
90+
});
7791
});

lib/decorators/path-variable.decorator.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@ import { PathVariable } from './path-variable.decorator';
44
import { type PathVariableBuilder } from '../builders/path-variable.builder';
55

66
describe('PathVariable', () => {
7+
test('should not create path variable metadata when not on method', () => {
8+
// given
9+
class TestService {
10+
constructor(@PathVariable('foo') foo: string) {
11+
return foo;
12+
}
13+
}
14+
15+
// when
16+
const result = Reflect.getMetadata(
17+
PATH_VARIABLE_METADATA,
18+
TestService.prototype,
19+
'request',
20+
);
21+
22+
// then
23+
expect(result).toBeUndefined();
24+
});
25+
726
test('should set path variable metadata', () => {
827
// given
928
class TestService {

lib/decorators/request-body.decorator.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,25 @@ import { type RequestBodyBuilder } from '../builders/request-body.builder';
55
import { type RequestParamBuilder } from '../builders/request-param.builder';
66

77
describe('RequestBody', () => {
8+
test('should not create request body metadata when not on method', () => {
9+
// given
10+
class TestService {
11+
constructor(@RequestBody() foo: string) {
12+
return foo;
13+
}
14+
}
15+
16+
// when
17+
const result = Reflect.getMetadata(
18+
REQUEST_BODY_METADATA,
19+
TestService.prototype,
20+
'request',
21+
);
22+
23+
// then
24+
expect(result).toBeUndefined();
25+
});
26+
827
test('should set request body metadata with empty key', () => {
928
// given
1029
class TestService {

lib/decorators/request-form.decorator.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,25 @@ import { type RequestFormBuilder } from '../builders/request-form.builder';
55
import { type RequestParamBuilder } from '../builders/request-param.builder';
66

77
describe('RequestForm', () => {
8+
test('should not create request form metadata when not on method', () => {
9+
// given
10+
class TestService {
11+
constructor(@RequestForm() foo: string) {
12+
return foo;
13+
}
14+
}
15+
16+
// when
17+
const result = Reflect.getMetadata(
18+
REQUEST_FORM_METADATA,
19+
TestService.prototype,
20+
'request',
21+
);
22+
23+
// then
24+
expect(result).toBeUndefined();
25+
});
26+
827
test('should set request form metadata with empty key', () => {
928
// given
1029
class TestService {

lib/decorators/request-header.decorator.spec.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,28 @@ import { describe, test, expect } from 'vitest';
22
import { REQUEST_HEADER_METADATA } from './constants';
33
import { RequestHeader } from './request-header.decorator';
44
import { type RequestHeaderBuilder } from '../builders/request-header.builder';
5+
import { type RequestParamBuilder } from '../builders/request-param.builder';
56

67
describe('RequestHeader', () => {
8+
test('should not create request header metadata when not on method', () => {
9+
// given
10+
class TestService {
11+
constructor(@RequestHeader() foo: string) {
12+
return foo;
13+
}
14+
}
15+
16+
// when
17+
const result = Reflect.getMetadata(
18+
REQUEST_HEADER_METADATA,
19+
TestService.prototype,
20+
'request',
21+
);
22+
23+
// then
24+
expect(result).toBeUndefined();
25+
});
26+
727
test('should set request header metadata with empty key', () => {
828
// given
929
class TestService {
@@ -41,4 +61,29 @@ describe('RequestHeader', () => {
4161
// then
4262
expect(result.metadata).toEqual([[0, 'foo']]);
4363
});
64+
65+
test('should set request header metadata with multiple decorator', () => {
66+
// given
67+
class TestService {
68+
request(
69+
@RequestHeader('foo') foo: string,
70+
@RequestHeader() bar: { bar: string },
71+
): string {
72+
return foo;
73+
}
74+
}
75+
76+
// when
77+
const result: RequestParamBuilder = Reflect.getMetadata(
78+
REQUEST_HEADER_METADATA,
79+
TestService.prototype,
80+
'request',
81+
);
82+
83+
// then
84+
expect(result.metadata).toEqual([
85+
[1, undefined],
86+
[0, 'foo'],
87+
]);
88+
});
4489
});

lib/decorators/request-param.decorator.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@ import { RequestParam } from './request-param.decorator';
44
import { type RequestParamBuilder } from '../builders/request-param.builder';
55

66
describe('RequestParam', () => {
7+
test('should not create request param metadata when not on method', () => {
8+
// given
9+
class TestService {
10+
constructor(@RequestParam() foo: string) {
11+
return foo;
12+
}
13+
}
14+
15+
// when
16+
const result = Reflect.getMetadata(
17+
REQUEST_PARAM_METADATA,
18+
TestService.prototype,
19+
'request',
20+
);
21+
22+
// then
23+
expect(result).toBeUndefined();
24+
});
25+
726
test('should set request param metadata with empty key', () => {
827
// given
928
class TestService {

lib/fixtures/stub-http-client.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ export class StubHttpClient implements HttpClient {
99

1010
const response = this.#responses.shift();
1111

12-
if (typeof response === 'undefined') {
13-
throw new Error('empty response array');
14-
}
15-
16-
return response;
12+
return response ?? new Response('{}', { status: 404 });
1713
}
1814

1915
get requestInfo(): Request[] {

lib/node-fetch.injector.spec.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
PostExchange,
1212
PutExchange,
1313
RequestBody,
14+
RequestForm,
1415
RequestParam,
1516
} from './decorators';
1617
import { StubDiscoveryService } from './fixtures/stub-discovery.service';
@@ -80,7 +81,6 @@ describe('NodeFetchInjector', () => {
8081
}
8182
}
8283
const instance = discoveryService.addProvider(SampleClient);
83-
httpClient.addResponse({ status: 'ok' });
8484
nodeFetchInjector.onModuleInit();
8585

8686
// when
@@ -101,7 +101,6 @@ describe('NodeFetchInjector', () => {
101101
}
102102
}
103103
const instance = discoveryService.addProvider(SampleClient);
104-
httpClient.addResponse({ status: 'ok' });
105104
nodeFetchInjector.onModuleInit();
106105

107106
// when
@@ -127,7 +126,6 @@ describe('NodeFetchInjector', () => {
127126
}
128127
}
129128
const instance = discoveryService.addProvider(SampleClient);
130-
httpClient.addResponse({ status: 'ok' });
131129
nodeFetchInjector.onModuleInit();
132130

133131
// when
@@ -150,7 +148,6 @@ describe('NodeFetchInjector', () => {
150148
}
151149
}
152150
const instance = discoveryService.addProvider(SampleClient);
153-
httpClient.addResponse({ status: 'ok' });
154151
nodeFetchInjector.onModuleInit();
155152

156153
// when
@@ -175,7 +172,6 @@ describe('NodeFetchInjector', () => {
175172
}
176173
}
177174
const instance = discoveryService.addProvider(SampleClient);
178-
httpClient.addResponse({ status: 'ok' });
179175
nodeFetchInjector.onModuleInit();
180176

181177
// when
@@ -206,7 +202,6 @@ describe('NodeFetchInjector', () => {
206202
}
207203
}
208204
const instance = discoveryService.addProvider(SampleClient);
209-
httpClient.addResponse({ status: 'ok' });
210205
nodeFetchInjector.onModuleInit();
211206

212207
// when
@@ -266,4 +261,32 @@ describe('NodeFetchInjector', () => {
266261
'application/json',
267262
);
268263
});
264+
265+
test('should include body provided by form', async () => {
266+
// given
267+
@HttpInterface()
268+
class SampleClient {
269+
@PostExchange('https://example.com/api')
270+
async request(
271+
@RequestForm() body: Record<string, unknown>,
272+
): Promise<string> {
273+
return 'request';
274+
}
275+
}
276+
const instance = discoveryService.addProvider(SampleClient);
277+
httpClient.addResponse({ status: 'ok' });
278+
nodeFetchInjector.onModuleInit();
279+
280+
// when
281+
await instance.request({ foo: 'bar' });
282+
283+
// then
284+
expect(httpClient.requestInfo).toHaveLength(1);
285+
expect(await httpClient.requestInfo[0].text()).toContain(
286+
`Content-Disposition: form-data; name="foo"`,
287+
);
288+
expect(httpClient.requestInfo[0].headers.get('Content-Type')).toBe(
289+
'application/x-www-form-urlencoded',
290+
);
291+
});
269292
});

0 commit comments

Comments
 (0)