feat: define Store aggregate, commands and event in Identity domain
This commit is contained in:
parent
3026294832
commit
176e9ff6f6
7 changed files with 460 additions and 3 deletions
|
@ -14,8 +14,8 @@ use super::update_password::events::*;
|
||||||
use crate::identity::domain::{
|
use crate::identity::domain::{
|
||||||
employee_logged_in_event::*, employee_registered_event::*, invite_accepted_event::*,
|
employee_logged_in_event::*, employee_registered_event::*, invite_accepted_event::*,
|
||||||
login_otp_sent_event::*, organization_exited_event::*, phone_number_changed_event::*,
|
login_otp_sent_event::*, organization_exited_event::*, phone_number_changed_event::*,
|
||||||
phone_number_verified_event::*, resend_login_otp_event::*, verification_otp_resent_event::*,
|
phone_number_verified_event::*, resend_login_otp_event::*, store_added_event::*,
|
||||||
verification_otp_sent_event::*,
|
store_updated_event::*, verification_otp_resent_event::*, verification_otp_sent_event::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
@ -39,6 +39,10 @@ pub enum IdentityEvent {
|
||||||
PhoneNumberChanged(PhoneNumberChangedEvent),
|
PhoneNumberChanged(PhoneNumberChangedEvent),
|
||||||
InviteAccepted(InviteAcceptedEvent),
|
InviteAccepted(InviteAcceptedEvent),
|
||||||
OrganizationExited(OrganizationExitedEvent),
|
OrganizationExited(OrganizationExitedEvent),
|
||||||
|
|
||||||
|
// store events
|
||||||
|
StoreAdded(StoreAddedEvent),
|
||||||
|
StoreUpdated(StoreUpdatedEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: define password type that takes string and converts to hash
|
//TODO: define password type that takes string and converts to hash
|
||||||
|
@ -69,6 +73,10 @@ impl DomainEvent for IdentityEvent {
|
||||||
IdentityEvent::PhoneNumberChanged { .. } => "EmployeePhoneNumberChanged",
|
IdentityEvent::PhoneNumberChanged { .. } => "EmployeePhoneNumberChanged",
|
||||||
IdentityEvent::InviteAccepted { .. } => "EmployeeInviteAccepted",
|
IdentityEvent::InviteAccepted { .. } => "EmployeeInviteAccepted",
|
||||||
IdentityEvent::OrganizationExited { .. } => "EmployeeOrganizationExited",
|
IdentityEvent::OrganizationExited { .. } => "EmployeeOrganizationExited",
|
||||||
|
|
||||||
|
// store
|
||||||
|
IdentityEvent::StoreAdded { .. } => "IdentityStoreAdded",
|
||||||
|
IdentityEvent::StoreUpdated { .. } => "IdentityStoreUpdated",
|
||||||
};
|
};
|
||||||
|
|
||||||
e.to_string()
|
e.to_string()
|
||||||
|
|
109
src/identity/domain/add_store_command.rs
Normal file
109
src/identity/domain/add_store_command.rs
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
use derive_builder::Builder;
|
||||||
|
use derive_getters::Getters;
|
||||||
|
use derive_more::{Display, Error};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Error, Display, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum AddStoreCommandError {
|
||||||
|
NameIsEmpty,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone, Builder, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters,
|
||||||
|
)]
|
||||||
|
#[builder(build_fn(validate = "Self::validate"))]
|
||||||
|
pub struct AddStoreCommand {
|
||||||
|
#[builder(setter(custom))]
|
||||||
|
name: String,
|
||||||
|
#[builder(setter(custom))]
|
||||||
|
address: Option<String>,
|
||||||
|
store_id: Uuid,
|
||||||
|
owner: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddStoreCommandBuilder {
|
||||||
|
pub fn address(&mut self, address: Option<String>) -> &mut Self {
|
||||||
|
self.address = if let Some(address) = address {
|
||||||
|
let address = address.trim();
|
||||||
|
if address.is_empty() {
|
||||||
|
Some(None)
|
||||||
|
} else {
|
||||||
|
Some(Some(address.to_owned()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Some(None)
|
||||||
|
};
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&mut self, name: String) -> &mut Self {
|
||||||
|
self.name = Some(name.trim().to_owned());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self) -> Result<(), String> {
|
||||||
|
let name = self.name.as_ref().unwrap().trim().to_owned();
|
||||||
|
if name.is_empty() {
|
||||||
|
return Err(AddStoreCommandError::NameIsEmpty.to_string());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::tests::bdd::*;
|
||||||
|
use crate::utils::uuid::tests::*;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cmd() {
|
||||||
|
let name = "foo";
|
||||||
|
let address = "bar";
|
||||||
|
let owner = UUID;
|
||||||
|
|
||||||
|
// address = None
|
||||||
|
let cmd = AddStoreCommandBuilder::default()
|
||||||
|
.name(name.into())
|
||||||
|
.address(None)
|
||||||
|
.owner(owner)
|
||||||
|
.store_id(UUID)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
// let cmd = AddStoreCommand::new(name.into(), None, owner, UUID).unwrap();
|
||||||
|
assert_eq!(cmd.name(), name);
|
||||||
|
assert_eq!(cmd.address(), &None);
|
||||||
|
assert_eq!(cmd.owner(), &owner);
|
||||||
|
assert_eq!(*cmd.store_id(), UUID);
|
||||||
|
|
||||||
|
// address = Some
|
||||||
|
let cmd = AddStoreCommandBuilder::default()
|
||||||
|
.name(name.into())
|
||||||
|
.address(Some(address.into()))
|
||||||
|
.owner(owner)
|
||||||
|
.store_id(UUID)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
// let cmd = AddStoreCommand::new(name.into(), Some(address.into()), owner, UUID).unwrap();
|
||||||
|
assert_eq!(cmd.name(), name);
|
||||||
|
assert_eq!(cmd.address(), &Some(address.to_owned()));
|
||||||
|
assert_eq!(cmd.owner(), &owner);
|
||||||
|
assert_eq!(*cmd.store_id(), UUID);
|
||||||
|
|
||||||
|
// AddStoreCommandError::NameIsEmpty
|
||||||
|
|
||||||
|
assert!(AddStoreCommandBuilder::default()
|
||||||
|
.name("".into())
|
||||||
|
.address(Some(address.into()))
|
||||||
|
.owner(owner)
|
||||||
|
.store_id(UUID)
|
||||||
|
.build()
|
||||||
|
.is_err())
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
pub mod aggregate;
|
pub mod aggregate;
|
||||||
pub mod employee_aggregate;
|
pub mod employee_aggregate;
|
||||||
//pub mod employee_commands;
|
//pub mod employee_commands;
|
||||||
// pub mod store_aggregate;
|
pub mod store_aggregate;
|
||||||
// pub mod invite;
|
// pub mod invite;
|
||||||
|
|
||||||
// events
|
// events
|
||||||
|
@ -17,15 +17,19 @@ pub mod organization_exited_event;
|
||||||
pub mod phone_number_changed_event;
|
pub mod phone_number_changed_event;
|
||||||
pub mod phone_number_verified_event;
|
pub mod phone_number_verified_event;
|
||||||
pub mod resend_login_otp_event;
|
pub mod resend_login_otp_event;
|
||||||
|
pub mod store_added_event;
|
||||||
|
pub mod store_updated_event;
|
||||||
pub mod verification_otp_resent_event;
|
pub mod verification_otp_resent_event;
|
||||||
pub mod verification_otp_sent_event;
|
pub mod verification_otp_sent_event;
|
||||||
|
|
||||||
// commands
|
// commands
|
||||||
pub mod accept_invite_command;
|
pub mod accept_invite_command;
|
||||||
|
pub mod add_store_command;
|
||||||
pub mod change_phone_number_command;
|
pub mod change_phone_number_command;
|
||||||
pub mod employee_login_command;
|
pub mod employee_login_command;
|
||||||
pub mod employee_register_command;
|
pub mod employee_register_command;
|
||||||
pub mod exit_organization_command;
|
pub mod exit_organization_command;
|
||||||
pub mod resend_login_otp_command;
|
pub mod resend_login_otp_command;
|
||||||
pub mod resend_verification_otp_command;
|
pub mod resend_verification_otp_command;
|
||||||
|
pub mod update_store_command;
|
||||||
pub mod verify_phone_number_command;
|
pub mod verify_phone_number_command;
|
||||||
|
|
18
src/identity/domain/store_added_event.rs
Normal file
18
src/identity/domain/store_added_event.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
use derive_builder::Builder;
|
||||||
|
use derive_getters::Getters;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone, Debug, Builder, Serialize, Deserialize, Getters, Eq, PartialEq, Ord, PartialOrd,
|
||||||
|
)]
|
||||||
|
pub struct StoreAddedEvent {
|
||||||
|
name: String,
|
||||||
|
address: Option<String>,
|
||||||
|
owner: Uuid,
|
||||||
|
store_id: Uuid,
|
||||||
|
}
|
148
src/identity/domain/store_aggregate.rs
Normal file
148
src/identity/domain/store_aggregate.rs
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use cqrs_es::Aggregate;
|
||||||
|
use derive_builder::Builder;
|
||||||
|
use derive_getters::Getters;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::identity::application::services::{errors::*, events::*, *};
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone, Default, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Builder, Getters,
|
||||||
|
)]
|
||||||
|
pub struct Store {
|
||||||
|
name: String,
|
||||||
|
address: Option<String>,
|
||||||
|
owner: Uuid,
|
||||||
|
store_id: Uuid,
|
||||||
|
#[builder(default = "false")]
|
||||||
|
deleted: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Aggregate for Store {
|
||||||
|
type Command = IdentityCommand;
|
||||||
|
type Event = IdentityEvent;
|
||||||
|
type Error = IdentityError;
|
||||||
|
type Services = std::sync::Arc<dyn IdentityServicesInterface>;
|
||||||
|
|
||||||
|
// This identifier should be unique to the system.
|
||||||
|
fn aggregate_type() -> String {
|
||||||
|
"billing.store".to_string()
|
||||||
|
}
|
||||||
|
// The aggregate logic goes here. Note that this will be the _bulk_ of a CQRS system
|
||||||
|
// so expect to use helper functions elsewhere to keep the code clean.
|
||||||
|
async fn handle(
|
||||||
|
&self,
|
||||||
|
command: Self::Command,
|
||||||
|
services: &Self::Services,
|
||||||
|
) -> Result<Vec<Self::Event>, Self::Error> {
|
||||||
|
match command {
|
||||||
|
IdentityCommand::AddStore(cmd) => {
|
||||||
|
let res = services.add_store().add_store(cmd).await?;
|
||||||
|
Ok(vec![IdentityEvent::StoreAdded(res)])
|
||||||
|
}
|
||||||
|
IdentityCommand::UpdateStore(cmd) => {
|
||||||
|
let res = services.update_store().update_store(cmd).await?;
|
||||||
|
Ok(vec![IdentityEvent::StoreUpdated(res)])
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => Ok(Vec::default()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(&mut self, event: Self::Event) {
|
||||||
|
match event {
|
||||||
|
IdentityEvent::StoreAdded(e) => {
|
||||||
|
self.name = e.name().into();
|
||||||
|
self.address = e.address().as_ref().map(|s| s.to_string());
|
||||||
|
self.owner = *e.owner();
|
||||||
|
self.store_id = *e.store_id();
|
||||||
|
self.deleted = false;
|
||||||
|
}
|
||||||
|
IdentityEvent::StoreUpdated(e) => *self = e.new_store().clone(),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//#[cfg(test)]
|
||||||
|
//mod tests {
|
||||||
|
// use std::sync::Arc;
|
||||||
|
//
|
||||||
|
// use cqrs_es::test::TestFramework;
|
||||||
|
// use update_store_service::tests::mock_update_store_service;
|
||||||
|
//
|
||||||
|
// use super::*;
|
||||||
|
// use crate::billing::{
|
||||||
|
// application::services::add_store_service::tests::*,
|
||||||
|
// domain::{
|
||||||
|
// add_store_command::*, commands::IdentityCommand, events::IdentityEvent,
|
||||||
|
// store_added_event::*, store_updated_event::tests::get_store_updated_event_from_command,
|
||||||
|
// update_store_command::tests::get_update_store_cmd,
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
// use crate::tests::bdd::*;
|
||||||
|
// use crate::utils::uuid::tests::*;
|
||||||
|
//
|
||||||
|
// // A test framework that will apply our events and command
|
||||||
|
// // and verify that the logic works as expected.
|
||||||
|
// type StoreTestFramework = TestFramework<Store>;
|
||||||
|
//
|
||||||
|
// #[test]
|
||||||
|
// fn test_create_store() {
|
||||||
|
// let name = "store_name";
|
||||||
|
// let address = Some("store_address".to_string());
|
||||||
|
// let owner = UUID;
|
||||||
|
// let store_id = UUID;
|
||||||
|
//
|
||||||
|
// let expected = StoreAddedEventBuilder::default()
|
||||||
|
// .name(name.into())
|
||||||
|
// .address(address.clone())
|
||||||
|
// .store_id(store_id)
|
||||||
|
// .owner(owner)
|
||||||
|
// .build()
|
||||||
|
// .unwrap();
|
||||||
|
// let expected = IdentityEvent::StoreAdded(expected);
|
||||||
|
//
|
||||||
|
// let cmd = AddStoreCommandBuilder::default()
|
||||||
|
// .name(name.into())
|
||||||
|
// .address(address.clone())
|
||||||
|
// .owner(owner)
|
||||||
|
// .store_id(UUID)
|
||||||
|
// .build()
|
||||||
|
// .unwrap();
|
||||||
|
//
|
||||||
|
// let mut services = MockIdentityServicesInterface::new();
|
||||||
|
// services
|
||||||
|
// .expect_add_store()
|
||||||
|
// .times(IS_CALLED_ONLY_ONCE.unwrap())
|
||||||
|
// .return_const(mock_add_store_service(IS_CALLED_ONLY_ONCE, cmd.clone()));
|
||||||
|
//
|
||||||
|
// StoreTestFramework::with(Arc::new(services))
|
||||||
|
// .given_no_previous_events()
|
||||||
|
// .when(IdentityCommand::AddStore(cmd))
|
||||||
|
// .then_expect_events(vec![expected]);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// #[test]
|
||||||
|
// fn test_update_store() {
|
||||||
|
// let cmd = get_update_store_cmd();
|
||||||
|
// let expected = IdentityEvent::StoreUpdated(get_store_updated_event_from_command(&cmd));
|
||||||
|
//
|
||||||
|
// let mut services = MockIdentityServicesInterface::new();
|
||||||
|
// services
|
||||||
|
// .expect_update_store()
|
||||||
|
// .times(IS_CALLED_ONLY_ONCE.unwrap())
|
||||||
|
// .return_const(mock_update_store_service(IS_CALLED_ONLY_ONCE, cmd.clone()));
|
||||||
|
//
|
||||||
|
// StoreTestFramework::with(Arc::new(services))
|
||||||
|
// .given_no_previous_events()
|
||||||
|
// .when(IdentityCommand::UpdateStore(cmd))
|
||||||
|
// .then_expect_events(vec![expected]);
|
||||||
|
// }
|
||||||
|
//}
|
43
src/identity/domain/store_updated_event.rs
Normal file
43
src/identity/domain/store_updated_event.rs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
use derive_builder::Builder;
|
||||||
|
use derive_getters::Getters;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::store_aggregate::*;
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone, Debug, Builder, Serialize, Deserialize, Getters, Eq, PartialEq, Ord, PartialOrd,
|
||||||
|
)]
|
||||||
|
pub struct StoreUpdatedEvent {
|
||||||
|
added_by_user: Uuid,
|
||||||
|
old_store: Store,
|
||||||
|
new_store: Store,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub mod tests {
|
||||||
|
use crate::identity::domain::update_store_command::UpdateStoreCommand;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub fn get_store_updated_event_from_command(cmd: &UpdateStoreCommand) -> StoreUpdatedEvent {
|
||||||
|
let new_store = StoreBuilder::default()
|
||||||
|
.name(cmd.name().into())
|
||||||
|
.address(cmd.address().as_ref().map(|s| s.to_string()))
|
||||||
|
.owner(*cmd.owner())
|
||||||
|
.store_id(*cmd.old_store().store_id())
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
StoreUpdatedEventBuilder::default()
|
||||||
|
.new_store(new_store)
|
||||||
|
.old_store(cmd.old_store().clone())
|
||||||
|
.added_by_user(*cmd.adding_by())
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
127
src/identity/domain/update_store_command.rs
Normal file
127
src/identity/domain/update_store_command.rs
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
use derive_getters::Getters;
|
||||||
|
use derive_more::{Display, Error};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::store_aggregate::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Error, Display, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum UpdateStoreCommandError {
|
||||||
|
NameIsEmpty,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Getters)]
|
||||||
|
pub struct UpdateStoreCommand {
|
||||||
|
name: String,
|
||||||
|
address: Option<String>,
|
||||||
|
owner: Uuid,
|
||||||
|
old_store: Store,
|
||||||
|
adding_by: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UpdateStoreCommand {
|
||||||
|
pub fn new(
|
||||||
|
name: String,
|
||||||
|
address: Option<String>,
|
||||||
|
owner: Uuid,
|
||||||
|
old_store: Store,
|
||||||
|
adding_by: Uuid,
|
||||||
|
) -> Result<Self, UpdateStoreCommandError> {
|
||||||
|
let address: Option<String> = if let Some(address) = address {
|
||||||
|
let address = address.trim();
|
||||||
|
if address.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(address.to_owned())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = name.trim().to_owned();
|
||||||
|
if name.is_empty() {
|
||||||
|
return Err(UpdateStoreCommandError::NameIsEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
name,
|
||||||
|
address,
|
||||||
|
owner,
|
||||||
|
old_store,
|
||||||
|
adding_by,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub mod tests {
|
||||||
|
use crate::utils::uuid::tests::UUID;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub fn get_update_store_cmd() -> UpdateStoreCommand {
|
||||||
|
let name = "foo";
|
||||||
|
let address = "bar";
|
||||||
|
let owner = UUID;
|
||||||
|
let adding_by = UUID;
|
||||||
|
let old_store = Store::default();
|
||||||
|
|
||||||
|
UpdateStoreCommand::new(
|
||||||
|
name.into(),
|
||||||
|
Some(address.into()),
|
||||||
|
owner,
|
||||||
|
old_store.clone(),
|
||||||
|
adding_by,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cmd() {
|
||||||
|
let name = "foo";
|
||||||
|
let address = "bar";
|
||||||
|
let owner = UUID;
|
||||||
|
let old_store = Store::default();
|
||||||
|
let adding_by = Uuid::new_v4();
|
||||||
|
|
||||||
|
// address = None
|
||||||
|
let cmd = UpdateStoreCommand::new(name.into(), None, owner, old_store.clone(), adding_by)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(cmd.name(), name);
|
||||||
|
assert_eq!(cmd.address(), &None);
|
||||||
|
assert_eq!(cmd.owner(), &owner);
|
||||||
|
assert_eq!(cmd.old_store(), &old_store);
|
||||||
|
assert_eq!(cmd.adding_by(), &adding_by);
|
||||||
|
|
||||||
|
// address = Some
|
||||||
|
let cmd = UpdateStoreCommand::new(
|
||||||
|
name.into(),
|
||||||
|
Some(address.into()),
|
||||||
|
owner,
|
||||||
|
old_store.clone(),
|
||||||
|
adding_by,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(cmd.name(), name);
|
||||||
|
assert_eq!(cmd.address(), &Some(address.to_owned()));
|
||||||
|
assert_eq!(cmd.owner(), &owner);
|
||||||
|
assert_eq!(cmd.old_store(), &old_store);
|
||||||
|
assert_eq!(cmd.adding_by(), &adding_by);
|
||||||
|
|
||||||
|
// UpdateStoreCommandError::NameIsEmpty
|
||||||
|
assert_eq!(
|
||||||
|
UpdateStoreCommand::new(
|
||||||
|
"".into(),
|
||||||
|
Some(address.into()),
|
||||||
|
owner,
|
||||||
|
old_store.clone(),
|
||||||
|
adding_by
|
||||||
|
),
|
||||||
|
Err(UpdateStoreCommandError::NameIsEmpty)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue