use std::future; use axum::extract::{Json, State}; use futures::stream::StreamExt as _; use super::post; use crate::{ channel::app, test::fixtures::{self, future::Immediately as _}, }; #[tokio::test] async fn new_channel() { // Set up the environment let app = fixtures::scratch_app().await; let creator = fixtures::identity::create(&app, &fixtures::now()).await; // Call the endpoint let name = fixtures::channel::propose(); let request = post::Request { name: name.clone() }; let post::Response(response) = post::handler(State(app.clone()), creator, fixtures::now(), Json(request)) .await .expect("creating a channel in an empty app succeeds"); // Verify the structure of the response assert_eq!(name, response.name); // Verify the semantics let snapshot = app.boot().snapshot().await.expect("boot always succeeds"); assert!(snapshot.channels.iter().any(|channel| channel == &response)); let channel = app .channels() .get(&response.id) .await .expect("searching for channels by ID never fails") .expect("the newly-created channel exists"); assert_eq!(response, channel); let mut events = app .events() .subscribe(None) .await .expect("subscribing never fails") .filter_map(fixtures::channel::events) .filter_map(fixtures::channel::created) .filter(|event| future::ready(event.channel == response)); let event = events .next() .immediately() .await .expect("creation event published"); assert_eq!(event.channel, response); } #[tokio::test] async fn duplicate_name() { // Set up the environment let app = fixtures::scratch_app().await; let creator = fixtures::identity::create(&app, &fixtures::now()).await; let channel = fixtures::channel::create(&app, &fixtures::now()).await; // Call the endpoint let request = post::Request { name: channel.name.clone(), }; let post::Error(error) = post::handler(State(app.clone()), creator, fixtures::now(), Json(request)) .await .expect_err("duplicate channel name should fail the request"); // Verify the structure of the response assert!(matches!( error, app::CreateError::DuplicateName(name) if channel.name == name )); } #[tokio::test] async fn name_reusable_after_delete() { // Set up the environment let app = fixtures::scratch_app().await; let creator = fixtures::identity::create(&app, &fixtures::now()).await; let name = fixtures::channel::propose(); // Call the endpoint (first time) let request = post::Request { name: name.clone() }; let post::Response(response) = post::handler( State(app.clone()), creator.clone(), fixtures::now(), Json(request), ) .await .expect("new channel in an empty app"); // Delete the channel app.channels() .delete(&response.id, &fixtures::now()) .await .expect("deleting a newly-created channel succeeds"); // Call the endpoint (second time) let request = post::Request { name: name.clone() }; let post::Response(response) = post::handler(State(app.clone()), creator, fixtures::now(), Json(request)) .await .expect("new channel in an empty app"); // Verify the structure of the response assert_eq!(name, response.name); // Verify the semantics let snapshot = app.boot().snapshot().await.expect("boot always succeeds"); assert!(snapshot.channels.iter().any(|channel| channel == &response)); let channel = app .channels() .get(&response.id) .await .expect("searching for channels by ID never fails") .expect("the newly-created channel exists"); assert_eq!(response, channel); let mut events = app .events() .subscribe(None) .await .expect("subscribing never fails") .filter_map(fixtures::channel::events) .filter_map(fixtures::channel::created) .filter(|event| future::ready(event.channel == response)); let event = events .next() .immediately() .await .expect("creation event published"); assert_eq!(event.channel, response); }