feat(nextcloud): add command 'nextcloud stack list'
Some checks failed
Test / build (map[name:nightly]) (push) Successful in 2m23s
Test / build (map[name:stable]) (push) Successful in 3m1s
Release Please / Release-plz (push) Failing after 21s

This commit is contained in:
Paul Campbell 2024-11-30 18:04:48 +00:00
parent 584f056b45
commit 9c8243561f
8 changed files with 169 additions and 60 deletions

View file

@ -29,5 +29,6 @@ toml = "0.8"
[dev-dependencies] [dev-dependencies]
assert2 = "0.3" assert2 = "0.3"
mutants = "0.0" mutants = "0.0"
#pretty_assertions = "1.4" pretty_assertions = "1.4"
rstest = "0.23"
test-log = { version = "0.2", features = ["trace"] } test-log = { version = "0.2", features = ["trace"] }

View file

@ -42,6 +42,8 @@ enum Command {
enum NextcloudCommand { enum NextcloudCommand {
#[clap(subcommand)] #[clap(subcommand)]
Board(NextcloudBoardCommand), Board(NextcloudBoardCommand),
#[clap(subcommand)]
Stack(NextcloudStackCommand),
} }
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -52,6 +54,14 @@ enum NextcloudBoardCommand {
}, },
} }
#[derive(Parser, Debug)]
enum NextcloudStackCommand {
List {
#[clap(long, action = clap::ArgAction::SetTrue)]
dump: bool,
},
}
#[derive(Clone)] #[derive(Clone)]
pub struct Ctx { pub struct Ctx {
pub fs: FileSystem, pub fs: FileSystem,
@ -109,6 +119,9 @@ pub async fn run(ctx: Ctx) -> color_eyre::Result<()> {
Command::Nextcloud(NextcloudCommand::Board(NextcloudBoardCommand::List { Command::Nextcloud(NextcloudCommand::Board(NextcloudBoardCommand::List {
dump, dump,
})) => nextcloud::board::list(ctx, dump).await, })) => nextcloud::board::list(ctx, dump).await,
Command::Nextcloud(NextcloudCommand::Stack(NextcloudStackCommand::List {
dump,
})) => nextcloud::stack::list(ctx, dump).await,
} }
} }
} }

View file

@ -9,6 +9,7 @@ use model::{Board, Card, NextcloudBoardId, Stack};
pub mod board; pub mod board;
pub mod model; pub mod model;
pub mod stack;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;

View file

@ -98,6 +98,7 @@ newtype!(
newtype!( newtype!(
NextcloudStackTitle, NextcloudStackTitle,
String, String,
Display,
PartialOrd, PartialOrd,
Ord, Ord,
"Title of the Stack" "Title of the Stack"
@ -105,6 +106,7 @@ newtype!(
newtype!( newtype!(
NextcloudCardTitle, NextcloudCardTitle,
String, String,
Display,
PartialOrd, PartialOrd,
Ord, Ord,
"Title of the Card" "Title of the Card"

View file

@ -1,19 +1,19 @@
// //
use crate::{p, FullCtx}; use crate::{p, FullCtx};
use super::DeckClient;
pub async fn list(ctx: FullCtx, dump: bool) -> color_eyre::Result<()> { pub async fn list(ctx: FullCtx, dump: bool) -> color_eyre::Result<()> {
let dc = DeckClient::new(&ctx.cfg.nextcloud, ctx.net); let api_result = ctx
let apiresult = dc.get_stacks(ctx.cfg.nextcloud.board_id()).await; .deck_client()
.get_stacks(ctx.cfg.nextcloud.board_id)
.await;
if dump { if dump {
p!("{}", apiresult.text); p!(ctx.prt, "{}", api_result.text);
} else { } else {
let mut stacks = apiresult.result?; let mut stacks = api_result.result?;
stacks.sort_by_key(|stack| stack.order); stacks.sort_by_key(|stack| stack.order);
stacks stacks
.iter() .iter()
.for_each(|stack| p!("{}:{}", stack.id, stack.title)); .for_each(|stack| p!(ctx.prt, "{}:{}", stack.id, stack.title));
} }
Ok(()) Ok(())
} }

View file

@ -1,5 +1,6 @@
// //
use kxio::net::StatusCode; use kxio::net::StatusCode;
use pretty_assertions::assert_eq as assert_peq;
use crate::{ use crate::{
config::NextcloudConfig, config::NextcloudConfig,
@ -13,6 +14,8 @@ use crate::{
AppConfig, FullCtx, AppConfig, FullCtx,
}; };
mod stack;
mod config { mod config {
use super::*; use super::*;
@ -32,7 +35,7 @@ mod config {
//when //when
//then //then
assert_eq!(cfg.hostname, hostname); assert_peq!(cfg.hostname, hostname);
} }
#[test] #[test]
@ -51,7 +54,7 @@ mod config {
//when //when
//then //then
assert_eq!(cfg.username, username); assert_peq!(cfg.username, username);
} }
#[test] #[test]
@ -70,7 +73,7 @@ mod config {
//when //when
//then //then
assert_eq!(cfg.password, password); assert_peq!(cfg.password, password);
} }
#[test] #[test]
@ -89,7 +92,7 @@ mod config {
//when //when
//then //then
assert_eq!(cfg.board_id, board_id); assert_peq!(cfg.board_id, board_id);
} }
} }
@ -140,7 +143,7 @@ mod commands {
//then //then
let output = prt.output(); let output = prt.output();
assert_eq!( assert_peq!(
output.trim(), output.trim(),
include_str!("../tests/responses/nextcloud-board-list.json").trim() // [""].join("\n") include_str!("../tests/responses/nextcloud-board-list.json").trim() // [""].join("\n")
); );
@ -160,7 +163,7 @@ mod commands {
//then //then
let output = prt.output(); let output = prt.output();
assert_eq!( assert_peq!(
output.trim(), output.trim(),
[ [
"4:4 Published: Cossmass Infinities", "4:4 Published: Cossmass Infinities",
@ -173,56 +176,68 @@ mod commands {
} }
} }
#[tokio::test] mod stack {
async fn get_stacks() { use super::*;
//given
let mock_net = kxio::net::mock();
mock_net #[tokio::test]
.on() async fn list() {
.get("https://host-name/index.php/apps/deck/api/v1.0/boards/2/stacks") //given
.basic_auth("username", Some("password")) let mock_net = kxio::net::mock();
.respond(StatusCode::OK)
.body(include_str!("../tests/responses/nextcloud-stack-list.json"))
.expect("mock request");
let fs = given::a_filesystem(); mock_net
let ctx = given::a_full_context(mock_net, fs); .on()
let deck_client = DeckClient::new(&ctx); .get("https://host-name/index.php/apps/deck/api/v1.0/boards/2/stacks")
.basic_auth("username", Some("password"))
.respond(StatusCode::OK)
.body(include_str!("../tests/responses/nextcloud-stack-list.json"))
.expect("mock request");
//when let fs = given::a_filesystem();
let result = deck_client let ctx = FullCtx {
.get_stacks(ctx.cfg.nextcloud.board_id) fs: fs.as_real(),
.await net: mock_net.into(),
.result prt: given::a_printer(),
.expect("get stacks"); cfg: AppConfig {
trello: given::a_trello_config(),
assert_eq!( nextcloud: given::a_nextcloud_config(),
result,
vec![
Stack {
id: NextcloudStackId::new(3),
title: NextcloudStackTitle::new("Done"),
order: NextcloudOrder::new(2),
board_id: NextcloudBoardId::new(1),
etag: NextcloudETag::new("97592874d17017ef4f620c9c2a490086")
}, },
Stack { };
id: NextcloudStackId::new(2), let deck_client = DeckClient::new(&ctx);
title: NextcloudStackTitle::new("Doing"),
order: NextcloudOrder::new(1), //when
board_id: NextcloudBoardId::new(1), let result = deck_client
etag: NextcloudETag::new("3da05f904903c88450b79e4f8f6e2160") .get_stacks(ctx.cfg.nextcloud.board_id)
}, .await
Stack { .result
id: NextcloudStackId::new(1), .expect("get stacks");
title: NextcloudStackTitle::new("To do"),
order: NextcloudOrder::new(0), assert_peq!(
board_id: NextcloudBoardId::new(1), result,
etag: NextcloudETag::new("b567d287210fa4d9b108ac68d5b087c1") vec![
} Stack {
] id: NextcloudStackId::new(3),
); title: NextcloudStackTitle::new("Done"),
order: NextcloudOrder::new(2),
board_id: NextcloudBoardId::new(1),
etag: NextcloudETag::new("97592874d17017ef4f620c9c2a490086")
},
Stack {
id: NextcloudStackId::new(2),
title: NextcloudStackTitle::new("Doing"),
order: NextcloudOrder::new(1),
board_id: NextcloudBoardId::new(1),
etag: NextcloudETag::new("3da05f904903c88450b79e4f8f6e2160")
},
Stack {
id: NextcloudStackId::new(1),
title: NextcloudStackTitle::new("To do"),
order: NextcloudOrder::new(0),
board_id: NextcloudBoardId::new(1),
etag: NextcloudETag::new("b567d287210fa4d9b108ac68d5b087c1")
}
]
);
}
} }
} }
@ -246,6 +261,10 @@ mod given {
} }
} }
pub fn a_network() -> MockNet {
kxio::net::mock()
}
pub fn a_printer() -> Printer { pub fn a_printer() -> Printer {
kxio::print::test() kxio::print::test()
} }

View file

@ -0,0 +1,69 @@
//
use super::*;
#[rstest::fixture]
fn ctx() -> FullCtx {
let fs = given::a_filesystem();
let nextcloud_config = given::a_nextcloud_config();
let mock_net = given::a_network();
mock_net
.on()
.get(crate::f!(
"https://{}/index.php/apps/deck/api/v1.0/boards/{}/stacks",
nextcloud_config.hostname,
nextcloud_config.board_id
))
.respond(StatusCode::OK)
.body(include_str!(
"../../../tests/responses/nextcloud-stack-list.json"
))
.expect("mock request");
FullCtx {
fs: fs.as_real(),
net: mock_net.into(),
prt: given::a_printer(),
cfg: AppConfig {
trello: given::a_trello_config(),
nextcloud: nextcloud_config,
},
}
}
#[rstest::rstest]
#[test_log::test(tokio::test)]
async fn dump(ctx: FullCtx) {
//given
let prt = ctx.prt.clone();
let prt = prt.as_test().unwrap();
//when
crate::nextcloud::stack::list(ctx, true)
.await
.expect("execute");
//then
let output = prt.output();
assert_peq!(
output.trim(),
include_str!("../../../tests/responses/nextcloud-stack-list.json").trim()
);
}
#[rstest::rstest]
#[test_log::test(tokio::test)]
async fn no_dump(ctx: FullCtx) {
//given
let prt = ctx.prt.clone();
let prt = prt.as_test().unwrap();
//when
crate::nextcloud::stack::list(ctx, false)
.await
.expect("execute");
//then
let output = prt.output();
assert_peq!(output.trim(), ["1:To do", "2:Doing", "3:Done"].join("\n"));
}

View file

@ -0,0 +1,4 @@
//
use super::*;
mod list;