Skip to content

Commit e3b858d

Browse files
committed
!
1 parent b976465 commit e3b858d

2 files changed

Lines changed: 159 additions & 56 deletions

File tree

crates/rustapi-core/src/app.rs

Lines changed: 89 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,9 +1285,15 @@ mod tests {
12851285
/// Unit test: Verify OpenAPI operations are propagated during nesting
12861286
#[test]
12871287
fn test_openapi_operations_propagated_during_nesting() {
1288-
async fn list_users() -> &'static str { "list users" }
1289-
async fn get_user() -> &'static str { "get user" }
1290-
async fn create_user() -> &'static str { "create user" }
1288+
async fn list_users() -> &'static str {
1289+
"list users"
1290+
}
1291+
async fn get_user() -> &'static str {
1292+
"get user"
1293+
}
1294+
async fn create_user() -> &'static str {
1295+
"create user"
1296+
}
12911297

12921298
// Create nested router with multiple routes
12931299
// Note: We use separate routes since MethodRouter doesn't support chaining
@@ -1302,26 +1308,42 @@ mod tests {
13021308
let spec = app.openapi_spec();
13031309

13041310
// Verify /api/v1/users path exists with GET
1305-
assert!(spec.paths.contains_key("/api/v1/users"), "Should have /api/v1/users path");
1311+
assert!(
1312+
spec.paths.contains_key("/api/v1/users"),
1313+
"Should have /api/v1/users path"
1314+
);
13061315
let users_path = spec.paths.get("/api/v1/users").unwrap();
13071316
assert!(users_path.get.is_some(), "Should have GET operation");
13081317

13091318
// Verify /api/v1/users/create path exists with POST
1310-
assert!(spec.paths.contains_key("/api/v1/users/create"), "Should have /api/v1/users/create path");
1319+
assert!(
1320+
spec.paths.contains_key("/api/v1/users/create"),
1321+
"Should have /api/v1/users/create path"
1322+
);
13111323
let create_path = spec.paths.get("/api/v1/users/create").unwrap();
13121324
assert!(create_path.post.is_some(), "Should have POST operation");
13131325

13141326
// Verify /api/v1/users/{id} path exists with GET
1315-
assert!(spec.paths.contains_key("/api/v1/users/{id}"), "Should have /api/v1/users/{{id}} path");
1327+
assert!(
1328+
spec.paths.contains_key("/api/v1/users/{id}"),
1329+
"Should have /api/v1/users/{{id}} path"
1330+
);
13161331
let user_path = spec.paths.get("/api/v1/users/{id}").unwrap();
1317-
assert!(user_path.get.is_some(), "Should have GET operation for user by id");
1332+
assert!(
1333+
user_path.get.is_some(),
1334+
"Should have GET operation for user by id"
1335+
);
13181336

13191337
// Verify path parameter is added
13201338
let get_user_op = user_path.get.as_ref().unwrap();
13211339
assert!(get_user_op.parameters.is_some(), "Should have parameters");
13221340
let params = get_user_op.parameters.as_ref().unwrap();
1323-
assert!(params.iter().any(|p| p.name == "id" && p.location == "path"),
1324-
"Should have 'id' path parameter");
1341+
assert!(
1342+
params
1343+
.iter()
1344+
.any(|p| p.name == "id" && p.location == "path"),
1345+
"Should have 'id' path parameter"
1346+
);
13251347
}
13261348

13271349
/// Unit test: Verify nested routes don't appear without nesting
@@ -1331,7 +1353,10 @@ mod tests {
13311353
let spec = app.openapi_spec();
13321354

13331355
// Should have no paths (except potentially default ones)
1334-
assert!(spec.paths.is_empty(), "OpenAPI spec should have no paths without routes");
1356+
assert!(
1357+
spec.paths.is_empty(),
1358+
"OpenAPI spec should have no paths without routes"
1359+
);
13351360
}
13361361

13371362
/// Unit test: Verify RustApi::nest delegates correctly to Router::nest
@@ -1342,9 +1367,15 @@ mod tests {
13421367
fn test_rustapi_nest_delegates_to_router_nest() {
13431368
use crate::router::RouteMatch;
13441369

1345-
async fn list_users() -> &'static str { "list users" }
1346-
async fn get_user() -> &'static str { "get user" }
1347-
async fn create_user() -> &'static str { "create user" }
1370+
async fn list_users() -> &'static str {
1371+
"list users"
1372+
}
1373+
async fn get_user() -> &'static str {
1374+
"get user"
1375+
}
1376+
async fn create_user() -> &'static str {
1377+
"create user"
1378+
}
13481379

13491380
// Create nested router with multiple routes
13501381
let users_router = Router::new()
@@ -1361,9 +1392,18 @@ mod tests {
13611392
assert_eq!(routes.len(), 3, "Should have 3 routes registered");
13621393

13631394
// Verify route paths
1364-
assert!(routes.contains_key("/api/v1/users"), "Should have /api/v1/users route");
1365-
assert!(routes.contains_key("/api/v1/users/create"), "Should have /api/v1/users/create route");
1366-
assert!(routes.contains_key("/api/v1/users/:id"), "Should have /api/v1/users/:id route");
1395+
assert!(
1396+
routes.contains_key("/api/v1/users"),
1397+
"Should have /api/v1/users route"
1398+
);
1399+
assert!(
1400+
routes.contains_key("/api/v1/users/create"),
1401+
"Should have /api/v1/users/create route"
1402+
);
1403+
assert!(
1404+
routes.contains_key("/api/v1/users/:id"),
1405+
"Should have /api/v1/users/:id route"
1406+
);
13671407

13681408
// Verify route matching works
13691409
match router.match_route("/api/v1/users", &Method::GET) {
@@ -1382,7 +1422,11 @@ mod tests {
13821422

13831423
match router.match_route("/api/v1/users/123", &Method::GET) {
13841424
RouteMatch::Found { params, .. } => {
1385-
assert_eq!(params.get("id"), Some(&"123".to_string()), "Should extract id param");
1425+
assert_eq!(
1426+
params.get("id"),
1427+
Some(&"123".to_string()),
1428+
"Should extract id param"
1429+
);
13861430
}
13871431
_ => panic!("GET /api/v1/users/123 should be found"),
13881432
}
@@ -1402,8 +1446,12 @@ mod tests {
14021446
/// **Validates: Requirements 6.1, 6.2**
14031447
#[test]
14041448
fn test_rustapi_nest_includes_routes_in_openapi_spec() {
1405-
async fn list_items() -> &'static str { "list items" }
1406-
async fn get_item() -> &'static str { "get item" }
1449+
async fn list_items() -> &'static str {
1450+
"list items"
1451+
}
1452+
async fn get_item() -> &'static str {
1453+
"get item"
1454+
}
14071455

14081456
// Create nested router
14091457
let items_router = Router::new()
@@ -1417,22 +1465,38 @@ mod tests {
14171465
let spec = app.openapi_spec();
14181466

14191467
// Verify paths exist
1420-
assert!(spec.paths.contains_key("/api/items"), "Should have /api/items in OpenAPI");
1421-
assert!(spec.paths.contains_key("/api/items/{item_id}"), "Should have /api/items/{{item_id}} in OpenAPI");
1468+
assert!(
1469+
spec.paths.contains_key("/api/items"),
1470+
"Should have /api/items in OpenAPI"
1471+
);
1472+
assert!(
1473+
spec.paths.contains_key("/api/items/{item_id}"),
1474+
"Should have /api/items/{{item_id}} in OpenAPI"
1475+
);
14221476

14231477
// Verify operations
14241478
let list_path = spec.paths.get("/api/items").unwrap();
1425-
assert!(list_path.get.is_some(), "Should have GET operation for /api/items");
1479+
assert!(
1480+
list_path.get.is_some(),
1481+
"Should have GET operation for /api/items"
1482+
);
14261483

14271484
let get_path = spec.paths.get("/api/items/{item_id}").unwrap();
1428-
assert!(get_path.get.is_some(), "Should have GET operation for /api/items/{{item_id}}");
1485+
assert!(
1486+
get_path.get.is_some(),
1487+
"Should have GET operation for /api/items/{{item_id}}"
1488+
);
14291489

14301490
// Verify path parameter is added
14311491
let get_op = get_path.get.as_ref().unwrap();
14321492
assert!(get_op.parameters.is_some(), "Should have parameters");
14331493
let params = get_op.parameters.as_ref().unwrap();
1434-
assert!(params.iter().any(|p| p.name == "item_id" && p.location == "path"),
1435-
"Should have 'item_id' path parameter");
1494+
assert!(
1495+
params
1496+
.iter()
1497+
.any(|p| p.name == "item_id" && p.location == "path"),
1498+
"Should have 'item_id' path parameter"
1499+
);
14361500
}
14371501
}
14381502

crates/rustapi-core/src/router.rs

Lines changed: 70 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,10 @@ impl Router {
446446
.insert(prefixed_matchit_path.clone(), method_router.clone());
447447

448448
// Try to insert into the matchit router
449-
match self.inner.insert(prefixed_matchit_path.clone(), method_router) {
449+
match self
450+
.inner
451+
.insert(prefixed_matchit_path.clone(), method_router)
452+
{
450453
Ok(_) => {
451454
// Track the registered route
452455
self.registered_routes.insert(
@@ -1043,7 +1046,9 @@ mod tests {
10431046
let parent = Router::new().nest("/api", nested);
10441047

10451048
// Parent should track the nested state type ID
1046-
assert!(parent.state_type_ids().contains(&std::any::TypeId::of::<NestedState>()));
1049+
assert!(parent
1050+
.state_type_ids()
1051+
.contains(&std::any::TypeId::of::<NestedState>()));
10471052
}
10481053

10491054
#[test]
@@ -1152,11 +1157,21 @@ mod tests {
11521157

11531158
#[test]
11541159
fn test_multiple_router_composition_all_routes_registered() {
1155-
async fn users_list() -> &'static str { "users list" }
1156-
async fn users_get() -> &'static str { "users get" }
1157-
async fn posts_list() -> &'static str { "posts list" }
1158-
async fn posts_get() -> &'static str { "posts get" }
1159-
async fn comments_list() -> &'static str { "comments list" }
1160+
async fn users_list() -> &'static str {
1161+
"users list"
1162+
}
1163+
async fn users_get() -> &'static str {
1164+
"users get"
1165+
}
1166+
async fn posts_list() -> &'static str {
1167+
"posts list"
1168+
}
1169+
async fn posts_get() -> &'static str {
1170+
"posts get"
1171+
}
1172+
async fn comments_list() -> &'static str {
1173+
"comments list"
1174+
}
11601175

11611176
// Create multiple sub-routers with different routes
11621177
let users_router = Router::new()
@@ -1167,8 +1182,7 @@ mod tests {
11671182
.route("/", get(posts_list))
11681183
.route("/{id}", get(posts_get));
11691184

1170-
let comments_router = Router::new()
1171-
.route("/", get(comments_list));
1185+
let comments_router = Router::new().route("/", get(comments_list));
11721186

11731187
// Nest all routers under different prefixes
11741188
let app = Router::new()
@@ -1181,22 +1195,43 @@ mod tests {
11811195
assert_eq!(routes.len(), 5, "Should have 5 routes registered");
11821196

11831197
// Verify users routes
1184-
assert!(routes.contains_key("/api/users"), "Should have /api/users route");
1185-
assert!(routes.contains_key("/api/users/:id"), "Should have /api/users/:id route");
1198+
assert!(
1199+
routes.contains_key("/api/users"),
1200+
"Should have /api/users route"
1201+
);
1202+
assert!(
1203+
routes.contains_key("/api/users/:id"),
1204+
"Should have /api/users/:id route"
1205+
);
11861206

11871207
// Verify posts routes
1188-
assert!(routes.contains_key("/api/posts"), "Should have /api/posts route");
1189-
assert!(routes.contains_key("/api/posts/:id"), "Should have /api/posts/:id route");
1208+
assert!(
1209+
routes.contains_key("/api/posts"),
1210+
"Should have /api/posts route"
1211+
);
1212+
assert!(
1213+
routes.contains_key("/api/posts/:id"),
1214+
"Should have /api/posts/:id route"
1215+
);
11901216

11911217
// Verify comments routes
1192-
assert!(routes.contains_key("/api/comments"), "Should have /api/comments route");
1218+
assert!(
1219+
routes.contains_key("/api/comments"),
1220+
"Should have /api/comments route"
1221+
);
11931222
}
11941223

11951224
#[test]
11961225
fn test_multiple_router_composition_no_interference() {
1197-
async fn users_handler() -> &'static str { "users" }
1198-
async fn posts_handler() -> &'static str { "posts" }
1199-
async fn admin_handler() -> &'static str { "admin" }
1226+
async fn users_handler() -> &'static str {
1227+
"users"
1228+
}
1229+
async fn posts_handler() -> &'static str {
1230+
"posts"
1231+
}
1232+
async fn admin_handler() -> &'static str {
1233+
"admin"
1234+
}
12001235

12011236
// Create routers with same internal structure but different prefixes
12021237
let users_router = Router::new()
@@ -1254,9 +1289,15 @@ mod tests {
12541289

12551290
#[test]
12561291
fn test_multiple_router_composition_with_multiple_methods() {
1257-
async fn get_handler() -> &'static str { "get" }
1258-
async fn post_handler() -> &'static str { "post" }
1259-
async fn put_handler() -> &'static str { "put" }
1292+
async fn get_handler() -> &'static str {
1293+
"get"
1294+
}
1295+
async fn post_handler() -> &'static str {
1296+
"post"
1297+
}
1298+
async fn put_handler() -> &'static str {
1299+
"put"
1300+
}
12601301

12611302
// Create routers with multiple HTTP methods
12621303
// Combine GET and POST for users root
@@ -1296,8 +1337,7 @@ mod tests {
12961337
posts_root_combined.handlers.insert(method, handler);
12971338
}
12981339

1299-
let posts_router = Router::new()
1300-
.route("/", posts_root_combined);
1340+
let posts_router = Router::new().route("/", posts_root_combined);
13011341

13021342
// Nest routers
13031343
let app = Router::new()
@@ -1339,17 +1379,16 @@ mod tests {
13391379

13401380
#[test]
13411381
fn test_multiple_router_composition_deep_nesting() {
1342-
async fn handler() -> &'static str { "handler" }
1382+
async fn handler() -> &'static str {
1383+
"handler"
1384+
}
13431385

13441386
// Create nested routers at different depth levels
1345-
let deep_router = Router::new()
1346-
.route("/action", get(handler));
1387+
let deep_router = Router::new().route("/action", get(handler));
13471388

1348-
let mid_router = Router::new()
1349-
.route("/info", get(handler));
1389+
let mid_router = Router::new().route("/info", get(handler));
13501390

1351-
let shallow_router = Router::new()
1352-
.route("/status", get(handler));
1391+
let shallow_router = Router::new().route("/status", get(handler));
13531392

13541393
// Nest at different depths
13551394
let app = Router::new()
@@ -2252,7 +2291,7 @@ mod property_tests {
22522291
// Success
22532292
}
22542293
other => {
2255-
prop_assert!(false, "Route should be found for registered method, got: {:?}",
2294+
prop_assert!(false, "Route should be found for registered method, got: {:?}",
22562295
match other {
22572296
RouteMatch::NotFound => "NotFound",
22582297
RouteMatch::MethodNotAllowed { .. } => "MethodNotAllowed",
@@ -3212,7 +3251,7 @@ mod property_tests {
32123251
msg
32133252
);
32143253
prop_assert!(
3215-
msg.contains("Use different path patterns") ||
3254+
msg.contains("Use different path patterns") ||
32163255
msg.contains("different path patterns"),
32173256
"Error should suggest using different path patterns, got: {}",
32183257
msg

0 commit comments

Comments
 (0)