@@ -45,9 +45,7 @@ describe('validatePlanSteps — REQUIRED_PARAMS', () => {
4545 params : { AWSServiceName : 'config.amazonaws.com' } ,
4646 } ) ,
4747 ] ) ;
48- expect (
49- errors . filter ( ( e ) => e . includes ( 'AWSServiceName' ) ) ,
50- ) . toHaveLength ( 0 ) ;
48+ expect ( errors . filter ( ( e ) => e . includes ( 'AWSServiceName' ) ) ) . toHaveLength ( 0 ) ;
5149 } ) ;
5250
5351 it . each ( [ '' , null , undefined ] ) (
@@ -84,6 +82,126 @@ describe('validatePlanSteps — REQUIRED_PARAMS', () => {
8482 ) . toHaveLength ( 1 ) ;
8583 } ) ;
8684
85+ it ( 'requires a group identifier for property-based security-group revoke commands' , ( ) => {
86+ const errors = validatePlanSteps ( [
87+ step ( {
88+ service : 'ec2' ,
89+ command : 'RevokeSecurityGroupIngressCommand' ,
90+ params : {
91+ IpPermissions : [
92+ {
93+ IpProtocol : 'tcp' ,
94+ FromPort : 22 ,
95+ ToPort : 22 ,
96+ IpRanges : [ { CidrIp : '0.0.0.0/0' } ] ,
97+ } ,
98+ ] ,
99+ } ,
100+ } ) ,
101+ ] ) ;
102+
103+ expect ( errors ) . toEqual (
104+ expect . arrayContaining ( [
105+ 'Step 1 (RevokeSecurityGroupIngressCommand): One of "GroupId" or "GroupName" is required' ,
106+ ] ) ,
107+ ) ;
108+ } ) ;
109+
110+ it ( 'rejects revoke commands that mix rule IDs with rule properties' , ( ) => {
111+ const errors = validatePlanSteps ( [
112+ step ( {
113+ service : 'ec2' ,
114+ command : 'RevokeSecurityGroupIngressCommand' ,
115+ params : {
116+ GroupId : 'sg-0123abc' ,
117+ SecurityGroupRuleIds : [ 'sgr-0123abc' ] ,
118+ IpPermissions : [
119+ {
120+ IpProtocol : 'tcp' ,
121+ FromPort : 22 ,
122+ ToPort : 22 ,
123+ IpRanges : [ { CidrIp : '0.0.0.0/0' } ] ,
124+ } ,
125+ ] ,
126+ } ,
127+ } ) ,
128+ ] ) ;
129+
130+ expect ( errors ) . toEqual (
131+ expect . arrayContaining ( [
132+ 'Step 1 (RevokeSecurityGroupIngressCommand): SecurityGroupRuleIds cannot be combined with rule property params' ,
133+ ] ) ,
134+ ) ;
135+ } ) ;
136+
137+ it ( 'requires a rule selector for security-group revoke commands' , ( ) => {
138+ const errors = validatePlanSteps ( [
139+ step ( {
140+ service : 'ec2' ,
141+ command : 'RevokeSecurityGroupIngressCommand' ,
142+ params : { GroupId : 'sg-0123abc' } ,
143+ } ) ,
144+ ] ) ;
145+
146+ expect ( errors ) . toEqual (
147+ expect . arrayContaining ( [
148+ 'Step 1 (RevokeSecurityGroupIngressCommand): One of "SecurityGroupRuleIds" or rule property params is required' ,
149+ ] ) ,
150+ ) ;
151+ } ) ;
152+
153+ it ( 'allows property-based security-group revoke commands when GroupId is present' , ( ) => {
154+ const errors = validatePlanSteps ( [
155+ step ( {
156+ service : 'ec2' ,
157+ command : 'RevokeSecurityGroupIngressCommand' ,
158+ params : {
159+ GroupId : 'sg-0123abc' ,
160+ IpPermissions : [
161+ {
162+ IpProtocol : 'tcp' ,
163+ FromPort : 22 ,
164+ ToPort : 22 ,
165+ IpRanges : [ { CidrIp : '0.0.0.0/0' } ] ,
166+ } ,
167+ ] ,
168+ } ,
169+ } ) ,
170+ ] ) ;
171+
172+ expect (
173+ errors . some ( ( e ) => / R e v o k e S e c u r i t y G r o u p I n g r e s s C o m m a n d / . test ( e ) ) ,
174+ ) . toBe ( false ) ;
175+ } ) ;
176+
177+ it ( 'allows security-group revoke commands that use SecurityGroupRuleIds only' , ( ) => {
178+ const errors = validatePlanSteps ( [
179+ step ( {
180+ service : 'ec2' ,
181+ command : 'RevokeSecurityGroupIngressCommand' ,
182+ params : { SecurityGroupRuleIds : [ 'sgr-0123abc' ] } ,
183+ } ) ,
184+ ] ) ;
185+
186+ expect ( errors . some ( ( e ) => / G r o u p I d | G r o u p N a m e / . test ( e ) ) ) . toBe ( false ) ;
187+ } ) ;
188+
189+ it ( 'treats empty one-of arrays as missing values' , ( ) => {
190+ const errors = validatePlanSteps ( [
191+ step ( {
192+ service : 'ec2' ,
193+ command : 'RevokeSecurityGroupIngressCommand' ,
194+ params : { SecurityGroupRuleIds : [ ] } ,
195+ } ) ,
196+ ] ) ;
197+
198+ expect ( errors ) . toEqual (
199+ expect . arrayContaining ( [
200+ 'Step 1 (RevokeSecurityGroupIngressCommand): One of "SecurityGroupRuleIds" or rule property params is required' ,
201+ ] ) ,
202+ ) ;
203+ } ) ;
204+
87205 it ( 'does NOT apply required-param checks to commands not in REQUIRED_PARAMS' , ( ) => {
88206 // PutBucketVersioningCommand isn't in REQUIRED_PARAMS — should pass
89207 // even with no params (the AWS SDK will surface its own errors then).
@@ -101,7 +219,11 @@ describe('validatePlanSteps — REQUIRED_PARAMS', () => {
101219
102220 it ( 'uses the step index in the error message so customers know which step is broken' , ( ) => {
103221 const errors = validatePlanSteps ( [
104- step ( { service : 's3' , command : 'PutBucketVersioningCommand' , params : { Bucket : 'b' , VersioningConfiguration : { Status : 'Enabled' } } } ) ,
222+ step ( {
223+ service : 's3' ,
224+ command : 'PutBucketVersioningCommand' ,
225+ params : { Bucket : 'b' , VersioningConfiguration : { Status : 'Enabled' } } ,
226+ } ) ,
105227 step ( {
106228 service : 'iam' ,
107229 command : 'CreateServiceLinkedRoleCommand' ,
@@ -139,6 +261,7 @@ describe('looksLikeValidationError', () => {
139261 'Member must not be null' ,
140262 'failed to satisfy constraint: Member must have length less than or equal to 64' ,
141263 'Missing required parameter Bucket' ,
264+ 'The request must contain the parameter groupName or groupId' ,
142265 'is required' ,
143266 'must be a valid ARN' ,
144267 ] ) ( 'detects %p as a validation-class error' , ( msg ) => {
0 commit comments