mod common;
use std::sync::Arc;
use std::time::Duration;
use async_trait::async_trait;
use chorus::errors::GatewayError;
use chorus::gateway::*;
use chorus::types::{
self, Channel, ChannelCreateSchema, ChannelModifySchema, IntoShared, RoleCreateModifySchema,
RoleObject,
};
use pubserve::Subscriber;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::*;
#[cfg(target_arch = "wasm32")]
wasm_bindgen_test_configure!(run_in_browser);
#[cfg(not(target_arch = "wasm32"))]
use tokio::time::sleep;
#[cfg(target_arch = "wasm32")]
use wasmtimer::tokio::sleep;
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
async fn test_gateway_establish() {
let bundle = common::setup().await;
let _: GatewayHandle = Gateway::spawn(&bundle.urls.wss, GatewayOptions::default())
.await
.unwrap();
common::teardown(bundle).await
}
#[derive(Debug)]
struct GatewayErrorObserver {
channel: tokio::sync::mpsc::Sender<GatewayError>,
}
#[async_trait]
impl Subscriber<GatewayError> for GatewayErrorObserver {
async fn update(&self, data: &GatewayError) {
self.channel.send(data.clone()).await.unwrap();
}
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
async fn test_gateway_authenticate() {
let bundle = common::setup().await;
let gateway: GatewayHandle = Gateway::spawn(&bundle.urls.wss, GatewayOptions::default())
.await
.unwrap();
let mut identify = types::GatewayIdentifyPayload::common();
identify.token = bundle.user.token.clone();
match gateway.identify(identify).await {
Ok(_) => {}
Err(e) => {
println!("Failed to identify with error {}, failing", e);
assert!(false);
}
}
common::teardown(bundle).await
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
async fn test_gateway_errors() {
let bundle = common::setup().await;
bundle.user.gateway.close().await;
let gateway: GatewayHandle = Gateway::spawn(&bundle.urls.wss, GatewayOptions::default())
.await
.unwrap();
let (error_send, mut error_receive) = tokio::sync::mpsc::channel(1);
let observer = Arc::new(GatewayErrorObserver {
channel: error_send,
});
gateway.events.lock().await.error.subscribe(observer);
let mut identify = types::GatewayIdentifyPayload::common();
identify.token = bundle.user.token.clone();
match gateway.identify(identify.clone()).await {
Ok(_) => {}
Err(e) => {
println!("Failed to identify with error {}, failing", e);
assert!(false);
}
}
gateway.send_identify(identify).await;
tokio::select! {
() = sleep(Duration::from_secs(20)) => {
assert!(false);
}
Some(error) = error_receive.recv() => {
assert_eq!(error, GatewayError::AlreadyAuthenticated);
}
}
common::teardown(bundle).await;
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
async fn test_self_updating_structs() {
let mut bundle = common::setup().await;
let received_channel = bundle
.user
.gateway
.observe_and_into_inner(bundle.channel.clone())
.await;
assert_eq!(received_channel, bundle.channel.read().unwrap().clone());
let modify_schema = ChannelModifySchema {
name: Some("selfupdating".to_string()),
..Default::default()
};
received_channel
.modify(modify_schema, None, &mut bundle.user)
.await
.unwrap();
assert_eq!(
bundle
.user
.gateway
.observe_and_into_inner(bundle.channel.clone())
.await
.name
.unwrap(),
"selfupdating".to_string()
);
let guild = bundle
.user
.gateway
.observe_and_into_inner(bundle.guild.clone())
.await;
assert!(guild.channels.is_empty());
Channel::create(
&mut bundle.user,
guild.id,
None,
ChannelCreateSchema {
name: "selfupdating2".to_string(),
channel_type: Some(types::ChannelType::GuildText),
..Default::default()
},
)
.await
.unwrap();
let guild = bundle
.user
.gateway
.observe_and_into_inner(guild.into_shared())
.await;
assert!(!guild.channels.is_empty());
assert_eq!(guild.channels.len(), 1);
common::teardown(bundle).await
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
async fn test_recursive_self_updating_structs() {
let mut bundle = common::setup().await;
let guild = bundle.guild.clone();
let guild = bundle.user.gateway.observe(guild.clone()).await;
let inner_guild = guild.read().unwrap().clone();
assert!(inner_guild.roles.is_empty());
let permissions = types::PermissionFlags::CONNECT | types::PermissionFlags::MANAGE_EVENTS;
let mut role_create_schema: types::RoleCreateModifySchema = RoleCreateModifySchema {
name: Some("cool person".to_string()),
permissions: Some(permissions),
hoist: Some(true),
icon: None,
unicode_emoji: Some("".to_string()),
mentionable: Some(true),
position: None,
color: None,
};
let guild_id = inner_guild.id;
let role = RoleObject::create(&mut bundle.user, guild_id, role_create_schema.clone())
.await
.unwrap();
bundle
.user
.gateway
.observe(role.clone().into_shared())
.await;
let inner_guild = guild.read().unwrap().clone();
assert!(!inner_guild.roles.is_empty());
role_create_schema.name = Some("yippieee".to_string());
RoleObject::modify(&mut bundle.user, guild_id, role.id, role_create_schema)
.await
.unwrap();
let role_inner = bundle
.user
.gateway
.observe_and_into_inner(role.clone().into_shared())
.await;
assert_eq!(role_inner.name, "yippieee");
let guild = bundle.user.gateway.observe(bundle.guild.clone()).await;
let inner_guild = guild.read().unwrap().clone();
let guild_roles = inner_guild.roles;
let guild_role_inner = guild_roles.first().unwrap().read().unwrap().clone();
assert_eq!(guild_role_inner.name, "yippieee".to_string());
common::teardown(bundle).await;
}