application: channels bounded context

CQRS use cases (create/update/delete/get/list/list_by_owner),
ownership checks, auto-snapshot on config change.
Channel setters added to domain model.
This commit is contained in:
2026-07-12 01:57:38 +02:00
parent 2976600d12
commit 6fd47f2d93
18 changed files with 909 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
use std::sync::Arc;
use domain::testing::{InMemoryChannelRepository, NoopEventPublisher};
use domain::value_objects::UserId;
use crate::channels::commands::CreateChannelCommand;
use crate::channels::create;
use crate::channels::deps::ChannelCommandDeps;
fn make_deps() -> (ChannelCommandDeps, Arc<InMemoryChannelRepository>) {
let repo = Arc::new(InMemoryChannelRepository::new());
let deps = ChannelCommandDeps {
channel_command: repo.clone(),
channel_query: repo.clone(),
event_publisher: Arc::new(NoopEventPublisher::new()),
};
(deps, repo)
}
#[tokio::test]
async fn creates_channel_successfully() {
let (deps, repo) = make_deps();
let owner = UserId::generate();
let channel = create::execute(
&deps,
CreateChannelCommand {
owner_id: owner.value(),
name: "Movie Night".into(),
timezone: "America/New_York".into(),
},
)
.await
.unwrap();
assert_eq!(channel.name(), "Movie Night");
assert_eq!(channel.timezone(), "America/New_York");
assert_eq!(channel.owner_id(), owner);
// Verify persisted
let stored = repo.channels.lock().unwrap();
assert_eq!(stored.len(), 1);
let persisted = stored.values().next().unwrap();
assert_eq!(persisted.id(), channel.id());
}
#[tokio::test]
async fn create_returns_default_config() {
let (deps, _) = make_deps();
let channel = create::execute(
&deps,
CreateChannelCommand {
owner_id: UserId::generate().value(),
name: "Defaults".into(),
timezone: "UTC".into(),
},
)
.await
.unwrap();
assert!(channel.description().is_none());
assert!(!channel.auto_schedule());
assert!(channel.schedule_config().day_blocks().is_empty());
}