Skip to content

Commit 48fa398

Browse files
chrisolson443Chris Olson
andauthored
Case insensitive response header (#72)
* Make response header validation cas-insensitive * Added jest config files and dependencies for debuging spec files * Added changeset * Ran prettier * Remove reflect-metadata dependency * Lowercase header name to be validated * Move jest config from package.json to jest.config * prettier formatting * Simplify tests with toThrowErrorMatchingSnapshot * Change parameter name to fix duplicate name scope warning * Simplify no error expectation. Formatting * remove jest.setup.js * Remove setupFilesAfterEnv prop * prettier * Remove package-lock.json Co-authored-by: Chris Olson <chris.olson@dat.com>
1 parent 2fb84d5 commit 48fa398

File tree

7 files changed

+100
-26
lines changed

7 files changed

+100
-26
lines changed

.changeset/nice-terms-hide.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'oas3-chow-chow': minor
3+
---
4+
5+
Make response header name validation case-insensitive
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Response validateResponseByOperationId should fail if header value is invalid 1`] = `"ResponseValidationError: Schema validation error"`;
4+
5+
exports[`Response validateResponseByPath should fail if header value is invalid 1`] = `"ResponseValidationError: Schema validation error"`;

__test__/fixtures/response.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
"/header": {
8787
"get": {
8888
"summary": "Info for a specific pet",
89-
"operationId": "showHeader",
89+
"operationId": "getHeader",
9090
"tags": ["pets"],
9191
"parameters": [],
9292
"responses": {

__test__/response.spec.ts

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,20 +197,62 @@ describe('Response', () => {
197197
}).toThrow();
198198
});
199199

200-
it('should fail if header is invalid', () => {
200+
it('validateResponseByPath should fail if header value is invalid', () => {
201201
const responseMeta: ResponseMeta = {
202202
status: 200,
203203
header: {
204204
'content-type': 'application/json',
205205
version: [1, 2],
206206
},
207207
};
208-
expect(() => {
209-
chowchow.validateResponseByPath('/header', 'get', responseMeta);
210-
}).toThrow();
211-
expect(() => {
212-
chowchow.validateResponseByOperationId('getHeader', responseMeta);
213-
}).toThrow();
208+
209+
expect(() =>
210+
chowchow.validateResponseByPath('/header', 'get', responseMeta)
211+
).toThrowErrorMatchingSnapshot();
212+
});
213+
214+
it('validateResponseByOperationId should fail if header value is invalid', () => {
215+
const responseMeta: ResponseMeta = {
216+
status: 200,
217+
header: {
218+
'content-type': 'application/json',
219+
version: [1, 2],
220+
},
221+
};
222+
223+
expect(() =>
224+
chowchow.validateResponseByOperationId('getHeader', responseMeta)
225+
).toThrowErrorMatchingSnapshot();
226+
});
227+
228+
it('should succeed if header case is different than spec', () => {
229+
const lowercaseHeaderName = 'version';
230+
const responseMeta: ResponseMeta = {
231+
status: 200,
232+
header: {
233+
[lowercaseHeaderName]: '1',
234+
},
235+
};
236+
237+
// test validateResponseByPath
238+
expect(() =>
239+
chowchow.validateResponseByPath('/header', 'get', responseMeta)
240+
).not.toThrow();
241+
});
242+
243+
it('should succeed if header case is same as spec', () => {
244+
const uppercaseHeaderName = 'Version';
245+
const responseMeta: ResponseMeta = {
246+
status: 200,
247+
header: {
248+
[uppercaseHeaderName]: '1',
249+
},
250+
};
251+
252+
// test validateResponseByPath
253+
expect(() =>
254+
chowchow.validateResponseByPath('/header', 'get', responseMeta)
255+
).not.toThrow();
214256
});
215257

216258
it('should fail if required header is empty', () => {

jest.config.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module.exports = {
2+
preset: 'ts-jest',
3+
globals: {
4+
'ts-jest': {
5+
tsconfig: 'tsconfig.json'
6+
}
7+
},
8+
roots: [
9+
"<rootDir>/src",
10+
"<rootDir>__test__"
11+
],
12+
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$',
13+
moduleFileExtensions: [
14+
'ts',
15+
'tsx',
16+
'js',
17+
'jsx',
18+
'json',
19+
'node'
20+
],
21+
testEnvironment: 'node',
22+
transform: {
23+
"^.+\\.tsx?$": "ts-jest"
24+
}
25+
};

package.json

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,6 @@
2222
"prepublishOnly": "rm -rf lib && tsc",
2323
"release": "yarn prepublishOnly && changeset publish"
2424
},
25-
"jest": {
26-
"transform": {
27-
"^.+\\.tsx?$": "ts-jest"
28-
},
29-
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
30-
"moduleFileExtensions": [
31-
"ts",
32-
"tsx",
33-
"js",
34-
"jsx",
35-
"json",
36-
"node"
37-
]
38-
},
3925
"prettier": {
4026
"singleQuote": true
4127
},

src/compiler/CompiledResponseHeader.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,16 @@ export default class CompiledResponseHeader {
2020
if (this.ignoreHeaders.includes(name)) {
2121
continue;
2222
}
23+
24+
const headerNameLower = name.toLowerCase();
2325
const header = headers[name] as HeaderObject;
2426

2527
if (header.schema) {
26-
this.headerSchema.properties![name] = header.schema;
28+
this.headerSchema.properties![headerNameLower] = header.schema;
2729
}
2830

2931
if (header.required) {
30-
this.headerSchema.required!.push(name);
32+
this.headerSchema.required!.push(headerNameLower);
3133
}
3234
}
3335
this.compiledSchema = new CompiledSchema(
@@ -36,9 +38,18 @@ export default class CompiledResponseHeader {
3638
);
3739
}
3840

39-
public validate(value: any = {}) {
41+
public validate(header: any = {}) {
4042
try {
41-
this.compiledSchema.validate(value);
43+
// Before validation, lowercase the header name, since header name is also lowercased in compiledSchema
44+
const newHeader = Object.entries(header).reduce(
45+
(newObject: any, [key, value]) => {
46+
newObject[key.toLowerCase()] = value;
47+
return newObject;
48+
},
49+
{}
50+
);
51+
52+
this.compiledSchema.validate(newHeader);
4253
} catch (e) {
4354
throw new ChowError('Schema validation error', {
4455
in: 'response-header',

0 commit comments

Comments
 (0)