Skip to content

Commit

Permalink
Extend e2e_bot_test to cover update_bot
Browse files Browse the repository at this point in the history
  • Loading branch information
megrogan committed Dec 18, 2024
1 parent e701d6b commit 37c86d2
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 17 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ fn prepare(args: &Args, state: &RuntimeState) -> Result<PrepareResult, Response>
return Err(OwnerNotFound);
};

if owner.user_id != bot_user.user_id {
if owner.user_id != bot.owner {
return Err(NotAuthorised);
}

Expand Down
1 change: 1 addition & 0 deletions backend/integration_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ proposals_bot_canister = { path = "../canisters/proposals_bot/api" }
rand = { workspace = true }
registry_canister = { path = "../canisters/registry/api" }
serde = { workspace = true }
serde_json = { workspace = true }
sha256 = { path = "../libraries/sha256" }
sign_in_with_email_canister = { workspace = true }
sign_in_with_email_canister_test_utils = { workspace = true }
Expand Down
98 changes: 83 additions & 15 deletions backend/integration_tests/src/bot_tests.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
use crate::client::unwrap_msgpack_response;
use crate::env::ENV;
use crate::utils::now_millis;
use crate::{client, CanisterIds, TestEnv, User};
use candid::Principal;
use pocket_ic::common::rest::{CanisterHttpReply, CanisterHttpResponse, MockCanisterHttpResponse};
use pocket_ic::PocketIc;
use std::collections::HashSet;
use std::ops::Deref;
use std::time::Duration;
use testing::rng::{random_from_u128, random_string};
use types::bot_actions::{BotMessageAction, MessageContent};
use types::{
AccessTokenType, BotAction, BotCommandArgs, Chat, ChatEvent, ChatId, MessagePermission, SlashCommandPermissions,
SlashCommandSchema, TextContent,
AccessTokenType, BotAction, BotCommandArgs, BotDefinition, Chat, ChatEvent, ChatId, MessagePermission, OptionUpdate,
SlashCommandPermissions, SlashCommandSchema, TextContent,
};

#[test]
fn bot_smoke_test() {
fn e2e_bot_test() {
let mut wrapper = ENV.deref().get();
let TestEnv {
env,
Expand All @@ -29,23 +31,27 @@ fn bot_smoke_test() {
// Register a bot
let bot_name = random_string();
let command_name = "greet".to_string();
let endpoint = "https://my.bot.xyz/".to_string();
let description = "greet".to_string();
let commands = vec![SlashCommandSchema {
name: command_name.clone(),
description: Some("Hello {user}".to_string()),
params: vec![],
permissions: SlashCommandPermissions {
community: HashSet::new(),
chat: HashSet::new(),
message: HashSet::from_iter([MessagePermission::Text]),
},
}];

let bot_principal = client::register_bot(
env,
canister_ids,
&user,
bot_name.clone(),
"greet".to_string(),
"https://my.bot.xyz/".to_string(),
vec![SlashCommandSchema {
name: command_name.clone(),
description: Some("Hello {user}".to_string()),
params: vec![],
permissions: SlashCommandPermissions {
community: HashSet::new(),
chat: HashSet::new(),
message: HashSet::from_iter([MessagePermission::Text]),
},
}],
description.clone(),
endpoint.clone(),
commands.clone(),
);

let initial_time = now_millis(env);
Expand Down Expand Up @@ -190,6 +196,68 @@ fn bot_smoke_test() {
assert!(message.edited);
assert!(message.bot_context.is_some());
assert!(message.bot_context.as_ref().unwrap().finalised);

// Update the bot name
// Internally this will also try to call the bot endpoint to load the latest bot definition.
// We need to do the following to handle this
// 1. submit the update call but not wait for the response
// 2. tick
// 3. Intercept and mock the http outcall response
// 4. wait for the update_bot call to complete
let new_bot_name = random_string();
let raw_message_id = match env.submit_call(
canister_ids.user_index,
user.principal,
"update_bot_msgpack",
msgpack::serialize_then_unwrap(&user_index_canister::update_bot::Args {
bot_id: bot.id,
owner: None,
name: Some(new_bot_name.clone()),
avatar: OptionUpdate::NoChange,
endpoint: None,
}),
) {
Ok(r) => r,
Err(error) => panic!("'update_bot' call error: {error:?}"),
};

env.tick();
env.tick();

// Intercept the http call to get the bot definition and mock the response
let outgoing_http_requests = env.get_canister_http();

assert_eq!(outgoing_http_requests.len(), 1);
let bof_definition_request = &outgoing_http_requests[0];
assert_eq!(bof_definition_request.url, endpoint);

let body = serde_json::to_string(&BotDefinition { description, commands })
.unwrap()
.into_bytes();

env.mock_canister_http_response(MockCanisterHttpResponse {
subnet_id: bof_definition_request.subnet_id,
request_id: bof_definition_request.request_id,
response: CanisterHttpResponse::CanisterHttpReply(CanisterHttpReply {
status: 200,
headers: vec![],
body,
}),
additional_responses: vec![],
});

match unwrap_msgpack_response::<user_index_canister::update_bot::Response>(env.await_call(raw_message_id)) {
user_index_canister::update_bot::Response::Success => (),
response => panic!("'update_bot' response error: {response:?}"),
}

// Confirm bot returned in `bot_updates`
let response =
client::user_index::happy_path::bot_updates(env, user.principal, canister_ids.user_index, bot_added_timestamp);
assert_eq!(response.added_or_updated.len(), 1);

let bot = &response.added_or_updated[0];
assert_eq!(bot.name, new_bot_name);
}

fn init_test_data(env: &mut PocketIc, canister_ids: &CanisterIds, controller: Principal) -> TestData {
Expand Down
2 changes: 1 addition & 1 deletion backend/integration_tests/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ fn unwrap_response<R: CandidType + DeserializeOwned>(response: Result<WasmResult
}
}

fn unwrap_msgpack_response<R: DeserializeOwned>(response: Result<WasmResult, UserError>) -> R {
pub fn unwrap_msgpack_response<R: DeserializeOwned>(response: Result<WasmResult, UserError>) -> R {
match response.unwrap() {
WasmResult::Reply(bytes) => msgpack::deserialize_then_unwrap(&bytes),
WasmResult::Reject(error) => panic!("{error}"),
Expand Down

0 comments on commit 37c86d2

Please sign in to comment.