use nidus_core::{ModuleBuilder, ModuleGraph, NidusError};
#[test]
fn module_builder_records_explicit_imports_providers_controllers_and_exports() {
let definition = ModuleBuilder::new("UsersModule")
.import("DatabaseModule")
.provider("UsersRepository")
.provider("UsersService")
.controller("UsersController")
.export("UsersService")
.build();
assert_eq!(definition.name(), "UsersModule");
assert_eq!(definition.imports(), ["DatabaseModule"]);
assert_eq!(definition.providers(), ["UsersRepository", "UsersService"]);
assert_eq!(definition.controllers(), ["UsersController"]);
assert_eq!(definition.exports(), ["UsersService"]);
}
#[test]
fn module_graph_detects_circular_imports() {
let users = ModuleBuilder::new("UsersModule")
.import("BillingModule")
.build();
let billing = ModuleBuilder::new("BillingModule")
.import("UsersModule")
.build();
let error = ModuleGraph::from_modules([users, billing]).unwrap_err();
assert!(matches!(error, NidusError::CircularModuleImport { .. }));
}
#[test]
fn module_graph_rejects_duplicate_module_names() {
let first = ModuleBuilder::new("UsersModule")
.provider("UsersService")
.build();
let second = ModuleBuilder::new("UsersModule")
.provider("UsersRepository")
.build();
let error = ModuleGraph::from_modules([first, second]).unwrap_err();
assert!(matches!(error, NidusError::DuplicateModule { .. }));
assert!(error.to_string().contains("UsersModule"));
}
#[test]
fn module_graph_iterates_modules_in_name_order() {
let users = ModuleBuilder::new("UsersModule").build();
let auth = ModuleBuilder::new("AuthModule").build();
let billing = ModuleBuilder::new("BillingModule").build();
let graph = ModuleGraph::from_modules([users, auth, billing]).unwrap();
let module_names = graph
.modules()
.map(|module| module.name())
.collect::<Vec<_>>();
assert_eq!(module_names, ["AuthModule", "BillingModule", "UsersModule"]);
}
#[test]
fn module_graph_reports_validation_errors_in_module_name_order() {
let users = ModuleBuilder::new("UsersModule")
.provider("UsersService")
.provider("UsersService")
.build();
let auth = ModuleBuilder::new("AuthModule")
.provider("AuthService")
.provider("AuthService")
.build();
let error = ModuleGraph::from_modules([users, auth]).unwrap_err();
assert!(matches!(error, NidusError::DuplicateModuleProvider { .. }));
assert!(error.to_string().contains("AuthModule"));
assert!(error.to_string().contains("AuthService"));
}
#[test]
fn module_graph_rejects_duplicate_local_providers() {
let users = ModuleBuilder::new("UsersModule")
.provider("UsersService")
.provider("UsersService")
.build();
let error = ModuleGraph::from_modules([users]).unwrap_err();
assert!(matches!(error, NidusError::DuplicateModuleProvider { .. }));
assert!(error.to_string().contains("UsersModule"));
assert!(error.to_string().contains("UsersService"));
}
#[test]
fn module_graph_rejects_duplicate_local_controllers() {
let users = ModuleBuilder::new("UsersModule")
.controller("UsersController")
.controller("UsersController")
.build();
let error = ModuleGraph::from_modules([users]).unwrap_err();
assert!(matches!(
error,
NidusError::DuplicateModuleController { .. }
));
assert!(error.to_string().contains("UsersModule"));
assert!(error.to_string().contains("UsersController"));
}
#[test]
fn module_graph_rejects_provider_controller_name_conflicts() {
let users = ModuleBuilder::new("UsersModule")
.provider("UsersController")
.controller("UsersController")
.build();
let error = ModuleGraph::from_modules([users]).unwrap_err();
assert!(matches!(
error,
NidusError::ModuleProviderControllerConflict { .. }
));
assert!(error.to_string().contains("UsersModule"));
assert!(error.to_string().contains("UsersController"));
}
#[test]
fn module_graph_rejects_duplicate_imports() {
let database = ModuleBuilder::new("DatabaseModule")
.provider("DatabasePool")
.export("DatabasePool")
.build();
let users = ModuleBuilder::new("UsersModule")
.import("DatabaseModule")
.import("DatabaseModule")
.build();
let error = ModuleGraph::from_modules([database, users]).unwrap_err();
assert!(matches!(error, NidusError::DuplicateModuleImport { .. }));
assert!(error.to_string().contains("UsersModule"));
assert!(error.to_string().contains("DatabaseModule"));
}
#[test]
fn module_graph_rejects_duplicate_exports() {
let users = ModuleBuilder::new("UsersModule")
.provider("UsersService")
.export("UsersService")
.export("UsersService")
.build();
let error = ModuleGraph::from_modules([users]).unwrap_err();
assert!(matches!(error, NidusError::DuplicateModuleExport { .. }));
assert!(error.to_string().contains("UsersModule"));
assert!(error.to_string().contains("UsersService"));
}
#[test]
fn module_graph_rejects_exports_that_are_not_local_providers() {
let users = ModuleBuilder::new("UsersModule")
.provider("UsersRepository")
.export("UsersService")
.build();
let error = ModuleGraph::from_modules([users]).unwrap_err();
assert!(matches!(error, NidusError::MissingProviderExport { .. }));
assert!(error.to_string().contains("UsersService"));
}
#[test]
fn module_graph_rejects_local_providers_that_conflict_with_imported_exports() {
let database = ModuleBuilder::new("DatabaseModule")
.provider("DatabasePool")
.export("DatabasePool")
.build();
let users = ModuleBuilder::new("UsersModule")
.import("DatabaseModule")
.provider("DatabasePool")
.build();
let error = ModuleGraph::from_modules([database, users]).unwrap_err();
assert!(matches!(
error,
NidusError::ProviderVisibilityConflict { .. }
));
assert!(error.to_string().contains("UsersModule"));
assert!(error.to_string().contains("DatabasePool"));
assert!(error.to_string().contains("DatabaseModule"));
}
#[test]
fn module_graph_rejects_ambiguous_visible_providers() {
let database_a = ModuleBuilder::new("PrimaryDatabaseModule")
.provider("DatabasePool")
.export("DatabasePool")
.build();
let database_b = ModuleBuilder::new("ReplicaDatabaseModule")
.provider("DatabasePool")
.export("DatabasePool")
.build();
let users = ModuleBuilder::new("UsersModule")
.import("PrimaryDatabaseModule")
.import("ReplicaDatabaseModule")
.build();
let error = ModuleGraph::from_modules([database_a, database_b, users]).unwrap_err();
assert!(matches!(error, NidusError::AmbiguousProvider { .. }));
assert!(error.to_string().contains("DatabasePool"));
}