@@ -139,7 +139,10 @@ async fn main() {
139139#[ cfg( test) ]
140140mod tests {
141141 use super :: * ;
142+ use rocket:: http:: Status ;
143+ use rocket:: local:: asynchronous:: Client ;
142144 use rocket_okapi:: openapi_get_spec;
145+ use serde_json:: Value ;
143146
144147 #[ test]
145148 fn generated_spec_contains_user_routes ( ) {
@@ -155,4 +158,87 @@ mod tests {
155158 // The `hidden` endpoint is marked skip
156159 assert ! ( !spec. paths. keys( ) . any( |k| k. contains( "/hidden" ) ) ) ;
157160 }
161+
162+ async fn fetch_openapi_spec ( client : & Client , path : & str ) -> Value {
163+ let response = client. get ( path) . dispatch ( ) . await ;
164+ assert_eq ! ( response. status( ) , Status :: Ok ) ;
165+ let body = response. into_string ( ) . await . expect ( "body string" ) ;
166+ serde_json:: from_str ( & body) . expect ( "valid json" )
167+ }
168+
169+ #[ rocket:: async_test]
170+ async fn server_openapi_contains_and_matches_routes ( ) {
171+ // Rebuild the Rocket instance similarly to `main` so the example's routes are mounted
172+ let rocket = rocket:: build ( )
173+ . mount (
174+ "/" ,
175+ openapi_get_routes ! [
176+ get_all_users,
177+ get_user,
178+ get_user_by_name,
179+ create_user,
180+ hidden,
181+ create_post_by_query,
182+ ] ,
183+ )
184+ . mount (
185+ "/swagger-ui/" ,
186+ make_swagger_ui ( & SwaggerUIConfig {
187+ url : "../openapi.json" . to_owned ( ) ,
188+ ..Default :: default ( )
189+ } ) ,
190+ )
191+ . mount (
192+ "/rapidoc/" ,
193+ make_rapidoc ( & RapiDocConfig {
194+ general : GeneralConfig {
195+ spec_urls : vec ! [ UrlObject :: new( "General" , "../openapi.json" ) ] ,
196+ ..Default :: default ( )
197+ } ,
198+ hide_show : HideShowConfig {
199+ allow_spec_url_load : false ,
200+ allow_spec_file_load : false ,
201+ ..Default :: default ( )
202+ } ,
203+ ..Default :: default ( )
204+ } ) ,
205+ ) ;
206+
207+ let client = Client :: tracked ( rocket) . await . expect ( "client" ) ;
208+ let spec = fetch_openapi_spec ( & client, "/openapi.json" ) . await ;
209+
210+ // The spec should include the user related route paths
211+ assert ! ( spec[ "paths" ]
212+ . as_object( )
213+ . unwrap( )
214+ . keys( )
215+ . any( |k| k. contains( "/user" ) ) ) ;
216+ assert ! ( spec[ "paths" ]
217+ . as_object( )
218+ . unwrap( )
219+ . keys( )
220+ . any( |k| k. contains( "post_by_query" ) ) ) ;
221+ // And the `hidden` route should be omitted
222+ assert ! ( !spec[ "paths" ]
223+ . as_object( )
224+ . unwrap( )
225+ . keys( )
226+ . any( |k| k. contains( "/hidden" ) ) ) ;
227+
228+ // Cross-check: every documented path should match a Rocket route
229+ let paths = spec[ "paths" ] . as_object ( ) . unwrap ( ) ;
230+ for path in paths. keys ( ) {
231+ let rocket_style = path. replace ( '{' , "<" ) . replace ( '}' , ">" ) ;
232+ let rocket_style_alt = rocket_style. replace ( '>' , "..>" ) ;
233+ let found = client. rocket ( ) . routes ( ) . any ( |r| {
234+ r. uri . to_string ( ) . contains ( & rocket_style)
235+ || r. uri . to_string ( ) . contains ( & rocket_style_alt)
236+ } ) ;
237+ assert ! (
238+ found,
239+ "OpenApi path '{}' not found among Rocket routes" ,
240+ path
241+ ) ;
242+ }
243+ }
158244}
0 commit comments