From 74e32a725da8067b6daca88451023c0cab5c1961 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 6 Feb 2023 12:17:55 +0400 Subject: [PATCH] Add tests for response processing --- crates/teloxide-core/src/errors.rs | 1 + crates/teloxide-core/src/net/request.rs | 120 ++++++++++++++++++++++++ 2 files changed, 121 insertions(+) diff --git a/crates/teloxide-core/src/errors.rs b/crates/teloxide-core/src/errors.rs index 41acffdf..45be0f70 100644 --- a/crates/teloxide-core/src/errors.rs +++ b/crates/teloxide-core/src/errors.rs @@ -17,6 +17,7 @@ pub enum RequestError { /// The group has been migrated to a supergroup with the specified /// identifier. #[error("The group has been migrated to a supergroup with ID #{0}")] + // FIXME: change to `ChatId` :| MigrateToChatId(i64), /// In case of exceeding flood control, the number of seconds left to wait diff --git a/crates/teloxide-core/src/net/request.rs b/crates/teloxide-core/src/net/request.rs index 6c0580fe..b990e588 100644 --- a/crates/teloxide-core/src/net/request.rs +++ b/crates/teloxide-core/src/net/request.rs @@ -99,6 +99,13 @@ where let text = response.text().await?; + deserialize_response(text) +} + +fn deserialize_response(text: String) -> Result +where + T: DeserializeOwned + 'static, +{ serde_json::from_str::>(&text) .map(|mut response| { use crate::types::{Update, UpdateKind}; @@ -152,3 +159,116 @@ where .map_err(|source| RequestError::InvalidJson { source, raw: text.into() })? .into() } + +#[cfg(test)] +mod tests { + use std::time::Duration; + + use cool_asserts::assert_matches; + + use crate::{ + net::request::deserialize_response, + types::{True, Update, UpdateKind}, + ApiError, RequestError, + }; + + #[test] + fn smoke_ok() { + let json = r#"{"ok":true,"result":true}"#.to_owned(); + + let res = deserialize_response::(json); + assert_matches!(res, Ok(True)); + } + + #[test] + fn smoke_err() { + let json = + r#"{"ok":false,"description":"Forbidden: bot was blocked by the user"}"#.to_owned(); + + let res = deserialize_response::(json); + assert_matches!(res, Err(RequestError::Api(ApiError::BotBlocked))); + } + + #[test] + fn migrate() { + let json = r#"{"ok":false,"description":"this string is ignored","parameters":{"migrate_to_chat_id":123456}}"#.to_owned(); + + let res = deserialize_response::(json); + assert_matches!(res, Err(RequestError::MigrateToChatId(123456))); + } + + #[test] + fn retry_after() { + let json = r#"{"ok":false,"description":"this string is ignored","parameters":{"retry_after":123456}}"#.to_owned(); + + let res = deserialize_response::(json); + assert_matches!(res, Err(RequestError::RetryAfter(duration)) if duration == Duration::from_secs(123456)); + } + + #[test] + fn update_ok() { + let json = r#"{ + "ok":true, + "result":[ + { + "update_id":0, + "poll_answer":{ + "poll_id":"POLL_ID", + "user": {"id":42,"is_bot":false,"first_name":"blah"}, + "option_ids": [] + } + } + ] + }"# + .to_owned(); + + let res = deserialize_response::>(json).unwrap(); + assert_matches!(res, [Update { id: 0, kind: UpdateKind::PollAnswer(_) }]); + } + + /// Check that `get_updates` can work with malformed updates. + #[test] + fn update_err() { + let json = r#"{ + "ok":true, + "result":[ + { + "update_id":0, + "poll_answer":{ + "poll_id":"POLL_ID", + "user": {"id":42,"is_bot":false,"first_name":"blah"}, + "option_ids": [] + } + }, + { + "update_id":1, + "something unknown to us":17 + }, + { + "update_id":2, + "poll_answer":{ + "poll_id":"POLL_ID", + "user": {"id":42,"is_bot":false,"first_name":"blah"}, + "option_ids": [3, 4, 8] + } + }, + { + "update_id":3, + "message":{"some fields are missing":true} + } + ] + }"# + .to_owned(); + + let res = deserialize_response::>(json).unwrap(); + assert_matches!( + res, + [ + Update { id: 0, kind: UpdateKind::PollAnswer(_) }, + Update { id: 1, kind: UpdateKind::Error(v) } if v.is_object(), + Update { id: 2, kind: UpdateKind::PollAnswer(_) }, + Update { id: 3, kind: UpdateKind::Error(v) } if v.is_object(), + ] + ); + } +}