@@ -4023,4 +4023,313 @@ private Map<String, File> generateFromContract(
40234023 return generator .opts (input ).generate ().stream ()
40244024 .collect (Collectors .toMap (File ::getName , Function .identity ()));
40254025 }
4026+
4027+ // ========== AUTO X-SPRING-PAGINATED TESTS ==========
4028+
4029+ @ Test
4030+ public void autoXSpringPaginatedDetectsAllThreeParams () throws Exception {
4031+ Map <String , Object > additionalProperties = new HashMap <>();
4032+ additionalProperties .put (USE_TAGS , "true" );
4033+ additionalProperties .put (DOCUMENTATION_PROVIDER , "springdoc" );
4034+ additionalProperties .put (INTERFACE_ONLY , "true" );
4035+ additionalProperties .put (SKIP_DEFAULT_INTERFACE , "true" );
4036+ additionalProperties .put (AUTO_X_SPRING_PAGINATED , "true" );
4037+
4038+ Map <String , File > files = generateFromContract ("src/test/resources/3_0/spring/petstore-auto-paginated.yaml" , additionalProperties );
4039+
4040+ File petApi = files .get ("PetApi.kt" );
4041+ String content = Files .readString (petApi .toPath ());
4042+
4043+ // Operation with all three params (page, size, sort) should have Pageable auto-detected
4044+ assertFileContains (petApi .toPath (), "fun findPetsWithAutoDetect(" );
4045+ assertFileContains (petApi .toPath (), "import org.springframework.data.domain.Pageable" );
4046+
4047+ // Extract findPetsWithAutoDetect method
4048+ int methodStart = content .indexOf ("fun findPetsWithAutoDetect(" );
4049+ int methodEnd = content .indexOf ("): ResponseEntity" , methodStart );
4050+ String methodSignature = content .substring (methodStart , methodEnd );
4051+
4052+ // Should have pageable parameter
4053+ Assert .assertTrue (methodSignature .contains ("pageable: Pageable" ),
4054+ "findPetsWithAutoDetect should have pageable parameter when autoXSpringPaginated is enabled" );
4055+
4056+ // Should NOT have page, size, sort query params (they should be removed)
4057+ Assert .assertFalse (methodSignature .contains ("page:" ),
4058+ "page query param should be removed when pageable is added" );
4059+ Assert .assertFalse (methodSignature .contains ("size:" ),
4060+ "size query param should be removed when pageable is added" );
4061+ Assert .assertFalse (methodSignature .contains ("sort:" ),
4062+ "sort query param should be removed when pageable is added" );
4063+
4064+ // Should still have the status parameter
4065+ Assert .assertTrue (methodSignature .contains ("status:" ),
4066+ "status parameter should remain" );
4067+ }
4068+
4069+ @ Test
4070+ public void autoXSpringPaginatedNoDetectionWhenMissingPage () throws Exception {
4071+ Map <String , Object > additionalProperties = new HashMap <>();
4072+ additionalProperties .put (USE_TAGS , "true" );
4073+ additionalProperties .put (DOCUMENTATION_PROVIDER , "springdoc" );
4074+ additionalProperties .put (INTERFACE_ONLY , "true" );
4075+ additionalProperties .put (SKIP_DEFAULT_INTERFACE , "true" );
4076+ additionalProperties .put (AUTO_X_SPRING_PAGINATED , "true" );
4077+
4078+ Map <String , File > files = generateFromContract ("src/test/resources/3_0/spring/petstore-auto-paginated.yaml" , additionalProperties );
4079+
4080+ File petApi = files .get ("PetApi.kt" );
4081+ String content = Files .readString (petApi .toPath ());
4082+
4083+ // Operation missing 'page' param should NOT have Pageable
4084+ int methodStart = content .indexOf ("fun findPetsMissingPage(" );
4085+ int methodEnd = content .indexOf ("): ResponseEntity" , methodStart );
4086+ String methodSignature = content .substring (methodStart , methodEnd );
4087+
4088+ Assert .assertFalse (methodSignature .contains ("pageable: Pageable" ),
4089+ "findPetsMissingPage should NOT have pageable when 'page' param is missing" );
4090+
4091+ // Should still have the other params
4092+ Assert .assertTrue (methodSignature .contains ("size:" ),
4093+ "size param should remain" );
4094+ Assert .assertTrue (methodSignature .contains ("sort:" ),
4095+ "sort param should remain" );
4096+ }
4097+
4098+ @ Test
4099+ public void autoXSpringPaginatedNoDetectionWhenMissingSize () throws Exception {
4100+ Map <String , Object > additionalProperties = new HashMap <>();
4101+ additionalProperties .put (USE_TAGS , "true" );
4102+ additionalProperties .put (DOCUMENTATION_PROVIDER , "springdoc" );
4103+ additionalProperties .put (INTERFACE_ONLY , "true" );
4104+ additionalProperties .put (SKIP_DEFAULT_INTERFACE , "true" );
4105+ additionalProperties .put (AUTO_X_SPRING_PAGINATED , "true" );
4106+
4107+ Map <String , File > files = generateFromContract ("src/test/resources/3_0/spring/petstore-auto-paginated.yaml" , additionalProperties );
4108+
4109+ File petApi = files .get ("PetApi.kt" );
4110+ String content = Files .readString (petApi .toPath ());
4111+
4112+ // Operation missing 'size' param should NOT have Pageable
4113+ int methodStart = content .indexOf ("fun findPetsMissingSize(" );
4114+ int methodEnd = content .indexOf ("): ResponseEntity" , methodStart );
4115+ String methodSignature = content .substring (methodStart , methodEnd );
4116+
4117+ Assert .assertFalse (methodSignature .contains ("pageable: Pageable" ),
4118+ "findPetsMissingSize should NOT have pageable when 'size' param is missing" );
4119+
4120+ // Should still have the other params
4121+ Assert .assertTrue (methodSignature .contains ("page:" ),
4122+ "page param should remain" );
4123+ Assert .assertTrue (methodSignature .contains ("sort:" ),
4124+ "sort param should remain" );
4125+ }
4126+
4127+ @ Test
4128+ public void autoXSpringPaginatedNoDetectionWhenMissingSort () throws Exception {
4129+ Map <String , Object > additionalProperties = new HashMap <>();
4130+ additionalProperties .put (USE_TAGS , "true" );
4131+ additionalProperties .put (DOCUMENTATION_PROVIDER , "springdoc" );
4132+ additionalProperties .put (INTERFACE_ONLY , "true" );
4133+ additionalProperties .put (SKIP_DEFAULT_INTERFACE , "true" );
4134+ additionalProperties .put (AUTO_X_SPRING_PAGINATED , "true" );
4135+
4136+ Map <String , File > files = generateFromContract ("src/test/resources/3_0/spring/petstore-auto-paginated.yaml" , additionalProperties );
4137+
4138+ File petApi = files .get ("PetApi.kt" );
4139+ String content = Files .readString (petApi .toPath ());
4140+
4141+ // Operation missing 'sort' param should NOT have Pageable
4142+ int methodStart = content .indexOf ("fun findPetsMissingSort(" );
4143+ int methodEnd = content .indexOf ("): ResponseEntity" , methodStart );
4144+ String methodSignature = content .substring (methodStart , methodEnd );
4145+
4146+ Assert .assertFalse (methodSignature .contains ("pageable: Pageable" ),
4147+ "findPetsMissingSort should NOT have pageable when 'sort' param is missing" );
4148+
4149+ // Should still have the other params
4150+ Assert .assertTrue (methodSignature .contains ("page:" ),
4151+ "page param should remain" );
4152+ Assert .assertTrue (methodSignature .contains ("size:" ),
4153+ "size param should remain" );
4154+ }
4155+
4156+ @ Test
4157+ public void autoXSpringPaginatedManualFalseTakesPrecedence () throws Exception {
4158+ Map <String , Object > additionalProperties = new HashMap <>();
4159+ additionalProperties .put (USE_TAGS , "true" );
4160+ additionalProperties .put (DOCUMENTATION_PROVIDER , "springdoc" );
4161+ additionalProperties .put (INTERFACE_ONLY , "true" );
4162+ additionalProperties .put (SKIP_DEFAULT_INTERFACE , "true" );
4163+ additionalProperties .put (AUTO_X_SPRING_PAGINATED , "true" );
4164+
4165+ Map <String , File > files = generateFromContract ("src/test/resources/3_0/spring/petstore-auto-paginated.yaml" , additionalProperties );
4166+
4167+ File petApi = files .get ("PetApi.kt" );
4168+ String content = Files .readString (petApi .toPath ());
4169+
4170+ // Operation with x-spring-paginated: false should NOT have Pageable (manual override)
4171+ int methodStart = content .indexOf ("fun findPetsManualFalse(" );
4172+ int methodEnd = content .indexOf ("): ResponseEntity" , methodStart );
4173+ String methodSignature = content .substring (methodStart , methodEnd );
4174+
4175+ Assert .assertFalse (methodSignature .contains ("pageable: Pageable" ),
4176+ "findPetsManualFalse should NOT have pageable when x-spring-paginated is explicitly set to false" );
4177+
4178+ // Should still have all three params
4179+ Assert .assertTrue (methodSignature .contains ("page:" ),
4180+ "page param should remain when x-spring-paginated: false" );
4181+ Assert .assertTrue (methodSignature .contains ("size:" ),
4182+ "size param should remain when x-spring-paginated: false" );
4183+ Assert .assertTrue (methodSignature .contains ("sort:" ),
4184+ "sort param should remain when x-spring-paginated: false" );
4185+ }
4186+
4187+ @ Test
4188+ public void autoXSpringPaginatedCaseSensitiveMatching () throws Exception {
4189+ Map <String , Object > additionalProperties = new HashMap <>();
4190+ additionalProperties .put (USE_TAGS , "true" );
4191+ additionalProperties .put (DOCUMENTATION_PROVIDER , "springdoc" );
4192+ additionalProperties .put (INTERFACE_ONLY , "true" );
4193+ additionalProperties .put (SKIP_DEFAULT_INTERFACE , "true" );
4194+ additionalProperties .put (AUTO_X_SPRING_PAGINATED , "true" );
4195+
4196+ Map <String , File > files = generateFromContract ("src/test/resources/3_0/spring/petstore-auto-paginated.yaml" , additionalProperties );
4197+
4198+ File petApi = files .get ("PetApi.kt" );
4199+ String content = Files .readString (petApi .toPath ());
4200+
4201+ // Operation with Page, Size, Sort (capitalized) should NOT match
4202+ int methodStart = content .indexOf ("fun findPetsCaseSensitive(" );
4203+ int methodEnd = content .indexOf ("): ResponseEntity" , methodStart );
4204+ String methodSignature = content .substring (methodStart , methodEnd );
4205+
4206+ Assert .assertFalse (methodSignature .contains ("pageable: Pageable" ),
4207+ "findPetsCaseSensitive should NOT have pageable with capitalized param names (case-sensitive)" );
4208+
4209+ // Should still have all three params with capital letters
4210+ Assert .assertTrue (methodSignature .contains ("page:" ) || methodSignature .contains ("Page:" ),
4211+ "Page param should remain" );
4212+ }
4213+
4214+ @ Test
4215+ public void autoXSpringPaginatedOnlyForSpringBoot () throws Exception {
4216+ Map <String , Object > additionalProperties = new HashMap <>();
4217+ additionalProperties .put (USE_TAGS , "true" );
4218+ additionalProperties .put (DOCUMENTATION_PROVIDER , "springdoc" );
4219+ additionalProperties .put (AUTO_X_SPRING_PAGINATED , "true" );
4220+
4221+ // Test with spring-cloud library (should NOT auto-detect)
4222+ Map <String , File > files = generateFromContract (
4223+ "src/test/resources/3_0/spring/petstore-auto-paginated.yaml" ,
4224+ additionalProperties ,
4225+ new HashMap <>(),
4226+ configurator -> configurator .setLibrary ("spring-cloud" )
4227+ );
4228+
4229+ File petApi = files .get ("PetApiClient.kt" );
4230+ if (petApi != null ) {
4231+ String content = Files .readString (petApi .toPath ());
4232+
4233+ // For spring-cloud, should NOT have Pageable even with auto-detect enabled
4234+ Assert .assertFalse (content .contains ("pageable: Pageable" ),
4235+ "spring-cloud library should NOT auto-detect pageable (needs actual query params for HTTP)" );
4236+
4237+ // Should have all three query params
4238+ int methodStart = content .indexOf ("fun findPetsWithAutoDetect(" );
4239+ if (methodStart >= 0 ) {
4240+ int methodEnd = content .indexOf ("): " , methodStart );
4241+ String methodSignature = content .substring (methodStart , methodEnd );
4242+
4243+ Assert .assertTrue (methodSignature .contains ("page" ) || methodSignature .contains ("@Query" ),
4244+ "spring-cloud should keep query parameters" );
4245+ }
4246+ }
4247+ }
4248+
4249+ @ Test
4250+ public void autoXSpringPaginatedDisabledByDefault () throws Exception {
4251+ Map <String , Object > additionalProperties = new HashMap <>();
4252+ additionalProperties .put (USE_TAGS , "true" );
4253+ additionalProperties .put (DOCUMENTATION_PROVIDER , "springdoc" );
4254+ additionalProperties .put (INTERFACE_ONLY , "true" );
4255+ additionalProperties .put (SKIP_DEFAULT_INTERFACE , "true" );
4256+ // NOT setting AUTO_X_SPRING_PAGINATED (should default to false)
4257+
4258+ Map <String , File > files = generateFromContract ("src/test/resources/3_0/spring/petstore-auto-paginated.yaml" , additionalProperties );
4259+
4260+ File petApi = files .get ("PetApi.kt" );
4261+ String content = Files .readString (petApi .toPath ());
4262+
4263+ // Without AUTO_X_SPRING_PAGINATED, should NOT auto-detect
4264+ int methodStart = content .indexOf ("fun findPetsWithAutoDetect(" );
4265+ int methodEnd = content .indexOf ("): ResponseEntity" , methodStart );
4266+ String methodSignature = content .substring (methodStart , methodEnd );
4267+
4268+ Assert .assertFalse (methodSignature .contains ("pageable: Pageable" ),
4269+ "Should NOT have pageable when autoXSpringPaginated is not enabled (default: false)" );
4270+
4271+ // Should have all three query params
4272+ Assert .assertTrue (methodSignature .contains ("page:" ),
4273+ "page param should remain when auto-detect is disabled" );
4274+ Assert .assertTrue (methodSignature .contains ("size:" ),
4275+ "size param should remain when auto-detect is disabled" );
4276+ Assert .assertTrue (methodSignature .contains ("sort:" ),
4277+ "sort param should remain when auto-detect is disabled" );
4278+ }
4279+
4280+ @ Test
4281+ public void autoXSpringPaginatedWorksWithManualTrue () throws Exception {
4282+ Map <String , Object > additionalProperties = new HashMap <>();
4283+ additionalProperties .put (USE_TAGS , "true" );
4284+ additionalProperties .put (DOCUMENTATION_PROVIDER , "springdoc" );
4285+ additionalProperties .put (INTERFACE_ONLY , "true" );
4286+ additionalProperties .put (SKIP_DEFAULT_INTERFACE , "true" );
4287+ additionalProperties .put (AUTO_X_SPRING_PAGINATED , "true" );
4288+
4289+ Map <String , File > files = generateFromContract ("src/test/resources/3_0/spring/petstore-auto-paginated.yaml" , additionalProperties );
4290+
4291+ File petApi = files .get ("PetApi.kt" );
4292+ String content = Files .readString (petApi .toPath ());
4293+
4294+ // Operation with manual x-spring-paginated: true should still work
4295+ int methodStart = content .indexOf ("fun findPetsManualTrue(" );
4296+ int methodEnd = content .indexOf ("): ResponseEntity" , methodStart );
4297+ String methodSignature = content .substring (methodStart , methodEnd );
4298+
4299+ Assert .assertTrue (methodSignature .contains ("pageable: Pageable" ),
4300+ "findPetsManualTrue should have pageable (manual x-spring-paginated: true)" );
4301+
4302+ // Query params should be removed
4303+ Assert .assertFalse (methodSignature .contains ("page:" ),
4304+ "page param should be removed" );
4305+ Assert .assertFalse (methodSignature .contains ("size:" ),
4306+ "size param should be removed" );
4307+ Assert .assertFalse (methodSignature .contains ("sort:" ),
4308+ "sort param should be removed" );
4309+ }
4310+
4311+ @ Test
4312+ public void autoXSpringPaginatedNoParamsDoesNotDetect () throws Exception {
4313+ Map <String , Object > additionalProperties = new HashMap <>();
4314+ additionalProperties .put (USE_TAGS , "true" );
4315+ additionalProperties .put (DOCUMENTATION_PROVIDER , "springdoc" );
4316+ additionalProperties .put (INTERFACE_ONLY , "true" );
4317+ additionalProperties .put (SKIP_DEFAULT_INTERFACE , "true" );
4318+ additionalProperties .put (AUTO_X_SPRING_PAGINATED , "true" );
4319+
4320+ Map <String , File > files = generateFromContract ("src/test/resources/3_0/spring/petstore-auto-paginated.yaml" , additionalProperties );
4321+
4322+ File petApi = files .get ("PetApi.kt" );
4323+ String content = Files .readString (petApi .toPath ());
4324+
4325+ // Operation with no params should NOT have Pageable
4326+ int methodStart = content .indexOf ("fun findPetsNoParams(" );
4327+ int methodEnd = content .indexOf ("): ResponseEntity" , methodStart );
4328+ String methodSignature = content .substring (methodStart , methodEnd );
4329+
4330+ Assert .assertFalse (methodSignature .contains ("pageable: Pageable" ),
4331+ "findPetsNoParams should NOT have pageable when there are no pagination params" );
4332+ }
40264333}
4334+
4335+
0 commit comments