Skip to content

Commit 2f06459

Browse files
VirtueMeclaude
andauthored
test(apiGateway): improve requestValidators coverage to 100% (#740)
Adds tests for the three previously uncovered paths: - schema object without explicit schema property (implicit object) - plain string schema not referencing a provider model - createProviderModel: basic, with name, with description, implicit schema Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent dfbf54b commit 2f06459

1 file changed

Lines changed: 209 additions & 42 deletions

File tree

lib/deploy/events/apiGateway/requestValidators.test.js

Lines changed: 209 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,78 +8,245 @@ describe('#requestValidator()', () => {
88
let serverless;
99
let serverlessStepFunctions;
1010

11-
beforeEach(() => {
12-
const options = {
13-
stage: 'dev',
14-
region: 'us-east-1',
15-
};
11+
function setup(events, providerApiGateway) {
12+
const options = { stage: 'dev', region: 'us-east-1' };
1613

1714
serverless = createServerless();
1815
serverless.service.service = 'step-functions';
1916
serverless.service.provider.compiledCloudFormationTemplate = {
2017
Resources: {
21-
ApiGatewayMethodFirstPost: {
22-
Properties: {},
23-
},
18+
ApiGatewayMethodFirstPost: { Properties: {} },
19+
ApiGatewayMethodSecondPost: { Properties: {} },
2420
},
2521
};
2622

23+
if (providerApiGateway) {
24+
serverless.service.provider.apiGateway = providerApiGateway;
25+
}
26+
2727
serverlessStepFunctions = new ServerlessStepFunctions(serverless, options);
2828
serverlessStepFunctions.apiGatewayRestApiLogicalId = 'ApiGatewayRestApi';
2929
serverlessStepFunctions.apiGatewayResourceNames = {
3030
'foo/bar1': 'apiGatewayResourceNamesFirst',
3131
'foo/bar2': 'apiGatewayResourceNamesSecond',
3232
};
33-
serverlessStepFunctions.pluginhttpValidated = {
34-
events: [
35-
{
33+
serverlessStepFunctions.apiGatewayResources = {
34+
'foo/bar1': { name: 'First', resourceLogicalId: 'ApiGatewayResourceFirst' },
35+
'foo/bar2': { name: 'Second', resourceLogicalId: 'ApiGatewayResourceSecond' },
36+
};
37+
serverlessStepFunctions.pluginhttpValidated = { events };
38+
}
39+
40+
function getResources() {
41+
return serverlessStepFunctions.serverless.service.provider
42+
.compiledCloudFormationTemplate.Resources;
43+
}
44+
45+
describe('#compileRequestValidators()', () => {
46+
it('should create a model and validator for a schema object with explicit schema property', () => {
47+
setup([{
48+
stateMachineName: 'first',
49+
http: {
50+
path: 'foo/bar1',
51+
method: 'post',
52+
request: {
53+
schemas: {
54+
'application/json': {
55+
name: 'StartExecutionSchema',
56+
schema: { type: 'object' },
57+
},
58+
},
59+
},
60+
},
61+
}]);
62+
63+
return serverlessStepFunctions.compileRequestValidators().then(() => {
64+
const resources = getResources();
65+
expect(resources).to.have.property('ApiGatewayMethodFirstPostApplicationJsonModel');
66+
expect(resources).to.have.property('ApiGatewayStepfunctionsRequestValidator');
67+
const model = resources.ApiGatewayMethodFirstPostApplicationJsonModel;
68+
expect(model.Properties.Name).to.equal('StartExecutionSchema');
69+
expect(model.Properties.Schema).to.deep.equal({ type: 'object' });
70+
});
71+
});
72+
73+
it('should use the whole object as schema when schema object has no explicit schema property', () => {
74+
const implicitSchema = { type: 'object', properties: { id: { type: 'string' } } };
75+
setup([{
76+
stateMachineName: 'first',
77+
http: {
78+
path: 'foo/bar1',
79+
method: 'post',
80+
request: {
81+
schemas: {
82+
'application/json': implicitSchema,
83+
},
84+
},
85+
},
86+
}]);
87+
88+
return serverlessStepFunctions.compileRequestValidators().then(() => {
89+
const resources = getResources();
90+
expect(resources).to.have.property('ApiGatewayMethodFirstPostApplicationJsonModel');
91+
const model = resources.ApiGatewayMethodFirstPostApplicationJsonModel;
92+
expect(model.Properties.Schema).to.deep.equal(implicitSchema);
93+
expect(model.Properties.Name).to.equal(undefined);
94+
});
95+
});
96+
97+
it('should use a plain string as schema definition when schemaConfig is a string not referencing a provider model', () => {
98+
setup([{
99+
stateMachineName: 'first',
100+
http: {
101+
path: 'foo/bar1',
102+
method: 'post',
103+
request: {
104+
schemas: {
105+
'application/json': 'arn:aws:apigateway:us-east-1::/restapis/foo/models/bar',
106+
},
107+
},
108+
},
109+
}]);
110+
111+
return serverlessStepFunctions.compileRequestValidators().then(() => {
112+
const resources = getResources();
113+
expect(resources).to.have.property('ApiGatewayMethodFirstPostApplicationJsonModel');
114+
const model = resources.ApiGatewayMethodFirstPostApplicationJsonModel;
115+
expect(model.Properties.Schema).to.equal('arn:aws:apigateway:us-east-1::/restapis/foo/models/bar');
116+
});
117+
});
118+
119+
it('should not create a validator when no schemas are defined on the event', () => {
120+
setup([{
121+
stateMachineName: 'first',
122+
http: {
123+
path: 'foo/bar1',
124+
method: 'post',
125+
},
126+
}]);
127+
128+
return serverlessStepFunctions.compileRequestValidators().then(() => {
129+
const resources = getResources();
130+
expect(resources).to.not.have.property('ApiGatewayStepfunctionsRequestValidator');
131+
});
132+
});
133+
});
134+
135+
describe('#createProviderModel()', () => {
136+
it('should create a model resource using a provider-level schema reference', () => {
137+
setup(
138+
[{
36139
stateMachineName: 'first',
37140
http: {
38141
path: 'foo/bar1',
39142
method: 'post',
40143
request: {
41144
schemas: {
42-
'application/json': {
43-
name: 'StartExecutionSchema',
44-
schema: {},
45-
},
145+
'application/json': 'CreateRequest',
146+
},
147+
},
148+
},
149+
}],
150+
{
151+
request: {
152+
schemas: {
153+
CreateRequest: {
154+
schema: { type: 'object' },
46155
},
47156
},
48157
},
49158
},
159+
);
160+
161+
return serverlessStepFunctions.compileRequestValidators().then(() => {
162+
const resources = getResources();
163+
expect(resources).to.have.property('ApiGatewayCreateRequestModel');
164+
const model = resources.ApiGatewayCreateRequestModel;
165+
expect(model.Properties.Schema).to.deep.equal({ type: 'object' });
166+
expect(model.Properties.ContentType).to.equal('application/json');
167+
});
168+
});
169+
170+
it('should set Name on provider model when schemaConfig.name is present', () => {
171+
setup(
172+
[{
173+
stateMachineName: 'first',
174+
http: {
175+
path: 'foo/bar1',
176+
method: 'post',
177+
request: { schemas: { 'application/json': 'CreateRequest' } },
178+
},
179+
}],
50180
{
51-
stateMachineName: 'second',
181+
request: {
182+
schemas: {
183+
CreateRequest: {
184+
name: 'MyModel',
185+
schema: { type: 'object' },
186+
},
187+
},
188+
},
189+
},
190+
);
191+
192+
return serverlessStepFunctions.compileRequestValidators().then(() => {
193+
const model = getResources().ApiGatewayCreateRequestModel;
194+
expect(model.Properties.Name).to.equal('MyModel');
195+
});
196+
});
197+
198+
it('should set Description on provider model when schemaConfig.description is present', () => {
199+
setup(
200+
[{
201+
stateMachineName: 'first',
52202
http: {
53-
path: 'foo/bar2',
203+
path: 'foo/bar1',
54204
method: 'post',
55-
private: true,
205+
request: { schemas: { 'application/json': 'CreateRequest' } },
206+
},
207+
}],
208+
{
209+
request: {
210+
schemas: {
211+
CreateRequest: {
212+
description: 'Request payload for create',
213+
schema: { type: 'object' },
214+
},
215+
},
56216
},
57217
},
58-
],
59-
};
60-
serverlessStepFunctions.apiGatewayResources = {
61-
'foo/bar1': {
62-
name: 'First',
63-
resourceLogicalId: 'ApiGatewayResourceFirst',
64-
},
218+
);
65219

66-
'foo/bar2': {
67-
name: 'Second',
68-
resourceLogicalId: 'ApiGatewayResourceSecond',
69-
},
70-
};
71-
});
220+
return serverlessStepFunctions.compileRequestValidators().then(() => {
221+
const model = getResources().ApiGatewayCreateRequestModel;
222+
expect(model.Properties.Description).to.equal('Request payload for create');
223+
});
224+
});
72225

73-
describe('#compileRequestValidators()', () => {
74-
it('should process schema from http event request schemas', () => serverlessStepFunctions
75-
.compileRequestValidators().then(() => {
76-
expect(serverlessStepFunctions.serverless.service.provider.compiledCloudFormationTemplate
77-
.Resources)
78-
.to.have.property('ApiGatewayMethodFirstPostApplicationJsonModel');
79-
80-
expect(serverlessStepFunctions.serverless.service.provider.compiledCloudFormationTemplate
81-
.Resources)
82-
.to.have.property('ApiGatewayStepfunctionsRequestValidator');
83-
}));
226+
it('should use the whole schemaConfig as definition when no schema property is present', () => {
227+
const rawSchema = { type: 'object', properties: { id: { type: 'string' } } };
228+
setup(
229+
[{
230+
stateMachineName: 'first',
231+
http: {
232+
path: 'foo/bar1',
233+
method: 'post',
234+
request: { schemas: { 'application/json': 'CreateRequest' } },
235+
},
236+
}],
237+
{
238+
request: {
239+
schemas: {
240+
CreateRequest: rawSchema,
241+
},
242+
},
243+
},
244+
);
245+
246+
return serverlessStepFunctions.compileRequestValidators().then(() => {
247+
const model = getResources().ApiGatewayCreateRequestModel;
248+
expect(model.Properties.Schema).to.deep.equal(rawSchema);
249+
});
250+
});
84251
});
85252
});

0 commit comments

Comments
 (0)