Skip to content

Commit b737f24

Browse files
authored
Merge pull request #546 from abraham/async-refresh
Improve hash response parsing
2 parents 5616046 + 43f3a56 commit b737f24

File tree

4 files changed

+371
-3
lines changed

4 files changed

+371
-3
lines changed

config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"overrideCommits": [
88
"b1d8f95b506e2d734876ef47ec0f4e1feb4f5618",
99
"c6b60e2470226fd7bae1fcfebd4a372775f83419",
10-
"9a38bf8d99187663fbb905e4aba0205735accf32"
10+
"9a38bf8d99187663fbb905e4aba0205735accf32",
11+
"15751167f62fb97fc2e25c76f986b4e363e2a477"
1112
]
1213
}

dist/schema.json

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5215,7 +5215,7 @@
52155215
],
52165216
"responses": {
52175217
"200": {
5218-
"description": "[AsyncRefresh]",
5218+
"description": "Hash with a single key of `async_refresh` with value of [AsyncRefresh]",
52195219
"headers": {
52205220
"X-RateLimit-Limit": {
52215221
"$ref": "#/components/headers/X-RateLimit-Limit"
@@ -5230,7 +5230,15 @@
52305230
"content": {
52315231
"application/json": {
52325232
"schema": {
5233-
"$ref": "#/components/schemas/AsyncRefresh"
5233+
"type": "object",
5234+
"properties": {
5235+
"async_refresh": {
5236+
"$ref": "#/components/schemas/AsyncRefresh"
5237+
}
5238+
},
5239+
"required": [
5240+
"async_refresh"
5241+
]
52345242
}
52355243
}
52365244
}
@@ -16696,6 +16704,24 @@
1669616704
"X-RateLimit-Reset": {
1669716705
"$ref": "#/components/headers/X-RateLimit-Reset"
1669816706
}
16707+
},
16708+
"content": {
16709+
"application/json": {
16710+
"schema": {
16711+
"type": "object",
16712+
"properties": {
16713+
"merged": {
16714+
"type": "boolean"
16715+
}
16716+
},
16717+
"required": [
16718+
"merged"
16719+
]
16720+
},
16721+
"example": {
16722+
"merged": false
16723+
}
16724+
}
1669916725
}
1670016726
},
1670116727
"401": {
@@ -16811,6 +16837,24 @@
1681116837
"X-RateLimit-Reset": {
1681216838
"$ref": "#/components/headers/X-RateLimit-Reset"
1681316839
}
16840+
},
16841+
"content": {
16842+
"application/json": {
16843+
"schema": {
16844+
"type": "object",
16845+
"properties": {
16846+
"count": {
16847+
"type": "integer"
16848+
}
16849+
},
16850+
"required": [
16851+
"count"
16852+
]
16853+
},
16854+
"example": {
16855+
"count": 42
16856+
}
16857+
}
1681416858
}
1681516859
},
1681616860
"401": {
@@ -17736,6 +17780,24 @@
1773617780
"X-RateLimit-Reset": {
1773717781
"$ref": "#/components/headers/X-RateLimit-Reset"
1773817782
}
17783+
},
17784+
"content": {
17785+
"application/json": {
17786+
"schema": {
17787+
"type": "object",
17788+
"properties": {
17789+
"count": {
17790+
"type": "integer"
17791+
}
17792+
},
17793+
"required": [
17794+
"count"
17795+
]
17796+
},
17797+
"example": {
17798+
"count": 42
17799+
}
17800+
}
1773917801
}
1774017802
},
1774117803
"401": {
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
import { TypeParser } from '../../generators/TypeParser';
2+
import { UtilityHelpers } from '../../generators/UtilityHelpers';
3+
import { OpenAPISpec } from '../../interfaces/OpenAPISchema';
4+
5+
describe('TypeParser - Hash wrapper pattern handling', () => {
6+
let typeParser: TypeParser;
7+
let spec: OpenAPISpec;
8+
9+
beforeEach(() => {
10+
const utilityHelpers = new UtilityHelpers();
11+
typeParser = new TypeParser(utilityHelpers);
12+
13+
// Create a minimal spec with some test entities
14+
spec = {
15+
openapi: '3.1.0',
16+
info: { title: 'Test', version: '1.0.0' },
17+
paths: {},
18+
components: {
19+
schemas: {
20+
AsyncRefresh: {
21+
type: 'object',
22+
properties: {
23+
id: { type: 'string' },
24+
status: { type: 'string' },
25+
},
26+
},
27+
},
28+
},
29+
};
30+
});
31+
32+
describe('Hash with a single key of `key_name`', () => {
33+
it('should handle simple hash wrapper with count', () => {
34+
const result = typeParser.parseResponseSchema(
35+
'Hash with a single key of `count`',
36+
spec
37+
);
38+
39+
expect(result).toEqual({
40+
type: 'object',
41+
properties: {
42+
count: {
43+
type: 'integer',
44+
},
45+
},
46+
required: ['count'],
47+
});
48+
});
49+
50+
it('should handle simple hash wrapper with different key name', () => {
51+
const result = typeParser.parseResponseSchema(
52+
'Hash with a single key of `merged`',
53+
spec
54+
);
55+
56+
expect(result).toEqual({
57+
type: 'object',
58+
properties: {
59+
merged: {
60+
type: 'integer',
61+
},
62+
},
63+
required: ['merged'],
64+
});
65+
});
66+
});
67+
68+
describe('Hash with a single key of `key_name` with value of [Entity]', () => {
69+
it('should handle hash wrapper with entity reference', () => {
70+
const result = typeParser.parseResponseSchema(
71+
'Hash with a single key of `async_refresh` with value of [AsyncRefresh]',
72+
spec
73+
);
74+
75+
expect(result).toEqual({
76+
type: 'object',
77+
properties: {
78+
async_refresh: {
79+
$ref: '#/components/schemas/AsyncRefresh',
80+
},
81+
},
82+
required: ['async_refresh'],
83+
});
84+
});
85+
86+
it('should handle hash wrapper with different key and entity', () => {
87+
// Add another entity to the spec
88+
spec.components!.schemas!['Status'] = {
89+
type: 'object',
90+
properties: {
91+
id: { type: 'string' },
92+
content: { type: 'string' },
93+
},
94+
};
95+
96+
const result = typeParser.parseResponseSchema(
97+
'Hash with a single key of `status` with value of [Status]',
98+
spec
99+
);
100+
101+
expect(result).toEqual({
102+
type: 'object',
103+
properties: {
104+
status: {
105+
$ref: '#/components/schemas/Status',
106+
},
107+
},
108+
required: ['status'],
109+
});
110+
});
111+
112+
it('should return null if entity does not exist in schema', () => {
113+
const result = typeParser.parseResponseSchema(
114+
'Hash with a single key of `nonexistent` with value of [NonexistentEntity]',
115+
spec
116+
);
117+
118+
// Should fall through to later patterns or return null
119+
expect(result).toBeNull();
120+
});
121+
});
122+
123+
describe('Hash with a single [type] attribute `key_name`', () => {
124+
it('should handle boolean attribute', () => {
125+
const result = typeParser.parseResponseSchema(
126+
'Hash with a single boolean attribute `merged`',
127+
spec
128+
);
129+
130+
expect(result).toEqual({
131+
type: 'object',
132+
properties: {
133+
merged: {
134+
type: 'boolean',
135+
},
136+
},
137+
required: ['merged'],
138+
});
139+
});
140+
141+
it('should handle integer attribute', () => {
142+
const result = typeParser.parseResponseSchema(
143+
'Hash with a single integer attribute `total`',
144+
spec
145+
);
146+
147+
expect(result).toEqual({
148+
type: 'object',
149+
properties: {
150+
total: {
151+
type: 'integer',
152+
},
153+
},
154+
required: ['total'],
155+
});
156+
});
157+
158+
it('should handle string attribute', () => {
159+
const result = typeParser.parseResponseSchema(
160+
'Hash with a single string attribute `name`',
161+
spec
162+
);
163+
164+
expect(result).toEqual({
165+
type: 'object',
166+
properties: {
167+
name: {
168+
type: 'string',
169+
},
170+
},
171+
required: ['name'],
172+
});
173+
});
174+
});
175+
176+
describe('Case insensitivity', () => {
177+
it('should handle case variations in hash pattern', () => {
178+
const result = typeParser.parseResponseSchema(
179+
'hash with a single key of `count`',
180+
spec
181+
);
182+
183+
expect(result).toEqual({
184+
type: 'object',
185+
properties: {
186+
count: {
187+
type: 'integer',
188+
},
189+
},
190+
required: ['count'],
191+
});
192+
});
193+
194+
it('should handle case variations in entity pattern', () => {
195+
const result = typeParser.parseResponseSchema(
196+
'HASH WITH A SINGLE KEY OF `async_refresh` WITH VALUE OF [AsyncRefresh]',
197+
spec
198+
);
199+
200+
expect(result).toEqual({
201+
type: 'object',
202+
properties: {
203+
async_refresh: {
204+
$ref: '#/components/schemas/AsyncRefresh',
205+
},
206+
},
207+
required: ['async_refresh'],
208+
});
209+
});
210+
211+
it('should handle case variations in attribute pattern', () => {
212+
const result = typeParser.parseResponseSchema(
213+
'HASH WITH A SINGLE BOOLEAN ATTRIBUTE `enabled`',
214+
spec
215+
);
216+
217+
expect(result).toEqual({
218+
type: 'object',
219+
properties: {
220+
enabled: {
221+
type: 'boolean',
222+
},
223+
},
224+
required: ['enabled'],
225+
});
226+
});
227+
});
228+
});

0 commit comments

Comments
 (0)