feat(trello): add command 'trello board list'
This commit is contained in:
parent
9c8243561f
commit
5a6b297954
15 changed files with 7661 additions and 481 deletions
19
src/lib.rs
19
src/lib.rs
|
@ -35,6 +35,8 @@ enum Command {
|
||||||
Check,
|
Check,
|
||||||
Import,
|
Import,
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
|
Trello(TrelloCommand),
|
||||||
|
#[clap(subcommand)]
|
||||||
Nextcloud(NextcloudCommand),
|
Nextcloud(NextcloudCommand),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +64,20 @@ enum NextcloudStackCommand {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
enum TrelloCommand {
|
||||||
|
#[clap(subcommand)]
|
||||||
|
Board(TrelloBoardCommand),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
enum TrelloBoardCommand {
|
||||||
|
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,
|
||||||
|
@ -116,6 +132,9 @@ pub async fn run(ctx: Ctx) -> color_eyre::Result<()> {
|
||||||
Command::Init => Err(eyre!("Config file already exists. Not overwriting it.")),
|
Command::Init => Err(eyre!("Config file already exists. Not overwriting it.")),
|
||||||
Command::Check => todo!("check"),
|
Command::Check => todo!("check"),
|
||||||
Command::Import => todo!("import"),
|
Command::Import => todo!("import"),
|
||||||
|
Command::Trello(TrelloCommand::Board(TrelloBoardCommand::List { dump })) => {
|
||||||
|
trello::boards::list(ctx, dump).await
|
||||||
|
}
|
||||||
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,
|
||||||
|
|
|
@ -11,8 +11,8 @@ pub mod board;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
pub mod stack;
|
pub mod stack;
|
||||||
|
|
||||||
#[cfg(test)]
|
// #[cfg(test)]
|
||||||
mod tests;
|
// mod tests;
|
||||||
|
|
||||||
pub(crate) struct DeckClient<'ctx> {
|
pub(crate) struct DeckClient<'ctx> {
|
||||||
ctx: &'ctx FullCtx,
|
ctx: &'ctx FullCtx,
|
||||||
|
|
|
@ -1,295 +0,0 @@
|
||||||
//
|
|
||||||
use kxio::net::StatusCode;
|
|
||||||
use pretty_assertions::assert_eq as assert_peq;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
config::NextcloudConfig,
|
|
||||||
nextcloud::{
|
|
||||||
model::{
|
|
||||||
NextcloudBoardId, NextcloudETag, NextcloudHostname, NextcloudOrder, NextcloudPassword,
|
|
||||||
NextcloudStackId, NextcloudStackTitle, NextcloudUsername, Stack,
|
|
||||||
},
|
|
||||||
DeckClient,
|
|
||||||
},
|
|
||||||
AppConfig, FullCtx,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod stack;
|
|
||||||
|
|
||||||
mod config {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn config_hostname_returns_hostname() {
|
|
||||||
//given
|
|
||||||
let hostname = NextcloudHostname::new("host-name");
|
|
||||||
let username = NextcloudUsername::new("username");
|
|
||||||
let password = NextcloudPassword::new("password");
|
|
||||||
let board_id = NextcloudBoardId::new(2);
|
|
||||||
let cfg = NextcloudConfig {
|
|
||||||
hostname: hostname.clone(),
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
board_id,
|
|
||||||
};
|
|
||||||
|
|
||||||
//when
|
|
||||||
//then
|
|
||||||
assert_peq!(cfg.hostname, hostname);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn config_username_returns_username() {
|
|
||||||
//given
|
|
||||||
let hostname = NextcloudHostname::new("host-name");
|
|
||||||
let username = NextcloudUsername::new("username");
|
|
||||||
let password = NextcloudPassword::new("password");
|
|
||||||
let board_id = NextcloudBoardId::new(2);
|
|
||||||
let cfg = NextcloudConfig {
|
|
||||||
hostname,
|
|
||||||
username: username.clone(),
|
|
||||||
password,
|
|
||||||
board_id,
|
|
||||||
};
|
|
||||||
|
|
||||||
//when
|
|
||||||
//then
|
|
||||||
assert_peq!(cfg.username, username);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn config_password_returns_password() {
|
|
||||||
//given
|
|
||||||
let hostname = NextcloudHostname::new("host-name");
|
|
||||||
let username = NextcloudUsername::new("username");
|
|
||||||
let password = NextcloudPassword::new("password");
|
|
||||||
let board_id = NextcloudBoardId::new(2);
|
|
||||||
let cfg = NextcloudConfig {
|
|
||||||
hostname,
|
|
||||||
username,
|
|
||||||
password: password.clone(),
|
|
||||||
board_id,
|
|
||||||
};
|
|
||||||
|
|
||||||
//when
|
|
||||||
//then
|
|
||||||
assert_peq!(cfg.password, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn config_board_id_returns_board_id() {
|
|
||||||
//given
|
|
||||||
let hostname = NextcloudHostname::new("host-name");
|
|
||||||
let username = NextcloudUsername::new("username");
|
|
||||||
let password = NextcloudPassword::new("password");
|
|
||||||
let board_id = NextcloudBoardId::new(2);
|
|
||||||
let cfg = NextcloudConfig {
|
|
||||||
hostname,
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
board_id,
|
|
||||||
};
|
|
||||||
|
|
||||||
//when
|
|
||||||
//then
|
|
||||||
assert_peq!(cfg.board_id, board_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod commands {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
mod board {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
mod list {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
fn setup() -> FullCtx {
|
|
||||||
//
|
|
||||||
let mock_net = kxio::net::mock();
|
|
||||||
|
|
||||||
mock_net
|
|
||||||
.on()
|
|
||||||
.get("https://host-name/index.php/apps/deck/api/v1.0/boards")
|
|
||||||
.basic_auth("username", Some("password"))
|
|
||||||
.respond(StatusCode::OK)
|
|
||||||
.body(include_str!("../tests/responses/nextcloud-board-list.json"))
|
|
||||||
.expect("mock request");
|
|
||||||
|
|
||||||
let fs = given::a_filesystem();
|
|
||||||
|
|
||||||
FullCtx {
|
|
||||||
fs: fs.as_real(),
|
|
||||||
net: mock_net.into(),
|
|
||||||
prt: given::a_printer().clone(),
|
|
||||||
cfg: AppConfig {
|
|
||||||
trello: given::a_trello_config(),
|
|
||||||
nextcloud: given::a_nextcloud_config(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[tokio::test]
|
|
||||||
async fn dump() {
|
|
||||||
//given
|
|
||||||
let ctx = setup();
|
|
||||||
let prt = ctx.prt.clone();
|
|
||||||
let prt = prt.as_test().unwrap();
|
|
||||||
|
|
||||||
//when
|
|
||||||
crate::nextcloud::board::list(ctx, true)
|
|
||||||
.await
|
|
||||||
.expect("board list");
|
|
||||||
|
|
||||||
//then
|
|
||||||
let output = prt.output();
|
|
||||||
assert_peq!(
|
|
||||||
output.trim(),
|
|
||||||
include_str!("../tests/responses/nextcloud-board-list.json").trim() // [""].join("\n")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn no_dump() {
|
|
||||||
//given
|
|
||||||
let ctx = setup();
|
|
||||||
let prt = ctx.prt.clone();
|
|
||||||
let prt = prt.as_test().unwrap();
|
|
||||||
|
|
||||||
//when
|
|
||||||
crate::nextcloud::board::list(ctx, false)
|
|
||||||
.await
|
|
||||||
.expect("board list");
|
|
||||||
|
|
||||||
//then
|
|
||||||
let output = prt.output();
|
|
||||||
assert_peq!(
|
|
||||||
output.trim(),
|
|
||||||
[
|
|
||||||
"4:4 Published: Cossmass Infinities",
|
|
||||||
"5:Fulfilment: Cossmass Infinities",
|
|
||||||
"1:Personal Board"
|
|
||||||
]
|
|
||||||
.join("\n")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod stack {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn list() {
|
|
||||||
//given
|
|
||||||
let mock_net = kxio::net::mock();
|
|
||||||
|
|
||||||
mock_net
|
|
||||||
.on()
|
|
||||||
.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");
|
|
||||||
|
|
||||||
let fs = given::a_filesystem();
|
|
||||||
let ctx = FullCtx {
|
|
||||||
fs: fs.as_real(),
|
|
||||||
net: mock_net.into(),
|
|
||||||
prt: given::a_printer(),
|
|
||||||
cfg: AppConfig {
|
|
||||||
trello: given::a_trello_config(),
|
|
||||||
nextcloud: given::a_nextcloud_config(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let deck_client = DeckClient::new(&ctx);
|
|
||||||
|
|
||||||
//when
|
|
||||||
let result = deck_client
|
|
||||||
.get_stacks(ctx.cfg.nextcloud.board_id)
|
|
||||||
.await
|
|
||||||
.result
|
|
||||||
.expect("get stacks");
|
|
||||||
|
|
||||||
assert_peq!(
|
|
||||||
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),
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod given {
|
|
||||||
use kxio::{fs::TempFileSystem, net::MockNet, print::Printer};
|
|
||||||
|
|
||||||
use crate::{config::TrelloConfig, s, AppConfig, FullCtx};
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
pub fn a_nextcloud_config() -> NextcloudConfig {
|
|
||||||
let hostname = NextcloudHostname::new("host-name");
|
|
||||||
let username = NextcloudUsername::new("username");
|
|
||||||
let password = NextcloudPassword::new("password");
|
|
||||||
let board_id = NextcloudBoardId::new(2);
|
|
||||||
NextcloudConfig {
|
|
||||||
hostname,
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
board_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn a_network() -> MockNet {
|
|
||||||
kxio::net::mock()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn a_printer() -> Printer {
|
|
||||||
kxio::print::test()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn a_filesystem() -> TempFileSystem {
|
|
||||||
kxio::fs::temp().expect("temp fs")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn a_trello_config() -> TrelloConfig {
|
|
||||||
TrelloConfig {
|
|
||||||
api_key: s!("trello-api-key").into(),
|
|
||||||
api_secret: s!("trello-api-secret").into(),
|
|
||||||
board_name: s!("trello-board-name").into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn a_full_context(mock_net: MockNet, fs: TempFileSystem) -> FullCtx {
|
|
||||||
FullCtx {
|
|
||||||
fs: fs.as_real(),
|
|
||||||
net: mock_net.into(),
|
|
||||||
prt: given::a_printer(),
|
|
||||||
cfg: AppConfig {
|
|
||||||
trello: given::a_trello_config(),
|
|
||||||
nextcloud: given::a_nextcloud_config(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +1,16 @@
|
||||||
//
|
//
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
// type TestResult = Result<(), Box<dyn std::error::Error>>;
|
// type TestResult = Result<(), Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
use assert2::let_assert;
|
use assert2::let_assert;
|
||||||
|
use kxio::{
|
||||||
|
fs::{FileSystem, TempFileSystem},
|
||||||
|
net::{MockNet, Net},
|
||||||
|
print::Printer,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{config::AppConfig, f, NAME};
|
use crate::{config::AppConfig, f, init::run, Ctx, NAME};
|
||||||
|
|
||||||
mod config {
|
mod config {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -60,13 +66,8 @@ mod config {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod init {
|
mod init {
|
||||||
|
|
||||||
use test_log::test;
|
|
||||||
|
|
||||||
use crate::{f, init::run, NAME};
|
|
||||||
|
|
||||||
use super::given;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use test_log::test;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn when_file_does_not_exist_should_create() {
|
fn when_file_does_not_exist_should_create() {
|
||||||
|
@ -104,10 +105,7 @@ mod init {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod template {
|
mod template {
|
||||||
|
use super::*;
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use crate::template;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn expand_should_substitute_values() {
|
fn expand_should_substitute_values() {
|
||||||
|
@ -116,7 +114,7 @@ mod template {
|
||||||
let params = HashMap::from([("param1", "-v1-"), ("param2", "-v2-")]);
|
let params = HashMap::from([("param1", "-v1-"), ("param2", "-v2-")]);
|
||||||
|
|
||||||
//when
|
//when
|
||||||
let result = template::expand(template, params);
|
let result = crate::template::expand(template, params);
|
||||||
|
|
||||||
//then
|
//then
|
||||||
assert_eq!(result, "pre-v1-mid-v2-post");
|
assert_eq!(result, "pre-v1-mid-v2-post");
|
||||||
|
@ -124,13 +122,7 @@ mod template {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod given {
|
mod given {
|
||||||
use kxio::{
|
use super::*;
|
||||||
fs::{FileSystem, TempFileSystem},
|
|
||||||
net::{MockNet, Net},
|
|
||||||
print::Printer,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::Ctx;
|
|
||||||
|
|
||||||
pub fn a_context(fs: FileSystem, net: Net, prt: Printer) -> Ctx {
|
pub fn a_context(fs: FileSystem, net: Net, prt: Printer) -> Ctx {
|
||||||
Ctx { fs, net, prt }
|
Ctx { fs, net, prt }
|
||||||
|
@ -147,4 +139,32 @@ mod given {
|
||||||
pub fn a_printer() -> Printer {
|
pub fn a_printer() -> Printer {
|
||||||
kxio::print::test()
|
kxio::print::test()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub fn a_config() -> AppConfig {
|
||||||
|
// AppConfig {
|
||||||
|
// trello: a_trello_config(),
|
||||||
|
// nextcloud: a_nextcloud_config(),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn a_trello_config() -> TrelloConfig {
|
||||||
|
// TrelloConfig {
|
||||||
|
// api_key: s!("trello-api-key").into(),
|
||||||
|
// api_secret: s!("trello-api-secret").into(),
|
||||||
|
// board_name: s!("Trello Platform Changes").into(),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn a_nextcloud_config() -> NextcloudConfig {
|
||||||
|
// let hostname = s!("nextcloud.example.org").into();
|
||||||
|
// let username = s!("username").into();
|
||||||
|
// let password = s!("password").into();
|
||||||
|
// let board_id = NextcloudBoardId::new(2);
|
||||||
|
// NextcloudConfig {
|
||||||
|
// hostname,
|
||||||
|
// username,
|
||||||
|
// password,
|
||||||
|
// board_id,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
7484
src/tests/responses/trello-boards-list.json
Normal file
7484
src/tests/responses/trello-boards-list.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -2,12 +2,10 @@
|
||||||
use kxio::{net::Net, print::Printer};
|
use kxio::{net::Net, print::Printer};
|
||||||
|
|
||||||
use crate::api_result::APIResult;
|
use crate::api_result::APIResult;
|
||||||
use crate::{
|
use crate::config::TrelloConfig;
|
||||||
f,
|
use crate::trello::{
|
||||||
trello::{
|
types::{auth::TrelloAuth, board::TrelloBoard},
|
||||||
types::{auth::TrelloAuth, board::TrelloBoard},
|
url,
|
||||||
url,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Get lists from named board that Member belongs to
|
/// Get lists from named board that Member belongs to
|
||||||
|
@ -40,12 +38,13 @@ use crate::{
|
||||||
/// --url "https://api.trello.com/1/members/$TRELLO_USERNAME/boards?key=$TRELLO_KEY&token=$TRELLO_SECRET&lists=open" \
|
/// --url "https://api.trello.com/1/members/$TRELLO_USERNAME/boards?key=$TRELLO_KEY&token=$TRELLO_SECRET&lists=open" \
|
||||||
/// --header 'Accept: application/json'
|
/// --header 'Accept: application/json'
|
||||||
pub async fn get_boards_that_member_belongs_to(
|
pub async fn get_boards_that_member_belongs_to(
|
||||||
auth: &TrelloAuth,
|
cfg: &TrelloConfig,
|
||||||
net: &Net,
|
net: &Net,
|
||||||
prt: &Printer,
|
prt: &Printer,
|
||||||
) -> APIResult<Vec<TrelloBoard>> {
|
) -> APIResult<Vec<TrelloBoard>> {
|
||||||
|
let auth = TrelloAuth::new(&cfg.api_key, &cfg.api_secret);
|
||||||
APIResult::new(
|
APIResult::new(
|
||||||
net.get(url(f!("/members/{}/boards?lists=open", **auth.user())))
|
net.get(url("/members/me/boards?lists=open"))
|
||||||
.headers(auth.into())
|
.headers(auth.into())
|
||||||
.header("Accept", "application/json")
|
.header("Accept", "application/json")
|
||||||
.send()
|
.send()
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
//
|
//
|
||||||
use kxio::{net::MockNet, print::Printer};
|
use kxio::{net::MockNet, print::Printer};
|
||||||
|
|
||||||
use crate::trello::types::auth::{TrelloApiKey, TrelloApiSecret, TrelloAuth, TrelloUser};
|
|
||||||
|
|
||||||
pub(crate) fn a_network() -> MockNet {
|
pub(crate) fn a_network() -> MockNet {
|
||||||
kxio::net::mock()
|
kxio::net::mock()
|
||||||
}
|
}
|
||||||
|
@ -11,10 +9,9 @@ pub(crate) fn a_printer() -> Printer {
|
||||||
kxio::print::test()
|
kxio::print::test()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn an_auth() -> TrelloAuth {
|
// pub(crate) fn an_auth<'cfg>(cfg: &'cfg TrelloConfig) -> TrelloAuth<'cfg> {
|
||||||
TrelloAuth::new(
|
// TrelloAuth {
|
||||||
TrelloApiKey::new("foo"),
|
// api_key: &cfg.api_key,
|
||||||
TrelloApiSecret::new("bar"),
|
// api_secret: &cfg.api_secret,
|
||||||
TrelloUser::new("baz"),
|
// }
|
||||||
)
|
// }
|
||||||
}
|
|
||||||
|
|
|
@ -1,63 +1,63 @@
|
||||||
// use super::*;
|
//
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use kxio::net::StatusCode;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
config::TrelloConfig,
|
||||||
|
s,
|
||||||
|
trello::{api::members::get_boards_that_member_belongs_to, types::board::TrelloBoard},
|
||||||
|
};
|
||||||
|
|
||||||
use super::*;
|
|
||||||
mod given;
|
mod given;
|
||||||
|
|
||||||
type TestResult = color_eyre::Result<()>;
|
type TestResult = color_eyre::Result<()>;
|
||||||
|
|
||||||
mod members {
|
mod members {
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use super::*;
|
||||||
|
|
||||||
use kxio::net::StatusCode;
|
#[tokio::test]
|
||||||
use serde_json::json;
|
async fn get_member_boards() -> TestResult {
|
||||||
|
//given
|
||||||
|
let net = given::a_network();
|
||||||
|
let prt = given::a_printer();
|
||||||
|
let trello_config = TrelloConfig {
|
||||||
|
api_key: s!("foo").into(),
|
||||||
|
api_secret: s!("bar").into(),
|
||||||
|
board_name: s!("board-name").into(),
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
net.on()
|
||||||
s,
|
.get("https://api.trello.com/1/members/me/boards?lists=open")
|
||||||
trello::{
|
.headers(HashMap::from([
|
||||||
api::members::get_boards_that_member_belongs_to,
|
(
|
||||||
types::{board::TrelloBoard, TrelloBoardId, TrelloBoardName},
|
s!("authorization"),
|
||||||
},
|
s!("OAuth oauth_consumer_key=\"foo\", oauth_token=\"bar\""),
|
||||||
};
|
),
|
||||||
|
(s!("accept"), s!("application/json")),
|
||||||
|
]))
|
||||||
|
.respond(StatusCode::OK)
|
||||||
|
.body(s!(json!([
|
||||||
|
{"id": "1", "name": "board-name", "lists":[]}
|
||||||
|
])))?;
|
||||||
|
|
||||||
use super::*;
|
//when
|
||||||
|
let result = get_boards_that_member_belongs_to(&trello_config, &net.into(), &prt)
|
||||||
#[tokio::test]
|
|
||||||
async fn get_member_boards() -> TestResult {
|
|
||||||
//given
|
|
||||||
let net = given::a_network();
|
|
||||||
let prt = given::a_printer();
|
|
||||||
let auth = given::an_auth();
|
|
||||||
|
|
||||||
net.on()
|
|
||||||
.get("https://api.trello.com/1/members/baz/boards?lists=open")
|
|
||||||
.headers(HashMap::from([
|
|
||||||
(
|
|
||||||
s!("authorization"),
|
|
||||||
s!("OAuth oauth_consumer_key=\"foo\", oauth_token=\"bar\""),
|
|
||||||
),
|
|
||||||
(s!("accept"), s!("application/json")),
|
|
||||||
]))
|
|
||||||
.respond(StatusCode::OK)
|
|
||||||
.body(s!(json!([
|
|
||||||
{"id": "1", "name": "board-1", "lists":[]}
|
|
||||||
])))?;
|
|
||||||
|
|
||||||
//when
|
|
||||||
let result = get_boards_that_member_belongs_to(&auth, &net.into(), &prt)
|
|
||||||
.await
|
.await
|
||||||
.result?;
|
.result?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
vec![TrelloBoard::new(
|
vec![TrelloBoard {
|
||||||
TrelloBoardId::new("1"),
|
id: s!("1").into(),
|
||||||
TrelloBoardName::new("board-1"),
|
name: s!("board-name").into(),
|
||||||
vec![]
|
lists: vec![]
|
||||||
)]
|
}]
|
||||||
);
|
);
|
||||||
|
|
||||||
//then
|
//then
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
src/trello/boards.rs
Normal file
18
src/trello/boards.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
//
|
||||||
|
use crate::{p, FullCtx};
|
||||||
|
|
||||||
|
pub(crate) async fn list(ctx: FullCtx, dump: bool) -> color_eyre::Result<()> {
|
||||||
|
let api_result =
|
||||||
|
super::api::members::get_boards_that_member_belongs_to(&ctx.cfg.trello, &ctx.net, &ctx.prt)
|
||||||
|
.await;
|
||||||
|
if dump {
|
||||||
|
p!(ctx.prt, "{}", api_result.text);
|
||||||
|
} else {
|
||||||
|
let mut boards = api_result.result?;
|
||||||
|
boards.sort_by(|a, b| a.name.cmp(&b.name));
|
||||||
|
boards.into_iter().for_each(|board| {
|
||||||
|
p!(ctx.prt, "{}:{}", board.id, board.name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,14 +1,16 @@
|
||||||
//
|
//
|
||||||
// pub mod api;
|
// pub mod api;
|
||||||
|
pub mod api;
|
||||||
|
pub mod boards;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
#[cfg(test)]
|
// #[cfg(test)]
|
||||||
mod tests;
|
// mod tests;
|
||||||
|
|
||||||
// use crate::f;
|
use crate::f;
|
||||||
//
|
|
||||||
// pub fn url(path: impl Into<String>) -> String {
|
pub fn url(path: impl Into<String>) -> String {
|
||||||
// let path = path.into();
|
let path = path.into();
|
||||||
// assert!(path.starts_with("/"));
|
assert!(path.starts_with("/"));
|
||||||
// f!("https://api.trello.com/1{path}")
|
f!("https://api.trello.com/1{path}")
|
||||||
// }
|
}
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
use crate::s;
|
|
||||||
use crate::trello::types::auth::TrelloAuth;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
mod board {
|
|
||||||
// use crate::trello::{
|
|
||||||
// // api::boards::TrelloBoards as _,
|
|
||||||
// types::{
|
|
||||||
// board::TrelloBoard, TrelloBoardId, TrelloBoardName, TrelloListId, TrelloListName,
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn list_of_boards_find_by_name_returns_board() {
|
|
||||||
// //given
|
|
||||||
// let board = TrelloBoard::new(
|
|
||||||
// TrelloBoardId::new("2"),
|
|
||||||
// TrelloBoardName::new("beta"),
|
|
||||||
// vec![],
|
|
||||||
// );
|
|
||||||
// let boards = vec![
|
|
||||||
// TrelloBoard::new(
|
|
||||||
// TrelloBoardId::new("1"),
|
|
||||||
// TrelloBoardName::new("alpha"),
|
|
||||||
// vec![],
|
|
||||||
// ),
|
|
||||||
// board.clone(),
|
|
||||||
// TrelloBoard::new(
|
|
||||||
// TrelloBoardId::new("3"),
|
|
||||||
// TrelloBoardName::new("gamma"),
|
|
||||||
// vec![],
|
|
||||||
// ),
|
|
||||||
// ];
|
|
||||||
//
|
|
||||||
// //when
|
|
||||||
// let result = boards.find_by_name(board.name());
|
|
||||||
//
|
|
||||||
// //then
|
|
||||||
// assert_eq!(result, Some(&board));
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn trello_auth_into_hashmap() {
|
|
||||||
//given
|
|
||||||
let trello_auth = TrelloAuth {
|
|
||||||
api_key: s!("key").into(),
|
|
||||||
api_secret: s!("token").into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
//when
|
|
||||||
let result = HashMap::<String, String>::from(&trello_auth);
|
|
||||||
|
|
||||||
//then
|
|
||||||
assert_eq!(
|
|
||||||
result,
|
|
||||||
HashMap::from([(
|
|
||||||
s!("Authorization"),
|
|
||||||
s!("OAuth oauth_consumer_key=\"key\", oauth_token=\"token\"")
|
|
||||||
),])
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -14,12 +14,12 @@ newtype!(
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TrelloAuth {
|
pub struct TrelloAuth<'cfg> {
|
||||||
pub(crate) api_key: TrelloApiKey,
|
pub(crate) api_key: &'cfg TrelloApiKey,
|
||||||
pub(crate) api_secret: TrelloApiSecret,
|
pub(crate) api_secret: &'cfg TrelloApiSecret,
|
||||||
}
|
}
|
||||||
impl TrelloAuth {
|
impl<'cfg> TrelloAuth<'cfg> {
|
||||||
pub const fn new(api_key: TrelloApiKey, api_secret: TrelloApiSecret) -> Self {
|
pub const fn new(api_key: &'cfg TrelloApiKey, api_secret: &'cfg TrelloApiSecret) -> Self {
|
||||||
Self {
|
Self {
|
||||||
api_key,
|
api_key,
|
||||||
api_secret,
|
api_secret,
|
||||||
|
@ -33,8 +33,8 @@ impl TrelloAuth {
|
||||||
&self.api_secret
|
&self.api_secret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<&TrelloAuth> for HashMap<String, String> {
|
impl<'cfg> From<TrelloAuth<'cfg>> for HashMap<String, String> {
|
||||||
fn from(value: &TrelloAuth) -> Self {
|
fn from(value: TrelloAuth) -> Self {
|
||||||
HashMap::from([(
|
HashMap::from([(
|
||||||
"Authorization".into(),
|
"Authorization".into(),
|
||||||
format!(
|
format!(
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
//
|
//
|
||||||
use derive_more::derive::Constructor;
|
|
||||||
|
|
||||||
use crate::trello::types::list::TrelloList;
|
use crate::trello::types::list::TrelloList;
|
||||||
|
use crate::trello::types::{TrelloBoardId, TrelloBoardName};
|
||||||
|
|
||||||
use super::{TrelloBoardId, TrelloBoardName};
|
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, Constructor)]
|
|
||||||
pub(crate) struct TrelloBoard {
|
pub(crate) struct TrelloBoard {
|
||||||
pub(crate) id: TrelloBoardId,
|
pub(crate) id: TrelloBoardId,
|
||||||
pub(crate) name: TrelloBoardName,
|
pub(crate) name: TrelloBoardName,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
//
|
||||||
use derive_more::derive::Constructor;
|
use derive_more::derive::Constructor;
|
||||||
|
|
||||||
use super::{TrelloListId, TrelloListName};
|
use crate::trello::types::{TrelloListId, TrelloListName};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, Constructor)]
|
#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, Constructor)]
|
||||||
pub(crate) struct TrelloList {
|
pub(crate) struct TrelloList {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
pub(crate) mod auth;
|
pub(crate) mod auth;
|
||||||
// pub(crate) mod board;
|
pub(crate) mod board;
|
||||||
// mod card;
|
// mod card;
|
||||||
// mod list;
|
mod list;
|
||||||
// mod new_card;
|
// mod new_card;
|
||||||
|
|
||||||
use derive_more::derive::Display;
|
use derive_more::derive::Display;
|
||||||
|
|
||||||
use crate::newtype;
|
use crate::newtype;
|
||||||
|
|
||||||
// newtype!(TrelloBoardId, String, Display, "Board ID");
|
newtype!(TrelloBoardId, String, Display, "Board ID");
|
||||||
newtype!(
|
newtype!(
|
||||||
TrelloBoardName,
|
TrelloBoardName,
|
||||||
String,
|
String,
|
||||||
|
@ -17,14 +17,14 @@ newtype!(
|
||||||
Ord,
|
Ord,
|
||||||
"Board Name"
|
"Board Name"
|
||||||
);
|
);
|
||||||
// newtype!(TrelloListId, String, "List ID");
|
newtype!(TrelloListId, String, "List ID");
|
||||||
// newtype!(
|
newtype!(
|
||||||
// TrelloListName,
|
TrelloListName,
|
||||||
// String,
|
String,
|
||||||
// Display,
|
Display,
|
||||||
// PartialOrd,
|
PartialOrd,
|
||||||
// Ord,
|
Ord,
|
||||||
// "List Name"
|
"List Name"
|
||||||
// );
|
);
|
||||||
// newtype!(TrelloCardId, String, Display, "Card ID");
|
// newtype!(TrelloCardId, String, Display, "Card ID");
|
||||||
// newtype!(TrelloCardName, String, Display, "Card Name");
|
// newtype!(TrelloCardName, String, Display, "Card Name");
|
||||||
|
|
Loading…
Reference in a new issue