From 87a9fb79f2ac7f1aefde48bb17a4e923e621de8b Mon Sep 17 00:00:00 2001 From: Zomatree Date: Sun, 21 Jul 2024 22:22:46 +0100 Subject: [PATCH] chore: Write tests for pinning --- .../src/models/server_members/model.rs | 4 +- crates/core/database/src/util/idempotency.rs | 4 + .../delta/src/routes/channels/message_pin.rs | 81 +++++++++++++++ .../src/routes/channels/message_unpin.rs | 98 ++++++++++++++++++- .../delta/src/routes/invites/invite_join.rs | 3 +- .../delta/src/routes/servers/server_create.rs | 2 +- 6 files changed, 186 insertions(+), 6 deletions(-) diff --git a/crates/core/database/src/models/server_members/model.rs b/crates/core/database/src/models/server_members/model.rs index 0ca09ed4..88f953cf 100644 --- a/crates/core/database/src/models/server_members/model.rs +++ b/crates/core/database/src/models/server_members/model.rs @@ -81,7 +81,7 @@ impl Member { server: &Server, user: &User, channels: Option>, - ) -> Result> { + ) -> Result<(Member, Vec)> { if db.fetch_ban(&server.id, &user.id).await.is_ok() { return Err(create_error!(Banned)); } @@ -155,7 +155,7 @@ impl Member { .ok(); } - Ok(channels) + Ok((member, channels)) } /// Update member data diff --git a/crates/core/database/src/util/idempotency.rs b/crates/core/database/src/util/idempotency.rs index 94448c04..d95236d7 100644 --- a/crates/core/database/src/util/idempotency.rs +++ b/crates/core/database/src/util/idempotency.rs @@ -18,6 +18,10 @@ static TOKEN_CACHE: Lazy>> = Lazy::new(|| Mutex::new(lru::LruCache::new(NonZeroUsize::new(1000).unwrap()))); impl IdempotencyKey { + pub fn unchecked_from_string(key: String) -> Self { + Self { key } + } + // Backwards compatibility. // Issue #109 pub async fn consume_nonce(&mut self, v: Option) -> Result<()> { diff --git a/crates/delta/src/routes/channels/message_pin.rs b/crates/delta/src/routes/channels/message_pin.rs index 80dc19fe..3a5e347d 100644 --- a/crates/delta/src/routes/channels/message_pin.rs +++ b/crates/delta/src/routes/channels/message_pin.rs @@ -37,3 +37,84 @@ pub async fn message_pin( Ok(EmptyResponse) } + +#[cfg(test)] +mod test { + use crate::{rocket, util::test::TestHarness}; + use revolt_database::{events::client::EventV1, util::{idempotency::IdempotencyKey, reference::Reference}, Member, Message, Server}; + use revolt_models::v0; + use rocket::http::{Header, Status}; + + #[rocket::async_test] + async fn pin_message() { + let mut harness = TestHarness::new().await; + let (_, session, user) = harness.new_user().await; + + let (server, channels) = Server::create( + &harness.db, + v0::DataCreateServer { + name: "Test Server".to_string(), + ..Default::default() + }, + &user, + true + ).await.expect("Failed to create test server"); + + let (member, channels) = Member::create(&harness.db, &server, &user, Some(channels)).await.expect("Failed to create member"); + let channel = &channels[0]; + + let message = Message::create_from_api( + &harness.db, + channel.clone(), + v0::DataMessageSend { + content:Some("Test message".to_string()), + nonce: None, + attachments: None, + replies: None, + embeds: None, + masquerade: None, + interactions: None, + flags: None + }, + v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await), + Some(user.clone().into(&harness.db, Some(&user)).await), + Some(member.into()), + user.limits().await, + IdempotencyKey::unchecked_from_string("0".to_string()), + false, + false + ) + .await + .expect("Failed to create message"); + + let response = harness + .client + .post(format!("/channels/{}/messages/{}/pin", channel.id(), &message.id)) + .header(Header::new("x-session-token", session.token.to_string())) + .dispatch() + .await; + + assert_eq!(response.status(), Status::NoContent); + drop(response); + + harness.wait_for_event(&channel.id(), |event| { + match event { + EventV1::MessageUpdate { id, channel: channel_id, data, .. } => { + assert_eq!(id, &message.id); + assert_eq!(channel_id, &channel.id()); + assert_eq!(data.pinned, Some(true)); + + true + }, + _ => false + } + }).await; + + let updated_message = Reference::from_unchecked(message.id) + .as_message(&harness.db) + .await + .expect("Failed to find updated message"); + + assert_eq!(updated_message.pinned, Some(true)); + } +} diff --git a/crates/delta/src/routes/channels/message_unpin.rs b/crates/delta/src/routes/channels/message_unpin.rs index 13e91971..1edf9e46 100644 --- a/crates/delta/src/routes/channels/message_unpin.rs +++ b/crates/delta/src/routes/channels/message_unpin.rs @@ -1,5 +1,5 @@ use revolt_database::{ - util::{permissions::DatabasePermissionQuery, reference::Reference}, Database, PartialMessage, User + util::{permissions::DatabasePermissionQuery, reference::Reference}, Database, FieldsMessage, PartialMessage, User }; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; @@ -10,7 +10,7 @@ use rocket_empty::EmptyResponse; /// /// Unpins a message by its id. #[openapi(tag = "Messaging")] -#[post("//messages//unpin")] +#[delete("//messages//pin")] pub async fn message_unpin( db: &State, user: User, @@ -37,3 +37,97 @@ pub async fn message_unpin( Ok(EmptyResponse) } + +#[cfg(test)] +mod test { + use crate::{rocket, util::test::TestHarness}; + use revolt_database::{events::client::EventV1, util::{idempotency::IdempotencyKey, reference::Reference}, Member, Message, PartialMessage, Server}; + use revolt_models::v0; + use rocket::http::{Header, Status}; + + #[rocket::async_test] + async fn unpin_message() { + let mut harness = TestHarness::new().await; + let (_, session, user) = harness.new_user().await; + + let (server, channels) = Server::create( + &harness.db, + v0::DataCreateServer { + name: "Test Server".to_string(), + ..Default::default() + }, + &user, + true + ).await.expect("Failed to create test server"); + + let channel = &channels[0]; + + Member::create(&harness.db, &server, &user, Some(channels.clone())).await.expect("Failed to create member"); + let member = Reference::from_unchecked(user.id.clone()).as_member(&harness.db, &server.id).await.expect("Failed to get member"); + + let mut message = Message::create_from_api( + &harness.db, + channel.clone(), + v0::DataMessageSend { + content:Some("Test message".to_string()), + nonce: None, + attachments: None, + replies: None, + embeds: None, + masquerade: None, + interactions: None, + flags: None + }, + v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await), + Some(user.clone().into(&harness.db, Some(&user)).await), + Some(member.into()), + user.limits().await, + IdempotencyKey::unchecked_from_string("0".to_string()), + false, + false + ) + .await + .expect("Failed to create message"); + + harness.db.update_message( + &message.id, + &PartialMessage { + pinned: Some(true), + ..Default::default() + }, + vec![] + ).await.expect("Failed to update message"); + + let response = harness + .client + .delete(format!("/channels/{}/messages/{}/pin", channel.id(), &message.id)) + .header(Header::new("x-session-token", session.token.to_string())) + .dispatch() + .await; + + assert_eq!(response.status(), Status::NoContent); + drop(response); + + harness.wait_for_event(&channel.id(), |event| { + match event { + EventV1::MessageUpdate { id, data, .. } => { + if id != &message.id { + return false + }; + + assert_eq!(data.pinned, Some(false)); + + true + }, + _ => false + } + }).await; + + let updated_message = Reference::from_unchecked(message.id) + .as_message(&harness.db) + .await + .expect("Failed to find updated message"); + + assert_eq!(updated_message.pinned, None); + } +} diff --git a/crates/delta/src/routes/invites/invite_join.rs b/crates/delta/src/routes/invites/invite_join.rs index bfcb307b..2fa872d3 100644 --- a/crates/delta/src/routes/invites/invite_join.rs +++ b/crates/delta/src/routes/invites/invite_join.rs @@ -23,7 +23,8 @@ pub async fn join( match &invite { Invite::Server { server, .. } => { let server = db.fetch_server(server).await?; - let channels = Member::create(db, &server, &user, None).await?; + let (_, channels) = Member::create(db, &server, &user, None).await?; + Ok(Json(InviteJoinResponse::Server { channels: channels.into_iter().map(|c| c.into()).collect(), server: server.into(), diff --git a/crates/delta/src/routes/servers/server_create.rs b/crates/delta/src/routes/servers/server_create.rs index 8e682c4c..82f0a8aa 100644 --- a/crates/delta/src/routes/servers/server_create.rs +++ b/crates/delta/src/routes/servers/server_create.rs @@ -30,7 +30,7 @@ pub async fn create_server( user.can_acquire_server(db).await?; let (server, channels) = Server::create(db, data, &user, true).await?; - let channels = Member::create(db, &server, &user, Some(channels)).await?; + let (_, channels) = Member::create(db, &server, &user, Some(channels)).await?; Ok(Json(v0::CreateServerLegacyResponse { server: server.into(),