Skip to content

Commit 0c66d97

Browse files
authored
fix(response): brings Response object to parity with Functions (#287)
1 parent ecbf4ab commit 0c66d97

File tree

4 files changed

+138
-20
lines changed

4 files changed

+138
-20
lines changed

packages/runtime-handler/__tests__/dev-runtime/internal/response.test.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,30 @@ import { Response } from '../../../src/dev-runtime/internal/response';
33

44
test('has correct defaults', () => {
55
const response = new Response();
6-
expect(response['body']).toBeUndefined();
6+
expect(response['body']).toBeNull();
77
expect(response['statusCode']).toBe(200);
88
expect(response['headers']).toEqual({});
99
});
1010

11+
test('sets status code, body and headers from constructor', () => {
12+
const response = new Response({
13+
headers: {
14+
'Access-Control-Allow-Origin': 'example.com',
15+
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE',
16+
'Access-Control-Allow-Headers': 'Content-Type',
17+
},
18+
body: 'Error',
19+
statusCode: 400,
20+
});
21+
expect(response['statusCode']).toBe(400);
22+
expect(response['body']).toBe('Error');
23+
expect(response['headers']).toEqual({
24+
'Access-Control-Allow-Origin': 'example.com',
25+
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE',
26+
'Access-Control-Allow-Headers': 'Content-Type',
27+
});
28+
});
29+
1130
test('sets status code', () => {
1231
const response = new Response();
1332
expect(response['statusCode']).toBe(200);
@@ -17,7 +36,7 @@ test('sets status code', () => {
1736

1837
test('sets body correctly', () => {
1938
const response = new Response();
20-
expect(response['body']).toBeUndefined();
39+
expect(response['body']).toBeNull();
2140
response.setBody('Hello');
2241
expect(response['body']).toBe('Hello');
2342
response.setBody({ url: 'https://dkundel.com' });
@@ -68,6 +87,26 @@ test('appends a header correctly with no existing one', () => {
6887
});
6988
});
7089

90+
test('setStatusCode returns the response', () => {
91+
const response = new Response();
92+
expect(response.setStatusCode(418)).toBe(response);
93+
});
94+
95+
test('setBody returns the response', () => {
96+
const response = new Response();
97+
expect(response.setBody('Hello')).toBe(response);
98+
});
99+
100+
test('setHeader returns the response', () => {
101+
const response = new Response();
102+
expect(response.setHeaders({ 'X-Test': 'Hello' })).toBe(response);
103+
});
104+
105+
test('appendHeader returns the response', () => {
106+
const response = new Response();
107+
expect(response.appendHeader('X-Test', 'Hello')).toBe(response);
108+
});
109+
71110
test('calls express response correctly', () => {
72111
const mockRes = {
73112
status: jest.fn(),

packages/runtime-handler/src/dev-runtime/internal/response.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,64 @@ import debug from '../utils/debug';
44

55
const log = debug('twilio-runtime-handler:dev:response');
66

7+
type ResponseOptions = {
8+
headers?: Headers;
9+
statusCode?: number;
10+
body?: object | string;
11+
};
12+
713
type HeaderValue = number | string;
814
type Headers = {
915
[key: string]: HeaderValue;
1016
};
1117

1218
export class Response implements TwilioResponse {
13-
private body: undefined | any;
19+
private body: null | any;
1420
private statusCode: number;
1521
private headers: Headers;
1622

17-
constructor() {
18-
this.body = undefined;
23+
constructor(options?: ResponseOptions) {
24+
this.body = null;
1925
this.statusCode = 200;
2026
this.headers = {};
27+
28+
if (options && options.statusCode) {
29+
this.statusCode = options.statusCode;
30+
}
31+
if (options && options.body) {
32+
this.body = options.body;
33+
}
34+
if (options && options.headers) {
35+
this.headers = options.headers;
36+
}
2137
}
2238

23-
setStatusCode(statusCode: number): void {
39+
setStatusCode(statusCode: number): Response {
2440
log('Setting status code to %d', statusCode);
2541
this.statusCode = statusCode;
42+
return this;
2643
}
2744

28-
setBody(body: object | string): void {
45+
setBody(body: object | string): Response {
2946
log('Setting response body to %o', body);
3047
this.body = body;
48+
return this;
3149
}
3250

33-
setHeaders(headersObject: Headers): void {
51+
setHeaders(headersObject: Headers): Response {
3452
log('Setting headers to: %P', headersObject);
3553
if (typeof headersObject !== 'object') {
36-
return;
54+
return this;
3755
}
3856
this.headers = headersObject;
57+
return this;
3958
}
4059

41-
appendHeader(key: string, value: HeaderValue): void {
60+
appendHeader(key: string, value: HeaderValue): Response {
4261
log('Appending header for %s', key, value);
4362
this.headers = this.headers || {};
4463
this.headers[key] = value;
64+
return this;
4565
}
4666

4767
applyToExpressResponse(res: ExpressResponse): void {

packages/twilio-run/__tests__/runtime/internal/response.test.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,30 @@ import { Response as ExpressResponse } from 'express';
33

44
test('has correct defaults', () => {
55
const response = new Response();
6-
expect(response['body']).toBeUndefined();
6+
expect(response['body']).toBeNull();
77
expect(response['statusCode']).toBe(200);
88
expect(response['headers']).toEqual({});
99
});
1010

11+
test('sets status code, body and headers from constructor', () => {
12+
const response = new Response({
13+
headers: {
14+
'Access-Control-Allow-Origin': 'example.com',
15+
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE',
16+
'Access-Control-Allow-Headers': 'Content-Type',
17+
},
18+
body: 'Error',
19+
statusCode: 400,
20+
});
21+
expect(response['statusCode']).toBe(400);
22+
expect(response['body']).toBe('Error');
23+
expect(response['headers']).toEqual({
24+
'Access-Control-Allow-Origin': 'example.com',
25+
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE',
26+
'Access-Control-Allow-Headers': 'Content-Type',
27+
});
28+
});
29+
1130
test('sets status code', () => {
1231
const response = new Response();
1332
expect(response['statusCode']).toBe(200);
@@ -17,7 +36,7 @@ test('sets status code', () => {
1736

1837
test('sets body correctly', () => {
1938
const response = new Response();
20-
expect(response['body']).toBeUndefined();
39+
expect(response['body']).toBeNull();
2140
response.setBody('Hello');
2241
expect(response['body']).toBe('Hello');
2342
response.setBody({ url: 'https://dkundel.com' });
@@ -68,6 +87,26 @@ test('appends a header correctly with no existing one', () => {
6887
});
6988
});
7089

90+
test('setStatusCode returns the response', () => {
91+
const response = new Response();
92+
expect(response.setStatusCode(418)).toBe(response);
93+
});
94+
95+
test('setBody returns the response', () => {
96+
const response = new Response();
97+
expect(response.setBody('Hello')).toBe(response);
98+
});
99+
100+
test('setHeader returns the response', () => {
101+
const response = new Response();
102+
expect(response.setHeaders({ 'X-Test': 'Hello' })).toBe(response);
103+
});
104+
105+
test('appendHeader returns the response', () => {
106+
const response = new Response();
107+
expect(response.appendHeader('X-Test', 'Hello')).toBe(response);
108+
});
109+
71110
test('calls express response correctly', () => {
72111
const mockRes = {
73112
status: jest.fn(),

packages/twilio-run/src/runtime/internal/response.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,64 @@ import { getDebugFunction } from '../../utils/logger';
44

55
const debug = getDebugFunction('twilio-run:response');
66

7+
type ResponseOptions = {
8+
headers?: Headers;
9+
statusCode?: number;
10+
body?: object | string;
11+
};
12+
713
type HeaderValue = number | string;
814
type Headers = {
915
[key: string]: HeaderValue;
1016
};
1117

1218
export class Response implements TwilioResponse {
13-
private body: undefined | any;
19+
private body: null | any;
1420
private statusCode: number;
1521
private headers: Headers;
1622

17-
constructor() {
18-
this.body = undefined;
23+
constructor(options?: ResponseOptions) {
24+
this.body = null;
1925
this.statusCode = 200;
2026
this.headers = {};
27+
28+
if (options && options.statusCode) {
29+
this.statusCode = options.statusCode;
30+
}
31+
if (options && options.body) {
32+
this.body = options.body;
33+
}
34+
if (options && options.headers) {
35+
this.headers = options.headers;
36+
}
2137
}
2238

23-
setStatusCode(statusCode: number): void {
39+
setStatusCode(statusCode: number): Response {
2440
debug('Setting status code to %d', statusCode);
2541
this.statusCode = statusCode;
42+
return this;
2643
}
2744

28-
setBody(body: object | string): void {
45+
setBody(body: object | string): Response {
2946
debug('Setting response body to %o', body);
3047
this.body = body;
48+
return this;
3149
}
3250

33-
setHeaders(headersObject: Headers): void {
51+
setHeaders(headersObject: Headers): Response {
3452
debug('Setting headers to: %P', headersObject);
3553
if (typeof headersObject !== 'object') {
36-
return;
54+
return this;
3755
}
3856
this.headers = headersObject;
57+
return this;
3958
}
4059

41-
appendHeader(key: string, value: HeaderValue): void {
60+
appendHeader(key: string, value: HeaderValue): Response {
4261
debug('Appending header for %s', key, value);
4362
this.headers = this.headers || {};
4463
this.headers[key] = value;
64+
return this;
4565
}
4666

4767
applyToExpressResponse(res: ExpressResponse): void {

0 commit comments

Comments
 (0)