diff --git a/Cargo.toml b/Cargo.toml index bd96dfe..2b9bd1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,14 +8,10 @@ bytes = "1.9" clap = { version = "4.5", features = ["cargo", "derive"] } color-eyre = "0.6" derive_more = { version = "1.0", features = [ - "as_ref", - "constructor", - "deref", -# "display", - # "from", - #] } - #serde = { version = "1.0", features = ["derive"] } - "from", + "as_ref", + "constructor", + "deref", + "from", ] } # kxio = {path = "../kxio/"} kxio = "4.0" @@ -23,7 +19,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" tokio = { version = "1.41", features = ["full"] } toml = "0.8" -tracing= "0.1" +tracing = "0.1" tracing-subscriber = "0.3" [dev-dependencies] diff --git a/src/trello/tests/attachment/get.rs b/src/trello/tests/attachment/get.rs new file mode 100644 index 0000000..dec8344 --- /dev/null +++ b/src/trello/tests/attachment/get.rs @@ -0,0 +1,108 @@ +// +use crate::trello::attachment::TrelloAttachmentCommand; +use crate::trello::model::TrelloAttachmentId; + +use super::*; + +#[rstest::fixture] +fn card_id() -> TrelloCardId { + s!("65ad94865aed24f70ecdcebb").into() +} + +#[rstest::fixture] +fn attachment_id() -> TrelloAttachmentId { + s!("65ad94865aed24f70ecdcebc").into() +} + +#[rstest::fixture] +fn ctx() -> FullCtx { + let fs = given::a_filesystem(); + let trello_config = given::a_trello_config(); + let card_id = card_id(); + let attachment_id = attachment_id(); + + let mock_net = given::a_network(); + mock_net + .on() + .get(f!( + "https://api.trello.com/1/cards/{}/attachments/{}", + card_id.as_ref(), + attachment_id.as_ref() + )) + .header("content-type", "application/json") + .header("accept", "application/json") + .headers(HashMap::from([( + s!("authorization"), + f!( + "OAuth oauth_consumer_key=\"{}\", oauth_token=\"{}\"", + trello_config.api_key, + trello_config.api_secret + ), + )])) + .respond(StatusCode::OK) + .header("content-type", "application/json") + .body(include_str!( + "../../../tests/responses/trello-attachment-get.json" + )) + .expect("mock request"); + + FullCtx { + fs: fs.as_real(), + net: mock_net.into(), + prt: given::a_printer(), + cfg: AppConfig { + trello: trello_config, + nextcloud: given::a_nextcloud_config(), + }, + } +} + +#[rstest::rstest] +#[test_log::test(tokio::test)] +async fn dump(ctx: FullCtx, card_id: TrelloCardId, attachment_id: TrelloAttachmentId) { + //given + let prt = ctx.prt.clone(); + let prt = prt.as_test().unwrap(); + + //when + Command::Trello(TrelloCommand::Attachment(TrelloAttachmentCommand::Get { + dump: true, + card_id: card_id.into(), + attachment_id: attachment_id.into(), + })) + .execute(ctx) + .await + .expect("execute"); + + //then + let output = prt.output(); + assert_eq!( + output.trim(), + include_str!("../../../tests/responses/trello-attachment-get.json").trim() + ); +} + +#[rstest::rstest] +#[tokio::test] +async fn no_dump(ctx: FullCtx, card_id: TrelloCardId, attachment_id: TrelloAttachmentId) { + //given + let prt = ctx.prt.clone(); + let prt = prt.as_test().unwrap(); + + //when + Command::Trello(TrelloCommand::Attachment(TrelloAttachmentCommand::Get { + dump: false, + card_id: card_id.into(), + attachment_id: attachment_id.into(), + })) + .execute(ctx) + .await + .expect("execute"); + + //then + let output = prt.output(); + assert_peq!( + output.trim(), + ["Backlog.png:https://trello.com/1/cards/65ad94865aed24f70ecdcebb/attachments/65ad94875aed24f70ecdd037/download/Backlog.png"].join("\n") + ); +} diff --git a/src/trello/tests/attachment/mod.rs b/src/trello/tests/attachment/mod.rs new file mode 100644 index 0000000..b364aa6 --- /dev/null +++ b/src/trello/tests/attachment/mod.rs @@ -0,0 +1,5 @@ +// +use super::*; + +mod get; +mod save; diff --git a/src/trello/tests/attachment/save.rs b/src/trello/tests/attachment/save.rs new file mode 100644 index 0000000..6af388c --- /dev/null +++ b/src/trello/tests/attachment/save.rs @@ -0,0 +1,126 @@ +use crate::trello::attachment::TrelloAttachmentCommand; +use crate::trello::model::{TrelloAttachmentId, TrelloCardId}; +use crate::Command; +use assert2::let_assert; +use http::Response; +use kxio::fs::{FileSystem, TempFileSystem}; +use std::path::PathBuf; +// +use super::*; + +#[rstest::fixture] +fn card_id() -> TrelloCardId { + s!("65ad94865aed24f70ecdcebb").into() +} + +#[rstest::fixture] +fn attachment_id() -> TrelloAttachmentId { + s!("65ad94875aed24f70ecdd037").into() +} + +#[rstest::fixture] +fn ctx_fs() -> (FullCtx, TempFileSystem) { + let fs = given::a_filesystem(); + let trello_config = given::a_trello_config(); + let card_id = card_id(); + let attachment_id = attachment_id(); + + let mock_net = given::a_network(); + // get the attachment to obtian the URL to download + mock_net + .on() + .get(f!( + "https://api.trello.com/1/cards/{}/attachments/{}", + card_id.as_ref(), + attachment_id.as_ref() + )) + .header("content-type", "application/json") + .header("accept", "application/json") + .headers(HashMap::from([( + s!("authorization"), + f!( + "OAuth oauth_consumer_key=\"{}\", oauth_token=\"{}\"", + trello_config.api_key, + trello_config.api_secret + ), + )])) + .respond(StatusCode::OK) + .header("content-type", "application/json") + .body(include_str!( + "../../../tests/responses/trello-attachment-get.json" + )) + .expect("mock request"); + + // download the attachment + mock_net + .on() + .get(f!( + "https://trello.com/1/cards/{}/attachments/{}/download/Backlog.png", + card_id.as_ref(), + attachment_id.as_ref() + )) + .headers(HashMap::from([( + s!("authorization"), + f!( + "OAuth oauth_consumer_key=\"{}\", oauth_token=\"{}\"", + trello_config.api_key, + trello_config.api_secret + ), + )])) + .header("accept", "application/octet") + .respond(StatusCode::OK) + .body(include_bytes!("../../../tests/responses/trello-attachment-save.png").as_slice()) + .expect("mock response"); + + ( + FullCtx { + fs: fs.as_real(), + net: mock_net.into(), + prt: given::a_printer(), + cfg: AppConfig { + trello: trello_config, + nextcloud: given::a_nextcloud_config(), + }, + }, + fs, + ) +} + +#[rstest::rstest] +#[test_log::test(tokio::test)] +async fn save( + ctx_fs: (FullCtx, TempFileSystem), + card_id: TrelloCardId, + attachment_id: TrelloAttachmentId, +) { + //given + let (ctx, fs) = ctx_fs; + let prt = ctx.prt.clone(); + let prt = prt.as_test().unwrap(); + + //when + Command::Trello(TrelloCommand::Attachment(TrelloAttachmentCommand::Save { + card_id: card_id.into(), + attachment_id: attachment_id.into(), + file_name: None, // Case? + })) + .execute(ctx) + .await + .expect("execute"); + + //then + let file_name = fs.base().join("Backlog.png"); + let output = prt.output(); + assert_peq!( + output.trim(), + [f!("Wrote: {}", file_name.display())].join("\n") + ); + let saved_file = fs.file(&file_name); + let_assert!(Ok(_) = saved_file.is_file()); + let_assert!(Ok(reader) = saved_file.reader()); + let data = reader.bytes(); + assert_eq!( + data, + include_bytes!("../../../tests/responses/trello-attachment-save.png").as_slice() + ); +} diff --git a/src/trello/tests/card/get.rs b/src/trello/tests/card/get.rs index 4e371a4..d672039 100644 --- a/src/trello/tests/card/get.rs +++ b/src/trello/tests/card/get.rs @@ -15,7 +15,7 @@ fn ctx() -> FullCtx { let mock_net = given::a_network(); mock_net .on() - .get("https://api.trello.com/1/cards/65ad94865aed24f70ecdcebb") + .get(f!("https://api.trello.com/1/cards/{}", card_id.as_ref())) .header("content-type", "application/json") .header("accept", "application/json") .headers(HashMap::from([( diff --git a/src/trello/tests/mod.rs b/src/trello/tests/mod.rs index fc8ae38..bb87df8 100644 --- a/src/trello/tests/mod.rs +++ b/src/trello/tests/mod.rs @@ -25,6 +25,7 @@ use crate::{ AppConfig, Command, FullCtx, }; +mod attachment; mod board; mod card; mod member;