@@ -121,7 +121,15 @@ void parsesOneOf() {
121121 void parsesAnyOfAllOfNot () {
122122 assertThat (SchemaParser .parse (Map .of ("anyOf" , List .of (Map .of ("type" , "string" )))))
123123 .isInstanceOf (AnyOfSchema .class );
124+ // allOf with a single branch flattens to the branch itself (no wrapper AllOfSchema).
124125 assertThat (SchemaParser .parse (Map .of ("allOf" , List .of (Map .of ("type" , "string" )))))
126+ .isInstanceOf (StringSchema .class );
127+ // allOf with multiple branches flattens into AllOfSchema.
128+ assertThat (
129+ SchemaParser .parse (
130+ Map .of (
131+ "allOf" ,
132+ List .of (Map .of ("type" , "string" ), Map .of ("type" , "string" , "minLength" , 1 )))))
125133 .isInstanceOf (AllOfSchema .class );
126134 assertThat (SchemaParser .parse (Map .of ("not" , Map .of ("type" , "null" ))))
127135 .isInstanceOf (NotSchema .class );
@@ -146,4 +154,112 @@ void enumOnStringStaysAsStringSchema() {
146154 assertThat (s ).isInstanceOf (StringSchema .class );
147155 assertThat (((StringSchema ) s ).enumValues ()).containsExactly ("a" , "b" );
148156 }
157+
158+ @ Test
159+ void allOfWithSiblingTypeWrapsInImplicitAllOf () {
160+ Schema s =
161+ SchemaParser .parse (
162+ Map .of (
163+ "type" , "object" ,
164+ "required" , List .of ("x" ),
165+ "allOf" , List .of (Map .of ("type" , "object" , "required" , List .of ("y" )))));
166+ assertThat (s ).isInstanceOf (AllOfSchema .class );
167+ AllOfSchema all = (AllOfSchema ) s ;
168+ assertThat (all .parts ()).hasSize (2 );
169+ assertThat (all .parts ().get (0 )).isInstanceOf (ObjectSchema .class );
170+ assertThat (((ObjectSchema ) all .parts ().get (0 )).required ()).containsExactly ("x" );
171+ assertThat (all .parts ().get (1 )).isInstanceOf (ObjectSchema .class );
172+ assertThat (((ObjectSchema ) all .parts ().get (1 )).required ()).containsExactly ("y" );
173+ }
174+
175+ @ Test
176+ void anyOfWithSiblingTypeWrapsInImplicitAllOf () {
177+ Schema s =
178+ SchemaParser .parse (
179+ Map .of (
180+ "type" ,
181+ "string" ,
182+ "anyOf" ,
183+ List .of (
184+ Map .of ("type" , "string" , "minLength" , 1 ),
185+ Map .of ("type" , "string" , "maxLength" , 10 ))));
186+ assertThat (s ).isInstanceOf (AllOfSchema .class );
187+ AllOfSchema all = (AllOfSchema ) s ;
188+ assertThat (all .parts ()).hasSize (2 );
189+ assertThat (all .parts ().get (0 )).isInstanceOf (StringSchema .class );
190+ assertThat (all .parts ().get (1 )).isInstanceOf (AnyOfSchema .class );
191+ assertThat (((AnyOfSchema ) all .parts ().get (1 )).options ()).hasSize (2 );
192+ }
193+
194+ @ Test
195+ void oneOfWithSiblingTypeWrapsInImplicitAllOf () {
196+ Schema s =
197+ SchemaParser .parse (
198+ Map .of (
199+ "type" ,
200+ "string" ,
201+ "oneOf" ,
202+ List .of (
203+ Map .of ("type" , "string" , "minLength" , 1 ),
204+ Map .of ("type" , "string" , "maxLength" , 10 ))));
205+ assertThat (s ).isInstanceOf (AllOfSchema .class );
206+ AllOfSchema all = (AllOfSchema ) s ;
207+ assertThat (all .parts ()).hasSize (2 );
208+ assertThat (all .parts ().get (0 )).isInstanceOf (StringSchema .class );
209+ assertThat (all .parts ().get (1 )).isInstanceOf (OneOfSchema .class );
210+ }
211+
212+ @ Test
213+ void notWithSiblingTypeWrapsInImplicitAllOf () {
214+ Schema s =
215+ SchemaParser .parse (
216+ Map .of ("type" , "string" , "not" , Map .of ("type" , "string" , "maxLength" , 2 )));
217+ assertThat (s ).isInstanceOf (AllOfSchema .class );
218+ AllOfSchema all = (AllOfSchema ) s ;
219+ assertThat (all .parts ()).hasSize (2 );
220+ assertThat (all .parts ().get (0 )).isInstanceOf (StringSchema .class );
221+ assertThat (all .parts ().get (1 )).isInstanceOf (NotSchema .class );
222+ }
223+
224+ @ Test
225+ void multipleCombinatorsInOneSchemaWrapInAllOf () {
226+ Schema s =
227+ SchemaParser .parse (
228+ Map .of (
229+ "anyOf" , List .of (Map .of ("type" , "string" ), Map .of ("type" , "integer" )),
230+ "not" , Map .of ("type" , "boolean" )));
231+ assertThat (s ).isInstanceOf (AllOfSchema .class );
232+ AllOfSchema all = (AllOfSchema ) s ;
233+ assertThat (all .parts ()).hasSize (2 );
234+ assertThat (all .parts ().get (0 )).isInstanceOf (AnyOfSchema .class );
235+ assertThat (all .parts ().get (1 )).isInstanceOf (NotSchema .class );
236+ }
237+
238+ @ Test
239+ void allOfBranchesFlattenIntoOuterAllOf () {
240+ Schema s =
241+ SchemaParser .parse (
242+ Map .of (
243+ "type" ,
244+ "string" ,
245+ "allOf" ,
246+ List .of (
247+ Map .of ("type" , "string" , "minLength" , 1 ),
248+ Map .of ("type" , "string" , "maxLength" , 10 ))));
249+ assertThat (s ).isInstanceOf (AllOfSchema .class );
250+ AllOfSchema all = (AllOfSchema ) s ;
251+ // Base + the two allOf branches flattened.
252+ assertThat (all .parts ()).hasSize (3 );
253+ }
254+
255+ @ Test
256+ void aloneCombinatorStillReturnsCombinatorRecord () {
257+ // Regression: when no base assertions are present, the result is still the
258+ // single combinator record, not an AllOfSchema with a single child.
259+ Schema s =
260+ SchemaParser .parse (
261+ Map .of ("oneOf" , List .of (Map .of ("type" , "string" ), Map .of ("type" , "integer" ))));
262+ assertThat (s ).isInstanceOf (OneOfSchema .class );
263+ assertThat (((OneOfSchema ) s ).options ()).hasSize (2 );
264+ }
149265}
0 commit comments