feat: employee aggregate tests
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Aravinth Manivannan 2024-10-07 13:37:38 +05:30
parent 5f97c96f07
commit edd84dd537
Signed by: realaravinth
GPG key ID: F8F50389936984FF
18 changed files with 441 additions and 59 deletions

View file

@ -2,12 +2,15 @@
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
use derive_builder::Builder; use derive_builder::Builder;
use mockall::predicate::*;
use mockall::*;
use crate::identity::application::port::output::db::{emp_id_exists::*, get_invite::*}; use crate::identity::application::port::output::db::{emp_id_exists::*, get_invite::*};
use crate::identity::domain::{accept_invite_command::*, invite_accepted_event::*}; use crate::identity::domain::{accept_invite_command::*, invite_accepted_event::*};
use super::errors::*; use super::errors::*;
#[automock]
#[async_trait::async_trait] #[async_trait::async_trait]
pub trait EmployeeAcceptInviteUseCase: Send + Sync { pub trait EmployeeAcceptInviteUseCase: Send + Sync {
async fn accept_invite(&self, cmd: AcceptInviteCommand) -> IdentityResult<InviteAcceptedEvent>; async fn accept_invite(&self, cmd: AcceptInviteCommand) -> IdentityResult<InviteAcceptedEvent>;
@ -60,6 +63,26 @@ mod tests {
use super::*; use super::*;
impl EmployeeAcceptInviteService {
pub fn mock_service(
times: Option<usize>,
cmd: AcceptInviteCommand,
) -> EmployeeAcceptInviteServiceObj {
let res = InviteAcceptedEvent::get_event(&cmd);
let mut m = MockEmployeeAcceptInviteUseCase::default();
if let Some(times) = times {
m.expect_accept_invite()
.times(times)
.returning(move |_| Ok(res.clone()));
} else {
m.expect_accept_invite().returning(move |_| Ok(res.clone()));
}
std::sync::Arc::new(m)
}
}
#[actix_rt::test] #[actix_rt::test]
async fn test_service() { async fn test_service() {
let s = EmployeeAcceptInviteServiceBuilder::default() let s = EmployeeAcceptInviteServiceBuilder::default()

View file

@ -2,12 +2,15 @@
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
use derive_builder::Builder; use derive_builder::Builder;
use mockall::predicate::*;
use mockall::*;
use crate::identity::application::port::output::db::{emp_id_exists::*, store_id_exists::*}; use crate::identity::application::port::output::db::{emp_id_exists::*, store_id_exists::*};
use crate::identity::domain::{exit_organization_command::*, organization_exited_event::*}; use crate::identity::domain::{exit_organization_command::*, organization_exited_event::*};
use super::errors::*; use super::errors::*;
#[automock]
#[async_trait::async_trait] #[async_trait::async_trait]
pub trait EmployeeExitOrganizationUseCase: Send + Sync { pub trait EmployeeExitOrganizationUseCase: Send + Sync {
async fn exit_organization( async fn exit_organization(
@ -60,6 +63,27 @@ mod tests {
use super::*; use super::*;
impl EmployeeExitOrganizationService {
pub fn mock_service(
times: Option<usize>,
cmd: ExitOrganizationCommand,
) -> EmployeeExitOrganizationServiceObj {
let res = OrganizationExitedEvent::get_event(&cmd);
let mut m = MockEmployeeExitOrganizationUseCase::default();
if let Some(times) = times {
m.expect_exit_organization()
.times(times)
.returning(move |_| Ok(res.clone()));
} else {
m.expect_exit_organization()
.returning(move |_| Ok(res.clone()));
}
std::sync::Arc::new(m)
}
}
#[actix_rt::test] #[actix_rt::test]
async fn test_service() { async fn test_service() {
let s = EmployeeExitOrganizationServiceBuilder::default() let s = EmployeeExitOrganizationServiceBuilder::default()

View file

@ -236,7 +236,7 @@ mod tests {
let s = EmployeeLoginServiceBuilder::default() let s = EmployeeLoginServiceBuilder::default()
.db_phone_exists_adapter(mock_phone_exists_db_port(IS_CALLED_ONLY_ONCE, true)) .db_phone_exists_adapter(mock_phone_exists_db_port(IS_CALLED_ONLY_ONCE, true))
.db_get_emp_id_from_phone_number_adapter(mock_get_emp_id_from_phone_number_db_port( .db_get_emp_id_from_phone_number_adapter(mock_get_emp_id_from_phone_number_db_port(
IS_NEVER_CALLED, IS_CALLED_ONLY_ONCE,
)) ))
.db_create_login_otp_adapter(mock_create_login_otp_db_port(IS_NEVER_CALLED)) .db_create_login_otp_adapter(mock_create_login_otp_db_port(IS_NEVER_CALLED))
.db_delete_login_otp(mock_delete_login_otp_db_port(IS_NEVER_CALLED)) .db_delete_login_otp(mock_delete_login_otp_db_port(IS_NEVER_CALLED))

View file

@ -2,6 +2,8 @@
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
use derive_builder::Builder; use derive_builder::Builder;
use mockall::predicate::*;
use mockall::*;
use crate::identity::application::port::output::{ use crate::identity::application::port::output::{
db::{ db::{
@ -18,6 +20,7 @@ use crate::utils::random_number::*;
use super::employee_register_service::OTP_LEN; use super::employee_register_service::OTP_LEN;
use super::errors::*; use super::errors::*;
#[automock]
#[async_trait::async_trait] #[async_trait::async_trait]
pub trait EmployeeResendLoginOTPUseCase: Send + Sync { pub trait EmployeeResendLoginOTPUseCase: Send + Sync {
async fn resend_otp(&self, cmd: ResendLoginOTPCommand) -> IdentityResult<ResentLoginOTPEvent>; async fn resend_otp(&self, cmd: ResendLoginOTPCommand) -> IdentityResult<ResentLoginOTPEvent>;
@ -79,6 +82,26 @@ mod tests {
use super::*; use super::*;
impl EmployeeResendLoginOTPService {
pub fn mock_service(
times: Option<usize>,
_cmd: ResendLoginOTPCommand,
) -> EmployeeResendLoginOTPServiceObj {
let res = ResentLoginOTPEvent::get_event();
let mut m = MockEmployeeResendLoginOTPUseCase::default();
if let Some(times) = times {
m.expect_resend_otp()
.times(times)
.returning(move |_| Ok(res.clone()));
} else {
m.expect_resend_otp().returning(move |_| Ok(res.clone()));
}
std::sync::Arc::new(m)
}
}
#[actix_rt::test] #[actix_rt::test]
async fn test_service_init_login() { async fn test_service_init_login() {
let s = EmployeeResendLoginOTPServiceBuilder::default() let s = EmployeeResendLoginOTPServiceBuilder::default()

View file

@ -2,6 +2,8 @@
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
use derive_builder::Builder; use derive_builder::Builder;
use mockall::predicate::*;
use mockall::*;
use super::errors::*; use super::errors::*;
use crate::identity::domain::resend_verification_otp_command::*; use crate::identity::domain::resend_verification_otp_command::*;
@ -13,6 +15,7 @@ use crate::identity::{
domain::verification_otp_resent_event::*, domain::verification_otp_resent_event::*,
}; };
#[automock]
#[async_trait::async_trait] #[async_trait::async_trait]
pub trait EmployeeResendVerificationOTPUseCase: Send + Sync { pub trait EmployeeResendVerificationOTPUseCase: Send + Sync {
async fn resend_otp( async fn resend_otp(
@ -74,10 +77,34 @@ impl EmployeeResendVerificationOTPUseCase for EmployeeResendVerificationOTPServi
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{identity::domain::employee_aggregate::*, tests::bdd::*, utils::uuid::tests::*}; use crate::{
identity::{application::services::ResendLoginOTPCommand, domain::employee_aggregate::*},
tests::bdd::*,
utils::uuid::tests::*,
};
use super::*; use super::*;
impl EmployeeResendVerificationOTPService {
pub fn mock_service(
times: Option<usize>,
_cmd: ResendVerificationOTPCommand,
) -> EmployeeResendVerificationOTPServiceObj {
let res = VerificationOTPResentEvent::get_event();
let mut m = MockEmployeeResendVerificationOTPUseCase::default();
if let Some(times) = times {
m.expect_resend_otp()
.times(times)
.returning(move |_| Ok(res.clone()));
} else {
m.expect_resend_otp().returning(move |_| Ok(res.clone()));
}
std::sync::Arc::new(m)
}
}
#[actix_rt::test] #[actix_rt::test]
async fn test_service_init_login() { async fn test_service_init_login() {
let s = EmployeeResendVerificationOTPServiceBuilder::default() let s = EmployeeResendVerificationOTPServiceBuilder::default()

View file

@ -2,6 +2,8 @@
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
use derive_builder::Builder; use derive_builder::Builder;
use mockall::predicate::*;
use mockall::*;
use crate::identity::application::port::output::db::{ use crate::identity::application::port::output::db::{
delete_verification_otp::*, get_emp_id_from_phone_number::*, get_verification_otp::*, delete_verification_otp::*, get_emp_id_from_phone_number::*, get_verification_otp::*,
@ -10,6 +12,7 @@ use crate::identity::domain::{phone_number_verified_event::*, verify_phone_numbe
use super::errors::*; use super::errors::*;
#[automock]
#[async_trait::async_trait] #[async_trait::async_trait]
pub trait EmployeeVerifyPhoneNumberUseCase: Send + Sync { pub trait EmployeeVerifyPhoneNumberUseCase: Send + Sync {
async fn verify_phone_number( async fn verify_phone_number(
@ -67,6 +70,27 @@ mod tests {
use super::*; use super::*;
impl EmployeeVerifyPhoneNumberService {
pub fn mock_service(
times: Option<usize>,
_cmd: VerifyPhoneNumberCommand,
) -> EmployeeVerifyPhoneNumberServiceObj {
let res = PhoneNumberVerifiedEvent::get_event();
let mut m = MockEmployeeVerifyPhoneNumberUseCase::default();
if let Some(times) = times {
m.expect_verify_phone_number()
.times(times)
.returning(move |_| Ok(res.clone()));
} else {
m.expect_verify_phone_number()
.returning(move |_| Ok(res.clone()));
}
std::sync::Arc::new(m)
}
}
#[actix_rt::test] #[actix_rt::test]
async fn test_service_verify_phone_number() { async fn test_service_verify_phone_number() {
let s = EmployeeVerifyPhoneNumberServiceBuilder::default() let s = EmployeeVerifyPhoneNumberServiceBuilder::default()

View file

@ -16,3 +16,19 @@ pub struct AcceptInviteCommand {
emp_id: Uuid, emp_id: Uuid,
invite_id: Uuid, invite_id: Uuid,
} }
#[cfg(test)]
mod tests {
use crate::utils::uuid::tests::UUID;
use super::*;
impl AcceptInviteCommand {
pub fn get_cmd() -> Self {
Self {
emp_id: UUID,
invite_id: UUID,
}
}
}
}

View file

@ -171,10 +171,28 @@ mod tests {
use std::sync::Arc; use std::sync::Arc;
use cqrs_es::test::TestFramework; use cqrs_es::test::TestFramework;
use employee_accept_invite_service::EmployeeAcceptInviteService;
use employee_exit_organization_service::EmployeeExitOrganizationService;
use employee_login_service::EmployeeLoginService; use employee_login_service::EmployeeLoginService;
use employee_resend_login_otp_service::EmployeeResendLoginOTPService;
use employee_resend_verification_otp_service::EmployeeResendVerificationOTPService;
use employee_verify_phone_number_service::EmployeeVerifyPhoneNumberService;
use crate::identity::domain::{ use crate::identity::domain::{
employee_logged_in_event::{EmployeeInitLoggedInEvent, EmployeeLoggedInEvent}, employee_login_command::{EmployeeFinishLoginCommand, EmployeeInitLoginCommand}, employee_register_command::EmployeeRegisterCommand, employee_registered_event::EmployeeRegisteredEvent accept_invite_command::AcceptInviteCommand,
employee_logged_in_event::{EmployeeInitLoggedInEvent, EmployeeLoggedInEvent},
employee_login_command::{EmployeeFinishLoginCommand, EmployeeInitLoginCommand},
employee_register_command::EmployeeRegisterCommand,
employee_registered_event::EmployeeRegisteredEvent,
exit_organization_command::ExitOrganizationCommand,
invite_accepted_event::InviteAcceptedEvent,
organization_exited_event::OrganizationExitedEvent,
phone_number_verified_event::PhoneNumberVerifiedEvent,
resend_login_otp_command::ResendLoginOTPCommand,
resend_login_otp_event::ResentLoginOTPEvent,
resend_verification_otp_command::ResendVerificationOTPCommand,
verification_otp_resent_event::VerificationOTPResentEvent,
verify_phone_number_command::VerifyPhoneNumberCommand,
}; };
use employee_register_service::EmployeeRegisterUserService; use employee_register_service::EmployeeRegisterUserService;
@ -204,48 +222,150 @@ mod tests {
.then_expect_events(vec![expected]); .then_expect_events(vec![expected]);
} }
// #[test]
// #[test] fn test_init_login() {
// fn test_init_login() { let cmd = EmployeeInitLoginCommand::get_cmd();
// let cmd = EmployeeInitLoginCommand::get_cmd(); let expected = EmployeeInitLoggedInEvent::get_event();
// let expected = EmployeeInitLoggedInEvent::get_event(); let expected = IdentityEvent::EmployeeInitLoggedIn(expected);
// let expected = IdentityEvent::EmployeeInitLoggedIn(expected);
// let mut services = MockIdentityServicesInterface::new();
// let mut services = MockIdentityServicesInterface::new(); services
// services .expect_employee_login_service()
// .expect_employee_login_service() .times(IS_CALLED_ONLY_ONCE.unwrap())
// .times(IS_CALLED_ONLY_ONCE.unwrap()) .return_const(EmployeeLoginService::mock_init_login(
// .return_const(EmployeeLoginService::mock_init_login( IS_CALLED_ONLY_ONCE,
// IS_CALLED_ONLY_ONCE, cmd.clone(),
// cmd.clone(), ));
// ));
// EmployeeTestFramework::with(Arc::new(services))
// EmployeeTestFramework::with(Arc::new(services)) .given_no_previous_events()
// .given_no_previous_events() .when(IdentityCommand::EmployeeInitLogin(cmd))
// .when(IdentityCommand::EmployeeInitLogin(cmd)) .then_expect_events(vec![expected]);
// .then_expect_events(vec![expected]); }
// }
// #[test]
// fn test_finish_login() {
// let cmd = EmployeeFinishLoginCommand::get_cmd();
// #[test] let expected = EmployeeLoggedInEvent::get_event();
// fn test_finish_login() { let expected = IdentityEvent::EmployeeLoggedIn(expected);
// let cmd = EmployeeFinishLoginCommand::get_cmd();
// let expected = EmployeeLoggedInEvent::get_event(); let mut services = MockIdentityServicesInterface::new();
// let expected = IdentityEvent::EmployeeLoggedIn(expected); services
// .expect_employee_login_service()
// let mut services = MockIdentityServicesInterface::new(); .times(IS_CALLED_ONLY_ONCE.unwrap())
// services .return_const(EmployeeLoginService::mock_finish_login(
// .expect_employee_login_service() IS_CALLED_ONLY_ONCE,
// .times(IS_CALLED_ONLY_ONCE.unwrap()) cmd.clone(),
// .return_const(EmployeeLoginService::mock_finish_login( ));
// IS_CALLED_ONLY_ONCE,
// cmd.clone(), EmployeeTestFramework::with(Arc::new(services))
// )); .given_no_previous_events()
// .when(IdentityCommand::EmployeeFinishLogin(cmd))
// EmployeeTestFramework::with(Arc::new(services)) .then_expect_events(vec![expected]);
// .given_no_previous_events() }
// .when(IdentityCommand::EmployeeFinishLogin(cmd))
// .then_expect_events(vec![expected]); #[test]
// } fn test_resend_login_otp() {
let cmd = ResendLoginOTPCommand::get_cmd();
let expected = ResentLoginOTPEvent::get_event();
let expected = IdentityEvent::ResentLoginOTP(expected);
let mut services = MockIdentityServicesInterface::new();
services
.expect_employee_resend_login_otp_service()
.times(IS_CALLED_ONLY_ONCE.unwrap())
.return_const(EmployeeResendLoginOTPService::mock_service(
IS_CALLED_ONLY_ONCE,
cmd.clone(),
));
EmployeeTestFramework::with(Arc::new(services))
.given_no_previous_events()
.when(IdentityCommand::EmployeeResendLoginOTP(cmd))
.then_expect_events(vec![expected]);
}
#[test]
fn test_verify_phone_number() {
let cmd = VerifyPhoneNumberCommand::get_cmd();
let expected = PhoneNumberVerifiedEvent::get_event();
let expected = IdentityEvent::PhoneNumberVerified(expected);
let mut services = MockIdentityServicesInterface::new();
services
.expect_employee_verify_phone_number_service()
.times(IS_CALLED_ONLY_ONCE.unwrap())
.return_const(EmployeeVerifyPhoneNumberService::mock_service(
IS_CALLED_ONLY_ONCE,
cmd.clone(),
));
EmployeeTestFramework::with(Arc::new(services))
.given_no_previous_events()
.when(IdentityCommand::EmployeeVerifyPhoneNumber(cmd))
.then_expect_events(vec![expected]);
}
#[test]
fn test_resend_verification_otp() {
let cmd = ResendVerificationOTPCommand::get_cmd();
let expected = VerificationOTPResentEvent::get_event();
let expected = IdentityEvent::VerificationOTPResent(expected);
let mut services = MockIdentityServicesInterface::new();
services
.expect_employee_resend_verification_otp_service()
.times(IS_CALLED_ONLY_ONCE.unwrap())
.return_const(EmployeeResendVerificationOTPService::mock_service(
IS_CALLED_ONLY_ONCE,
cmd.clone(),
));
EmployeeTestFramework::with(Arc::new(services))
.given_no_previous_events()
.when(IdentityCommand::EmployeeResendVerificationOTP(cmd))
.then_expect_events(vec![expected]);
}
#[test]
fn test_accept_invite() {
let cmd = AcceptInviteCommand::get_cmd();
let expected = InviteAcceptedEvent::get_event(&cmd);
let expected = IdentityEvent::InviteAccepted(expected);
let mut services = MockIdentityServicesInterface::new();
services
.expect_employee_accept_invite_service()
.times(IS_CALLED_ONLY_ONCE.unwrap())
.return_const(EmployeeAcceptInviteService::mock_service(
IS_CALLED_ONLY_ONCE,
cmd.clone(),
));
EmployeeTestFramework::with(Arc::new(services))
.given_no_previous_events()
.when(IdentityCommand::EmployeeAcceptInvite(cmd))
.then_expect_events(vec![expected]);
}
#[test]
fn test_exit_organization() {
let cmd = ExitOrganizationCommand::get_cmd();
let expected = OrganizationExitedEvent::get_event(&cmd);
let expected = IdentityEvent::OrganizationExited(expected);
let mut services = MockIdentityServicesInterface::new();
services
.expect_employee_exit_organization_service()
.times(IS_CALLED_ONLY_ONCE.unwrap())
.return_const(EmployeeExitOrganizationService::mock_service(
IS_CALLED_ONLY_ONCE,
cmd.clone(),
));
EmployeeTestFramework::with(Arc::new(services))
.given_no_previous_events()
.when(IdentityCommand::EmployeeExitOrganization(cmd))
.then_expect_events(vec![expected]);
}
} }

View file

@ -29,23 +29,19 @@ mod tests {
use super::*; use super::*;
impl EmployeeInitLoginCommand { impl EmployeeInitLoginCommand {
pub fn get_cmd() -> Self {
Self {
phone_number: PhoneNumber::default()
}
}
}
impl EmployeeFinishLoginCommand {
pub fn get_cmd() -> Self { pub fn get_cmd() -> Self {
Self { Self {
phone_number: PhoneNumber::default(), phone_number: PhoneNumber::default(),
otp: 999,
} }
}
}
impl EmployeeFinishLoginCommand {
pub fn get_cmd() -> Self {
Self {
phone_number: PhoneNumber::default(),
otp: 999,
}
} }
} }
} }

View file

@ -16,3 +16,19 @@ pub struct ExitOrganizationCommand {
emp_id: Uuid, emp_id: Uuid,
store_id: Uuid, store_id: Uuid,
} }
#[cfg(test)]
mod tests {
use crate::utils::uuid::tests::UUID;
use super::*;
impl ExitOrganizationCommand {
pub fn get_cmd() -> Self {
Self {
emp_id: UUID,
store_id: UUID,
}
}
}
}

View file

@ -17,3 +17,21 @@ pub struct InviteAcceptedEvent {
invite_id: Uuid, invite_id: Uuid,
store_id: Uuid, store_id: Uuid,
} }
#[cfg(test)]
mod tests {
use super::*;
use crate::{
identity::domain::accept_invite_command::AcceptInviteCommand, utils::uuid::tests::UUID,
};
impl InviteAcceptedEvent {
pub fn get_event(cmd: &AcceptInviteCommand) -> Self {
Self {
emp_id: *cmd.emp_id(),
invite_id: *cmd.invite_id(),
store_id: UUID,
}
}
}
}

View file

@ -16,3 +16,19 @@ pub struct OrganizationExitedEvent {
emp_id: Uuid, emp_id: Uuid,
store_id: Uuid, store_id: Uuid,
} }
#[cfg(test)]
mod tests {
use crate::identity::domain::exit_organization_command::ExitOrganizationCommand;
use super::*;
impl OrganizationExitedEvent {
pub fn get_event(cmd: &ExitOrganizationCommand) -> Self {
Self {
emp_id: *cmd.emp_id(),
store_id: *cmd.store_id(),
}
}
}
}

View file

@ -15,3 +15,16 @@ use super::employee_aggregate::*;
pub struct PhoneNumberVerifiedEvent { pub struct PhoneNumberVerifiedEvent {
emp_id: Uuid, emp_id: Uuid,
} }
#[cfg(test)]
mod tests {
use crate::utils::uuid::tests::UUID;
use super::*;
impl PhoneNumberVerifiedEvent {
pub fn get_event() -> Self {
Self { emp_id: UUID }
}
}
}

View file

@ -15,3 +15,16 @@ use super::employee_aggregate::*;
pub struct ResendLoginOTPCommand { pub struct ResendLoginOTPCommand {
phone_number: PhoneNumber, phone_number: PhoneNumber,
} }
#[cfg(test)]
mod tests {
use super::*;
impl ResendLoginOTPCommand {
pub fn get_cmd() -> Self {
Self {
phone_number: Default::default(),
}
}
}
}

View file

@ -15,3 +15,16 @@ use super::employee_aggregate::*;
pub struct ResentLoginOTPEvent { pub struct ResentLoginOTPEvent {
emp_id: Uuid, emp_id: Uuid,
} }
#[cfg(test)]
mod tests {
use crate::utils::uuid::tests::UUID;
use super::*;
impl ResentLoginOTPEvent {
pub fn get_event() -> Self {
Self { emp_id: UUID }
}
}
}

View file

@ -15,3 +15,16 @@ use super::employee_aggregate::*;
pub struct ResendVerificationOTPCommand { pub struct ResendVerificationOTPCommand {
phone_number: PhoneNumber, phone_number: PhoneNumber,
} }
#[cfg(test)]
mod tests {
use super::*;
impl ResendVerificationOTPCommand {
pub fn get_cmd() -> Self {
Self {
phone_number: Default::default(),
}
}
}
}

View file

@ -14,3 +14,16 @@ use super::employee_aggregate::*;
pub struct VerificationOTPResentEvent { pub struct VerificationOTPResentEvent {
emp_id: Uuid, emp_id: Uuid,
} }
#[cfg(test)]
mod tests {
use crate::utils::uuid::tests::UUID;
use super::*;
impl VerificationOTPResentEvent {
pub fn get_event() -> Self {
Self { emp_id: UUID }
}
}
}

View file

@ -16,3 +16,17 @@ pub struct VerifyPhoneNumberCommand {
phone_number: PhoneNumber, phone_number: PhoneNumber,
otp: usize, otp: usize,
} }
#[cfg(test)]
mod tests {
use super::*;
impl VerifyPhoneNumberCommand {
pub fn get_cmd() -> Self {
Self {
phone_number: Default::default(),
otp: 999,
}
}
}
}