diff --git a/elebox-core/src/manufacturer.rs b/elebox-core/src/manufacturer.rs index 41dce1f..cb042d7 100644 --- a/elebox-core/src/manufacturer.rs +++ b/elebox-core/src/manufacturer.rs @@ -163,7 +163,7 @@ mod tests { ]; for (name, alias, url) in test_cases { - test_add_no_existing_value( + test_add_not_existing_value( name.to_string(), alias.map(|s| s.to_string()), url.map(|s| s.to_string()), @@ -171,7 +171,7 @@ mod tests { } } - fn test_add_no_existing_value(name: String, alias: Option, url: Option) { + fn test_add_not_existing_value(name: String, alias: Option, url: Option) { // Arrange let mfr = Manufacturer::new( &name.clone(), @@ -189,7 +189,7 @@ mod tests { // Mock add() to check all field and return Ok(()) mock_db .expect_add() - .withf(move |db_mfr: &DbManufacturer| { + .withf(move |db_mfr| { db_mfr.name == name && db_mfr.alias == alias.as_deref().unwrap_or("") && db_mfr.url == url.as_deref().unwrap_or("") @@ -203,4 +203,371 @@ mod tests { // Assert assert!(result.is_ok()); } + + #[test] + fn test_delete_existing() { + // Arrange + const NAME: &str = "TestName"; + const ID: &str = "TestID"; + + let mut mock_db = MockMyDatabase::new(); + + // Mock get_id() to check name, and return ID indicating the item existing + mock_db + .expect_get_id() + .withf(|name| name == NAME) + .returning(|_| Ok(ID.to_string())); + + // Mock delete() to check ID, and return Ok(()) + mock_db + .expect_delete() + .withf(|id| id == ID) + .returning(|_| Ok(())); + + // Act + let handler = ManufacturerHandler { db: &mock_db }; + let result = handler.delete(NAME); + + // Assert + assert!(result.is_ok()); + } + + #[test] + fn test_get_existing() { + // Arrange + const ID: &str = "TestID"; + const NAME: &str = "TestName"; + const ALIAS: &str = "TestAlias"; + const URL: &str = "https://test.com"; + + let mut mock_db = MockMyDatabase::new(); + + // Mock get_id() to check name, and return ID indicating the item existing + mock_db + .expect_get_id() + .withf(|name| name == NAME) + .returning(|_| Ok(ID.to_string())); + + // Mock get() to check ID, and return item + mock_db.expect_get().withf(|id| id == ID).returning(|_| { + Ok(DbManufacturer { + name: NAME.to_string(), + alias: ALIAS.to_string(), + url: URL.to_string(), + }) + }); + + // Act + let handler = ManufacturerHandler { db: &mock_db }; + let result = handler.get(NAME); + + // Assert + let mfr = result.expect("Expected OK"); + assert_eq!(mfr.name, NAME); + assert_eq!(mfr.alias.as_deref(), Some(ALIAS)); + assert_eq!(mfr.url.as_deref(), Some(URL)); + } + + #[test] + fn test_list_existing() { + // Arrange + const NAME: &str = "TestName"; + const ALIAS: &str = "TestAlias"; + const URL: &str = "https://test.com"; + const TEST_NUMBER: u16 = 10; + + let mut mock_db = MockMyDatabase::new(); + + // Mock list() return items + mock_db.expect_list().returning(|| { + let data: Vec = (0..TEST_NUMBER) + .map(|i| DbManufacturer { + name: format!("{NAME}{i}"), + alias: format!("{ALIAS}{i}"), + url: format!("{URL}{i}"), + }) + .collect(); + Ok(data) + }); + + // Act + let handler = ManufacturerHandler { db: &mock_db }; + let result = handler.list(); + + // Assert + let mfrs = result.expect("Expected OK"); + for (i, m) in mfrs.iter().enumerate() { + assert_eq!(m.name, format!("{NAME}{i}")); + assert_eq!(m.alias, Some(format!("{ALIAS}{i}"))); + assert_eq!(m.url, Some(format!("{URL}{i}"))); + } + } + + /// Update item, name does not change + #[test] + fn test_update_not_existing() { + // Arrange + const NAME: &str = "TestName"; + const ALIAS: &str = "TestAlias"; + const URL: &str = "https://test.com"; + const ID: &str = "TestID"; + + let mut mock_db = MockMyDatabase::new(); + + // Mock get_id() to check name, and return ID indicating the item existing + mock_db + .expect_get_id() + .withf(|name| name == NAME) + .returning(|_| Ok(ID.to_string())); + + // Mock update() check all fields and return Ok + mock_db + .expect_update() + .withf(|ori_id, new_item| { + ori_id == ID + && new_item.name == NAME + && new_item.alias == ALIAS + && new_item.url == URL + }) + .returning(|_, _| Ok(())); + + // Act + let new_item = Manufacturer { + name: NAME.to_string(), + alias: Some(ALIAS.to_string()), + url: Some(URL.to_string()), + }; + + let handler = ManufacturerHandler { db: &mock_db }; + let result = handler.update(NAME, &new_item); + + // Assert + assert!(result.is_ok()); + } + + /// Update item, name changed and not duplicate + #[test] + fn test_update_new_name_not_existing() { + // Arrange + const ORI_NAME: &str = "TestNameOri"; + const NEW_NAME: &str = "TestNameNew"; + const ALIAS: &str = "TestAlias"; + const URL: &str = "https://test.com"; + const ID: &str = "TestID"; + + let mut mock_db = MockMyDatabase::new(); + + // Mock get_id() to check name, and return ID indicating the item existing + mock_db + .expect_get_id() + .withf(|name| name == ORI_NAME) + .returning(|_| Ok(ID.to_string())); + + // New item new does not existing + mock_db + .expect_get_id() + .withf(|name| name == NEW_NAME) + .returning(|_| Err(DbError::NotExists(NEW_NAME.to_string()))); + + // Mock update() check all fields and return Ok + mock_db + .expect_update() + .withf(|ori_id, new_item| { + ori_id == ID + && new_item.name == NEW_NAME + && new_item.alias == ALIAS + && new_item.url == URL + }) + .returning(|_, _| Ok(())); + + // Act + let new_item = Manufacturer { + name: NEW_NAME.to_string(), + alias: Some(ALIAS.to_string()), + url: Some(URL.to_string()), + }; + + let handler = ManufacturerHandler { db: &mock_db }; + let result = handler.update(ORI_NAME, &new_item); + + // Assert + assert!(result.is_ok()); + } + + /// Update item, name changed and duplicate + #[test] + fn test_update_new_name_existing() { + // Arrange + const ORI_NAME: &str = "TestNameOri"; + const NEW_NAME: &str = "TestNameNew"; + const ALIAS: &str = "TestAlias"; + const URL: &str = "https://test.com"; + const ORI_ID: &str = "TestIDOri"; + const NEW_ID: &str = "TestIDNew"; + + let mut mock_db = MockMyDatabase::new(); + + // Check original item existing + mock_db + .expect_get_id() + .withf(|name| name == ORI_NAME) + .returning(|_| Ok(ORI_ID.to_string())); + + // New item name existing + mock_db + .expect_get_id() + .withf(|name| name == NEW_NAME) + .returning(|_| Ok(NEW_ID.to_string())); + + // Act + let new_item = Manufacturer { + name: NEW_NAME.to_string(), + alias: Some(ALIAS.to_string()), + url: Some(URL.to_string()), + }; + + let handler = ManufacturerHandler { db: &mock_db }; + let result = handler.update(ORI_NAME, &new_item); + + // Assert + if let Err(EleboxError::AlreadyExists(_, _)) = result { + // Ok + } else { + panic!("Expected AlreadyExists error") + } + } + + #[test] + fn test_to_db_item_some() { + // Arrange + const NAME: &str = "TestName"; + const ALIAS: &str = "TestAlias"; + const URL: &str = "https://test.com"; + + let item = Manufacturer { + name: NAME.to_string(), + alias: Some(ALIAS.to_string()), + url: Some(URL.to_string()), + }; + + let mock_db = MockMyDatabase::new(); + + // Act + let handler = ManufacturerHandler { db: &mock_db }; + let result = handler.to_db_item(&item); + + // Assert + let db_item = result.expect("Expected OK"); + assert_eq!(db_item.name, NAME.to_string()); + assert_eq!(db_item.alias, ALIAS.to_string()); + assert_eq!(db_item.url, URL.to_string()); + } + + #[test] + fn test_to_db_item_none() { + // Arrange + const NAME: &str = "TestName"; + const ALIAS: &str = ""; + const URL: &str = ""; + + let item = Manufacturer { + name: NAME.to_string(), + alias: None, + url: None, + }; + + let mock_db = MockMyDatabase::new(); + + // Act + let handler = ManufacturerHandler { db: &mock_db }; + let result = handler.to_db_item(&item); + + // Assert + let db_item = result.expect("Expected OK"); + assert_eq!(db_item.name, NAME.to_string()); + assert_eq!(db_item.alias, ALIAS.to_string()); + assert_eq!(db_item.url, URL.to_string()); + } + + #[test] + fn test_to_item_some() { + // Arrange + const NAME: &str = "TestName"; + const ALIAS: &str = "TestAlias"; + const URL: &str = "https://test.com"; + + let item = DbManufacturer { + name: NAME.to_string(), + alias: ALIAS.to_string(), + url: URL.to_string(), + }; + + let mock_db = MockMyDatabase::new(); + + // Act + let handler = ManufacturerHandler { db: &mock_db }; + let item = handler.to_item(&item); + + // Assert + assert_eq!(item.name, NAME.to_string()); + assert_eq!(item.alias, Some(ALIAS.to_string())); + assert_eq!(item.url, Some(URL.to_string())); + } + + #[test] + fn test_to_item_none() { + // Arrange + const NAME: &str = "TestName"; + const ALIAS: &str = ""; + const URL: &str = ""; + + let item = DbManufacturer { + name: NAME.to_string(), + alias: ALIAS.to_string(), + url: URL.to_string(), + }; + + let mock_db = MockMyDatabase::new(); + + // Act + let handler = ManufacturerHandler { db: &mock_db }; + let item = handler.to_item(&item); + + // Assert + assert_eq!(item.name, NAME.to_string()); + assert_eq!(item.alias, None); + assert_eq!(item.url, None); + } + + #[test] + fn test_new_item_some() { + // Arrange + const NAME: &str = "TestName"; + const ALIAS: Option<&str> = Some("TestAlias"); + const URL: Option<&str> = Some("https://test.com"); + + // Act + let item = Manufacturer::new(NAME, ALIAS, URL); + + // Assert + assert_eq!(item.name, NAME); + assert_eq!(item.alias.as_deref(), ALIAS); + assert_eq!(item.url.as_deref(), URL); + } + + #[test] + fn test_new_item_none() { + // Arrange + const NAME: &str = "TestName"; + const ALIAS: Option<&str> = None; + const URL: Option<&str> = None; + + // Act + let item = Manufacturer::new(NAME, ALIAS, URL); + + // Assert + assert_eq!(item.name, NAME); + assert_eq!(item.alias.as_deref(), ALIAS); + assert_eq!(item.url.as_deref(), URL); + } }