tests: add tests for importing
This commit is contained in:
parent
64467cf107
commit
4e0bf611c4
28 changed files with 908 additions and 77 deletions
|
@ -24,6 +24,9 @@ mod stack;
|
|||
mod stacks;
|
||||
mod supervisor;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub(crate) async fn run(ctx: &FullCtx) -> color_eyre::Result<()> {
|
||||
// get list of trello boards
|
||||
let trello_client = ctx.trello_client();
|
||||
|
|
413
src/import/tests/mod.rs
Normal file
413
src/import/tests/mod.rs
Normal file
|
@ -0,0 +1,413 @@
|
|||
//
|
||||
use http::StatusCode;
|
||||
use kameo::actor::spawn_in_thread;
|
||||
use kxio::{fs::TempFileSystem, net::MockNet};
|
||||
use rstest::fixture;
|
||||
use serde_json::json;
|
||||
use tokio::time::Instant;
|
||||
|
||||
use crate::{
|
||||
config::AppConfig,
|
||||
import::{
|
||||
labels::LabelsActor, rate_limit::RateLimitActor, stacks::ImportStacksActor,
|
||||
supervisor::Supervisor,
|
||||
},
|
||||
nextcloud::{
|
||||
model::{NextcloudBoardId, NextcloudStackId},
|
||||
NextcloudConfig,
|
||||
},
|
||||
rate_limit::RateLimit,
|
||||
s, spawn_in_thread,
|
||||
trello::{
|
||||
model::{
|
||||
card::TrelloShortCard,
|
||||
list::{TrelloList, TrelloListPosition},
|
||||
},
|
||||
TrelloConfig,
|
||||
},
|
||||
FullCtx,
|
||||
};
|
||||
|
||||
#[fixture]
|
||||
fn ctx_fs() -> (FullCtx, TempFileSystem) {
|
||||
let fs = kxio::fs::temp().expect("temp fs");
|
||||
let mock_net = kxio::net::mock();
|
||||
(
|
||||
FullCtx {
|
||||
fs: fs.as_real(),
|
||||
temp_fs: fs.clone(),
|
||||
net: mock_net.into(),
|
||||
prt: kxio::print::standard(),
|
||||
cfg: AppConfig {
|
||||
trello: TrelloConfig {
|
||||
api_key: crate::s!("trello-api-key").into(),
|
||||
api_secret: crate::s!("trello-api-secret").into(),
|
||||
},
|
||||
nextcloud: NextcloudConfig {
|
||||
hostname: crate::s!("https://nextcloud-hostname").into(),
|
||||
username: crate::s!("nextcloud-username").into(),
|
||||
password: crate::s!("nextcloud-password").into(),
|
||||
},
|
||||
},
|
||||
},
|
||||
fs,
|
||||
)
|
||||
}
|
||||
|
||||
#[fixture]
|
||||
fn trello_card_without_description_or_label() -> TrelloShortCard {
|
||||
TrelloShortCard {
|
||||
id: s!("trello-id").into(),
|
||||
name: s!("trello-name").into(),
|
||||
desc: s!("").into(),
|
||||
labels: vec![],
|
||||
pos: 333.into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[fixture]
|
||||
fn board_id() -> NextcloudBoardId {
|
||||
444.into()
|
||||
}
|
||||
|
||||
#[fixture]
|
||||
fn stack_id() -> NextcloudStackId {
|
||||
555.into()
|
||||
}
|
||||
|
||||
#[fixture]
|
||||
fn limiter() -> RateLimit {
|
||||
RateLimit::new("test", 100, 0.0, Instant::now())
|
||||
}
|
||||
|
||||
#[fixture]
|
||||
fn trello_stack() -> TrelloList {
|
||||
TrelloList {
|
||||
id: s!("trello-list-id").into(),
|
||||
name: s!("new-list-name").into(),
|
||||
pos: TrelloListPosition(3),
|
||||
}
|
||||
}
|
||||
|
||||
#[rstest::rstest]
|
||||
#[test_log::test(tokio::test(flavor = "multi_thread", worker_threads = 1))]
|
||||
async fn test_create_card_with_description_label_and_attachment(
|
||||
ctx_fs: (FullCtx, TempFileSystem),
|
||||
trello_stack: TrelloList,
|
||||
board_id: NextcloudBoardId,
|
||||
limiter: RateLimit,
|
||||
) {
|
||||
let (mut ctx, _temp_fs) = ctx_fs;
|
||||
|
||||
//given
|
||||
{
|
||||
let mock_net = MockNet::try_from(ctx.net.clone()).await.expect("mock net");
|
||||
|
||||
// LabelsActor
|
||||
given_nextcloud_get_labels_for_board(&mock_net);
|
||||
given_nextcloud_create_label(&mock_net);
|
||||
|
||||
// ImportStacksActor
|
||||
given_nextcloud_get_stacks_for_board(&mock_net);
|
||||
given_nextcloud_create_stack(&mock_net);
|
||||
given_nextcloud_get_stacks_for_board_with_new_stack(&mock_net);
|
||||
given_trello_get_stack(&mock_net);
|
||||
|
||||
// ImportCardActor
|
||||
given_nextcloud_create_card_with_description(&mock_net);
|
||||
given_trello_get_card_for_attachments_list(&mock_net);
|
||||
|
||||
// ImportLabelActor
|
||||
given_nextcloud_add_label_to_card(&mock_net);
|
||||
|
||||
// ImportAttachmentActor
|
||||
given_trello_get_details_of_attachment(&mock_net);
|
||||
given_trello_save_attachment(&mock_net);
|
||||
given_nextcloud_upload_attachment(&mock_net);
|
||||
|
||||
ctx.net = mock_net.into();
|
||||
}
|
||||
|
||||
let supervisor = spawn_in_thread(Supervisor);
|
||||
|
||||
// given_nextcloud_get_labels_for_board
|
||||
let labels_actor_ref = spawn_in_thread!(supervisor, LabelsActor::new(ctx.clone(), board_id));
|
||||
|
||||
let limiter = spawn_in_thread!(supervisor, RateLimitActor::new(limiter));
|
||||
|
||||
let trello_stack_name = trello_stack.name.clone();
|
||||
let trello_stacks: Vec<TrelloList> = vec![trello_stack];
|
||||
|
||||
//when
|
||||
// given_nextcloud_create_card_with_description
|
||||
// given_trello_get_card_for_attachments_list
|
||||
// spawns: label actor
|
||||
// given_nextcloud_create_label
|
||||
// given_nextcloud_add_label_to_card
|
||||
// spawns: attachment actor
|
||||
// given_trello_get_details_of_attachment
|
||||
// given_trello_save_attachment
|
||||
// given_nextcloud_upload_attachment
|
||||
let _stacks = spawn_in_thread!(
|
||||
supervisor,
|
||||
ImportStacksActor::new(
|
||||
ctx.clone(),
|
||||
trello_stacks,
|
||||
vec![trello_stack_name.into()],
|
||||
board_id,
|
||||
labels_actor_ref,
|
||||
limiter,
|
||||
)
|
||||
);
|
||||
|
||||
//then
|
||||
tokio::select! {
|
||||
_ = tokio::time::sleep(std::time::Duration::from_secs(1)) => {panic!("timeout")},
|
||||
_ = supervisor.wait_for_stop() => {}
|
||||
}
|
||||
|
||||
ctx.net.assert_no_unused_plans();
|
||||
}
|
||||
|
||||
#[rstest::rstest]
|
||||
#[test_log::test(tokio::test(flavor = "multi_thread", worker_threads = 1))]
|
||||
async fn test_create_card_without_description_label_or_attachment(
|
||||
ctx_fs: (FullCtx, TempFileSystem),
|
||||
trello_stack: TrelloList,
|
||||
board_id: NextcloudBoardId,
|
||||
limiter: RateLimit,
|
||||
) {
|
||||
let (mut ctx, _temp_fs) = ctx_fs;
|
||||
|
||||
//given
|
||||
{
|
||||
let mock_net = MockNet::try_from(ctx.net.clone()).await.expect("mock net");
|
||||
|
||||
// LabelsActor
|
||||
given_nextcloud_get_labels_for_board(&mock_net);
|
||||
|
||||
// ImportStacksActor
|
||||
given_nextcloud_get_stacks_for_board(&mock_net);
|
||||
given_nextcloud_create_stack(&mock_net);
|
||||
given_nextcloud_get_stacks_for_board_with_new_stack(&mock_net);
|
||||
given_trello_get_stack_with_card_with_no_description_or_label(&mock_net);
|
||||
|
||||
// ImportCardActor
|
||||
given_nextcloud_create_card_without_description(&mock_net);
|
||||
given_trello_get_card_for_empty_attachments_list(&mock_net);
|
||||
|
||||
ctx.net = mock_net.into();
|
||||
}
|
||||
|
||||
let supervisor = spawn_in_thread(Supervisor);
|
||||
|
||||
// requires: get_board (i.e. given_get_labels_for_board_from_nextcloud)
|
||||
// // nextcloud get labels for board: GET boards/{board_id}
|
||||
let labels_actor_ref = spawn_in_thread!(supervisor, LabelsActor::new(ctx.clone(), board_id));
|
||||
|
||||
let limiter = spawn_in_thread!(supervisor, RateLimitActor::new(limiter));
|
||||
|
||||
let trello_stack_name = trello_stack.name.clone();
|
||||
let trello_stacks: Vec<TrelloList> = vec![trello_stack];
|
||||
|
||||
//when
|
||||
let _stacks = spawn_in_thread!(
|
||||
supervisor,
|
||||
ImportStacksActor::new(
|
||||
ctx.clone(),
|
||||
trello_stacks,
|
||||
vec![trello_stack_name.into()],
|
||||
board_id,
|
||||
labels_actor_ref,
|
||||
limiter,
|
||||
)
|
||||
);
|
||||
|
||||
//then
|
||||
tokio::select! {
|
||||
_ = tokio::time::sleep(std::time::Duration::from_secs(1)) => {panic!("timeout")},
|
||||
_ = supervisor.wait_for_stop() => {}
|
||||
}
|
||||
|
||||
ctx.net.assert_no_unused_plans();
|
||||
}
|
||||
|
||||
fn given_nextcloud_upload_attachment(mock_net: &MockNet) {
|
||||
// upload attachment to Nextcloud
|
||||
mock_net
|
||||
.on()
|
||||
.post("https://nextcloud-hostname/index.php/apps/deck/api/v1.0/boards/444/stacks/555/cards/331/attachments")
|
||||
.respond(StatusCode::OK)
|
||||
.body(include_bytes!("../../tests/responses/nextcloud-attachment-add.json").as_slice())
|
||||
.expect("mock request create attachment");
|
||||
}
|
||||
|
||||
fn given_nextcloud_add_label_to_card(mock_net: &MockNet) {
|
||||
mock_net
|
||||
.on()
|
||||
.put("https://nextcloud-hostname/index.php/apps/deck/api/v1.0/boards/444/stacks/555/cards/331/assignLabel")
|
||||
.body(json!({
|
||||
"labelId": 54
|
||||
}).to_string())
|
||||
.respond(StatusCode::OK)
|
||||
.mock()
|
||||
.expect("mock request create attachment");
|
||||
}
|
||||
|
||||
fn given_trello_get_card_for_attachments_list(mock_net: &MockNet) {
|
||||
mock_net
|
||||
.on()
|
||||
.get("https://api.trello.com/1/cards/65ad94865aed24f70ecdcebb")
|
||||
.query("attachments", "true")
|
||||
.header("content-type", "application/json")
|
||||
.header("accept", "application/json")
|
||||
.respond(StatusCode::OK)
|
||||
.body(include_bytes!("../../tests/responses/trello-card-get.json").as_slice())
|
||||
.expect("mock request create attachment");
|
||||
}
|
||||
|
||||
fn given_trello_get_card_for_empty_attachments_list(mock_net: &MockNet) {
|
||||
mock_net
|
||||
.on()
|
||||
.get("https://api.trello.com/1/cards/65ad94865aed24f70ecdcebb")
|
||||
.query("attachments", "true")
|
||||
.header("content-type", "application/json")
|
||||
.header("accept", "application/json")
|
||||
.respond(StatusCode::OK)
|
||||
.body(
|
||||
include_bytes!("../../tests/responses/trello-card-get-no-description.json").as_slice(),
|
||||
)
|
||||
.expect("mock request create attachment");
|
||||
}
|
||||
|
||||
fn given_trello_save_attachment(mock_net: &MockNet) {
|
||||
// save attachment from Trello
|
||||
mock_net.on()
|
||||
.get("https://trello.com/1/cards/65ad94865aed24f70ecdcebb/attachments/65ad94875aed24f70ecdd037/download/Backlog.png")
|
||||
.respond(StatusCode::OK)
|
||||
.body(include_bytes!("../../tests/responses/trello-attachment-save.png").as_slice())
|
||||
.expect("mock save attachment");
|
||||
}
|
||||
|
||||
fn given_trello_get_details_of_attachment(mock_net: &MockNet) {
|
||||
// get details of attachment from Trello
|
||||
mock_net
|
||||
.on()
|
||||
.get("https://api.trello.com/1/cards/65ad94865aed24f70ecdcebb/attachments/65ad94875aed24f70ecdd037")
|
||||
.respond(StatusCode::OK)
|
||||
.body(include_bytes!("../../tests/responses/trello-attachment-get.json").as_slice())
|
||||
.expect("mock request attachment");
|
||||
}
|
||||
|
||||
fn given_nextcloud_get_labels_for_board(mock_net: &MockNet) {
|
||||
// get labels for the board from nextcloud
|
||||
mock_net
|
||||
.on()
|
||||
.get("https://nextcloud-hostname/index.php/apps/deck/api/v1.0/boards/444")
|
||||
.respond(StatusCode::OK)
|
||||
.body(include_bytes!("../../tests/responses/nextcloud-board-labels.json").as_slice())
|
||||
.expect("mock request board");
|
||||
}
|
||||
|
||||
fn given_nextcloud_create_card_with_description(mock_net: &MockNet) {
|
||||
// create card in Nextcloud
|
||||
mock_net
|
||||
.on()
|
||||
.post("https://nextcloud-hostname/index.php/apps/deck/api/v1.0/boards/444/stacks/555/cards")
|
||||
.body(
|
||||
json!({
|
||||
"description": "A list of the things we think we want to do, maybe not quite ready for work, but high likelihood of being worked on.\n\nThis is the staging area where specs should get fleshed out.\n\nNo limit on the list size, but we should reconsider if it gets long.",
|
||||
"title": "Backlog",
|
||||
}) // TODO: (#10) include card 'order' from trello 'pos'
|
||||
.to_string(),
|
||||
)
|
||||
.respond(StatusCode::OK)
|
||||
.body(include_bytes!("../../tests/responses/nextcloud-card-create.json").as_slice())
|
||||
.expect("mock request create card");
|
||||
}
|
||||
|
||||
fn given_nextcloud_create_card_without_description(mock_net: &MockNet) {
|
||||
// create card in Nextcloud
|
||||
mock_net
|
||||
.on()
|
||||
.post("https://nextcloud-hostname/index.php/apps/deck/api/v1.0/boards/444/stacks/555/cards")
|
||||
.body(
|
||||
json!({
|
||||
// "description": "trello-desc",
|
||||
"title": "Backlog",
|
||||
}) // TODO: (#10) include card 'order' from trello 'pos'
|
||||
.to_string(),
|
||||
)
|
||||
.respond(StatusCode::OK)
|
||||
.body(include_bytes!("../../tests/responses/nextcloud-card-create.json").as_slice())
|
||||
.expect("mock request create card");
|
||||
}
|
||||
|
||||
fn given_nextcloud_create_label(mock_net: &MockNet) {
|
||||
// create card in Nextcloud
|
||||
mock_net
|
||||
.on()
|
||||
.post("https://nextcloud-hostname/index.php/apps/deck/api/v1.0/boards/444/labels")
|
||||
.body(
|
||||
json!({
|
||||
"title": "Green",
|
||||
"color": "00ff00", // from green
|
||||
})
|
||||
.to_string(),
|
||||
)
|
||||
.respond(StatusCode::OK)
|
||||
.body(include_bytes!("../../tests/responses/nextcloud-board-create-label.json").as_slice())
|
||||
.expect("mock request create label");
|
||||
}
|
||||
|
||||
fn given_nextcloud_get_stacks_for_board(mock_net: &MockNet) {
|
||||
mock_net
|
||||
.on()
|
||||
.get("https://nextcloud-hostname/index.php/apps/deck/api/v1.0/boards/444/stacks")
|
||||
.respond(StatusCode::OK)
|
||||
.body(include_bytes!("../../tests/responses/nextcloud-board-get.json").as_slice())
|
||||
.expect("mock request get stacks");
|
||||
}
|
||||
|
||||
fn given_nextcloud_get_stacks_for_board_with_new_stack(mock_net: &MockNet) {
|
||||
mock_net
|
||||
.on()
|
||||
.get("https://nextcloud-hostname/index.php/apps/deck/api/v1.0/boards/444/stacks")
|
||||
.respond(StatusCode::OK)
|
||||
.body(
|
||||
include_bytes!("../../tests/responses/nextcloud-board-get-with-new-stack.json")
|
||||
.as_slice(),
|
||||
)
|
||||
.expect("mock request get stacks");
|
||||
}
|
||||
|
||||
fn given_nextcloud_create_stack(mock_net: &MockNet) {
|
||||
//
|
||||
mock_net
|
||||
.on()
|
||||
.post("https://nextcloud-hostname/index.php/apps/deck/api/v1.0/boards/444/stacks")
|
||||
.respond(StatusCode::OK)
|
||||
.body(include_bytes!("../../tests/responses/nextcloud-stack-create.json").as_slice())
|
||||
.expect("mock request create stack");
|
||||
}
|
||||
|
||||
fn given_trello_get_stack(mock_net: &MockNet) {
|
||||
mock_net
|
||||
.on()
|
||||
.get("https://api.trello.com/1/lists/trello-list-id/cards")
|
||||
.respond(StatusCode::OK)
|
||||
.body(include_bytes!("../../tests/responses/trello-list-get.json").as_slice())
|
||||
.expect("mock get stack");
|
||||
}
|
||||
|
||||
fn given_trello_get_stack_with_card_with_no_description_or_label(mock_net: &MockNet) {
|
||||
mock_net
|
||||
.on()
|
||||
.get("https://api.trello.com/1/lists/trello-list-id/cards")
|
||||
.respond(StatusCode::OK)
|
||||
.body(
|
||||
include_bytes!("../../tests/responses/trello-list-get-no-desc-or-label.json")
|
||||
.as_slice(),
|
||||
)
|
||||
.expect("mock get stack");
|
||||
}
|
|
@ -45,10 +45,7 @@ fn ctx_path() -> (FullCtx, PathBuf, TempFileSystem) {
|
|||
"{hostname}/index.php/apps/deck/api/v1.0/boards/{board_id}/stacks/{stack_id}/cards/{card_id}/attachments",
|
||||
))
|
||||
.respond(StatusCode::OK)
|
||||
.body(serde_json::to_string(&Attachment {
|
||||
id: 102,
|
||||
attachment_type: "file".to_string(),
|
||||
}).expect("json attachment"))
|
||||
.body(include_bytes!("../../../tests/responses/nextcloud-attachment-add.json").as_slice())
|
||||
.expect("mock request");
|
||||
|
||||
(
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
{"id":102,"type":"file"}
|
||||
{
|
||||
"foo": "nextcloud-attachment-add.json",
|
||||
"id": 102,
|
||||
"type": "file"
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"foo": "nextcloud-board-create-label.json",
|
||||
"id": 54,
|
||||
"title": "my green label",
|
||||
"color": "31CC7C",
|
||||
|
|
301
src/tests/responses/nextcloud-board-get-with-new-stack.json
Normal file
301
src/tests/responses/nextcloud-board-get-with-new-stack.json
Normal file
|
@ -0,0 +1,301 @@
|
|||
[
|
||||
{
|
||||
"foo": "nextcloud-board-get-with-new-stack.json",
|
||||
"id": 555,
|
||||
"title": "new-list-name",
|
||||
"boardId": 1,
|
||||
"deletedAt": 0,
|
||||
"lastModified": 1733515991,
|
||||
"cards": [],
|
||||
"order": 4,
|
||||
"ETag": "fda386b3b247d7b4bd8917e19d38c01b"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Done",
|
||||
"boardId": 1,
|
||||
"deletedAt": 0,
|
||||
"lastModified": 1733515991,
|
||||
"cards": [
|
||||
{
|
||||
"id": 322,
|
||||
"title": "Lunch: Soup & Toast",
|
||||
"description": "",
|
||||
"stackId": 3,
|
||||
"type": "plain",
|
||||
"lastModified": 1733515991,
|
||||
"lastEditor": null,
|
||||
"createdAt": 1733043472,
|
||||
"labels": [
|
||||
{
|
||||
"id": 4,
|
||||
"title": "Later",
|
||||
"color": "F1DB50",
|
||||
"boardId": 1,
|
||||
"cardId": 322,
|
||||
"lastModified": 1670965629,
|
||||
"ETag": "983f87848dc9c18d0aee63e7ee0fc83f"
|
||||
}
|
||||
],
|
||||
"assignedUsers": [
|
||||
{
|
||||
"id": 25,
|
||||
"participant": {
|
||||
"primaryKey": "pcampbell",
|
||||
"uid": "pcampbell",
|
||||
"displayname": "Paul Campbell",
|
||||
"type": 0
|
||||
},
|
||||
"cardId": 322,
|
||||
"type": 0
|
||||
}
|
||||
],
|
||||
"attachments": null,
|
||||
"attachmentCount": 0,
|
||||
"owner": {
|
||||
"primaryKey": "pcampbell",
|
||||
"uid": "pcampbell",
|
||||
"displayname": "Paul Campbell",
|
||||
"type": 0
|
||||
},
|
||||
"order": 0,
|
||||
"archived": false,
|
||||
"done": null,
|
||||
"duedate": null,
|
||||
"deletedAt": 0,
|
||||
"commentsUnread": 0,
|
||||
"commentsCount": 0,
|
||||
"ETag": "dda386b3b247d7b4bd8917e19d38c01b",
|
||||
"overdue": 0
|
||||
}
|
||||
],
|
||||
"order": 2,
|
||||
"ETag": "dda386b3b247d7b4bd8917e19d38c01b"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Doing",
|
||||
"boardId": 1,
|
||||
"deletedAt": 0,
|
||||
"lastModified": 1733695323,
|
||||
"cards": [
|
||||
{
|
||||
"id": 319,
|
||||
"title": "That",
|
||||
"description": "",
|
||||
"stackId": 2,
|
||||
"type": "plain",
|
||||
"lastModified": 1733335979,
|
||||
"lastEditor": null,
|
||||
"createdAt": 1732610551,
|
||||
"labels": [],
|
||||
"assignedUsers": [],
|
||||
"attachments": null,
|
||||
"attachmentCount": 1,
|
||||
"owner": {
|
||||
"primaryKey": "pcampbell",
|
||||
"uid": "pcampbell",
|
||||
"displayname": "Paul Campbell",
|
||||
"type": 0
|
||||
},
|
||||
"order": 0,
|
||||
"archived": false,
|
||||
"done": null,
|
||||
"duedate": null,
|
||||
"deletedAt": 0,
|
||||
"commentsUnread": 0,
|
||||
"commentsCount": 0,
|
||||
"ETag": "79aeb703494e67736cc66b35053d258d",
|
||||
"overdue": 0
|
||||
},
|
||||
{
|
||||
"id": 323,
|
||||
"title": "Second lunch: Poached Egg & Toasted Muffin",
|
||||
"description": "",
|
||||
"stackId": 2,
|
||||
"type": "plain",
|
||||
"lastModified": 1733695323,
|
||||
"lastEditor": null,
|
||||
"createdAt": 1733043481,
|
||||
"labels": [],
|
||||
"assignedUsers": [
|
||||
{
|
||||
"id": 26,
|
||||
"participant": {
|
||||
"primaryKey": "pcampbell",
|
||||
"uid": "pcampbell",
|
||||
"displayname": "Paul Campbell",
|
||||
"type": 0
|
||||
},
|
||||
"cardId": 323,
|
||||
"type": 0
|
||||
}
|
||||
],
|
||||
"attachments": null,
|
||||
"attachmentCount": 0,
|
||||
"owner": {
|
||||
"primaryKey": "pcampbell",
|
||||
"uid": "pcampbell",
|
||||
"displayname": "Paul Campbell",
|
||||
"type": 0
|
||||
},
|
||||
"order": 1,
|
||||
"archived": false,
|
||||
"done": null,
|
||||
"duedate": null,
|
||||
"deletedAt": 0,
|
||||
"commentsUnread": 0,
|
||||
"commentsCount": 0,
|
||||
"ETag": "9de45fc7d68507f1eaef462e90e6414c",
|
||||
"overdue": 0
|
||||
}
|
||||
],
|
||||
"order": 1,
|
||||
"ETag": "9de45fc7d68507f1eaef462e90e6414c"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"title": "To do",
|
||||
"boardId": 1,
|
||||
"deletedAt": 0,
|
||||
"lastModified": 1734115321,
|
||||
"cards": [
|
||||
{
|
||||
"id": 318,
|
||||
"title": "This",
|
||||
"description": "",
|
||||
"stackId": 1,
|
||||
"type": "plain",
|
||||
"lastModified": 1733049748,
|
||||
"lastEditor": null,
|
||||
"createdAt": 1732610548,
|
||||
"labels": [],
|
||||
"assignedUsers": [],
|
||||
"attachments": null,
|
||||
"attachmentCount": 1,
|
||||
"owner": {
|
||||
"primaryKey": "pcampbell",
|
||||
"uid": "pcampbell",
|
||||
"displayname": "Paul Campbell",
|
||||
"type": 0
|
||||
},
|
||||
"order": 0,
|
||||
"archived": false,
|
||||
"done": null,
|
||||
"duedate": null,
|
||||
"deletedAt": 0,
|
||||
"commentsUnread": 0,
|
||||
"commentsCount": 0,
|
||||
"ETag": "e5007451d88799e3e3d3581cbcb30210",
|
||||
"overdue": 0
|
||||
},
|
||||
{
|
||||
"id": 321,
|
||||
"title": "Breakfast: Cereal",
|
||||
"description": "",
|
||||
"stackId": 1,
|
||||
"type": "plain",
|
||||
"lastModified": 1734115321,
|
||||
"lastEditor": null,
|
||||
"createdAt": 1733043461,
|
||||
"labels": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Finished",
|
||||
"color": "31CC7C",
|
||||
"boardId": 1,
|
||||
"cardId": 321,
|
||||
"lastModified": 1670965629,
|
||||
"ETag": "983f87848dc9c18d0aee63e7ee0fc83f"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Finished",
|
||||
"color": "31CC7C",
|
||||
"boardId": 1,
|
||||
"cardId": 321,
|
||||
"lastModified": 1670965629,
|
||||
"ETag": "983f87848dc9c18d0aee63e7ee0fc83f"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Finished",
|
||||
"color": "31CC7C",
|
||||
"boardId": 1,
|
||||
"cardId": 321,
|
||||
"lastModified": 1670965629,
|
||||
"ETag": "983f87848dc9c18d0aee63e7ee0fc83f"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "To review",
|
||||
"color": "317CCC",
|
||||
"boardId": 1,
|
||||
"cardId": 321,
|
||||
"lastModified": 1670965629,
|
||||
"ETag": "983f87848dc9c18d0aee63e7ee0fc83f"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "To review",
|
||||
"color": "317CCC",
|
||||
"boardId": 1,
|
||||
"cardId": 321,
|
||||
"lastModified": 1670965629,
|
||||
"ETag": "983f87848dc9c18d0aee63e7ee0fc83f"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Action needed",
|
||||
"color": "FF7A66",
|
||||
"boardId": 1,
|
||||
"cardId": 321,
|
||||
"lastModified": 1670965629,
|
||||
"ETag": "983f87848dc9c18d0aee63e7ee0fc83f"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"title": "Later",
|
||||
"color": "F1DB50",
|
||||
"boardId": 1,
|
||||
"cardId": 321,
|
||||
"lastModified": 1670965629,
|
||||
"ETag": "983f87848dc9c18d0aee63e7ee0fc83f"
|
||||
}
|
||||
],
|
||||
"assignedUsers": [
|
||||
{
|
||||
"id": 24,
|
||||
"participant": {
|
||||
"primaryKey": "pcampbell",
|
||||
"uid": "pcampbell",
|
||||
"displayname": "Paul Campbell",
|
||||
"type": 0
|
||||
},
|
||||
"cardId": 321,
|
||||
"type": 0
|
||||
}
|
||||
],
|
||||
"attachments": null,
|
||||
"attachmentCount": 0,
|
||||
"owner": {
|
||||
"primaryKey": "pcampbell",
|
||||
"uid": "pcampbell",
|
||||
"displayname": "Paul Campbell",
|
||||
"type": 0
|
||||
},
|
||||
"order": 1,
|
||||
"archived": false,
|
||||
"done": null,
|
||||
"duedate": null,
|
||||
"deletedAt": 0,
|
||||
"commentsUnread": 0,
|
||||
"commentsCount": 0,
|
||||
"ETag": "9acdd42135c0347968891d2a073b87be",
|
||||
"overdue": 0
|
||||
}
|
||||
],
|
||||
"order": 0,
|
||||
"ETag": "9acdd42135c0347968891d2a073b87be"
|
||||
}
|
||||
]
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "nextcloud-board-get.json",
|
||||
"id": 3,
|
||||
"title": "Done",
|
||||
"boardId": 1,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"foo": "nextcloud-board-labels.json",
|
||||
"id": 1,
|
||||
"title": "Personal Board",
|
||||
"owner": {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "nextcloud-board-list.json",
|
||||
"id": 1,
|
||||
"title": "Personal Board",
|
||||
"owner": {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "nextcloud-boards.json",
|
||||
"id": 1,
|
||||
"title": "Personal Board",
|
||||
"owner": {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"foo": "nextcloud-card-create.json",
|
||||
"id": 331,
|
||||
"title": "my new card",
|
||||
"description": "my new description",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"foo": "nextcloud-card-get.json",
|
||||
"id": 321,
|
||||
"title": "Breakfast: Cereal",
|
||||
"description": "",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "nextcloud-deck-get.json",
|
||||
"id": 1,
|
||||
"title": "Personal Board",
|
||||
"owner": {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"foo": "nextcloud-stack-create.json",
|
||||
"id": 30,
|
||||
"title": "Incoming",
|
||||
"boardId": 1,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"foo": "nextcloud-stack-get.json",
|
||||
"id": 3,
|
||||
"title": "Done",
|
||||
"boardId": 1,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "nextcloud-stack-list-2.json",
|
||||
"id": 1,
|
||||
"title": "To do",
|
||||
"boardId": 1,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "nextcloud-stack-list.json",
|
||||
"id": 3,
|
||||
"title": "Done",
|
||||
"boardId": 1,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"foo": "trello-attachment-get.json",
|
||||
"id": "65ad94875aed24f70ecdd037",
|
||||
"bytes": 184198,
|
||||
"date": "2019-01-02T22:47:17.325Z",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"foo": "trello-board-get.json",
|
||||
"id": "65ad94865aed24f70ecdce4b",
|
||||
"name": "Tasyn Kanban",
|
||||
"desc": "Use this simple Kanban template to keep the engineering team on the same page and moving through work fluidly. \n\n1. Break down the roadmap by adding tasks as cards to the **Backlog** list. \n\n2. Move the cards one-by-one through **Design** as they becomes more fleshed out. *Pro tip:* You can enable Power-ups for your favorite design tools like [Figma](https://trello.com/power-ups/59b2e7611e6ece0b35eac16a/figma) or [Invision](https://trello.com/power-ups/596f2cb2d279152540b2bb31), in order to easily link and view designs without switching context.\n\n3. When a card is fully specced out and designs are attached, move it to **To Do** for engineers to pick up. \n\n4. Engineers move cards to **Doing** and assign themselves to the cards, so the whole team stays informed of who is working on what.\n\n5. Cards then move through **Code Review** when they're ready for a second set of eyes. The team can set a **List Limit** (with the List Limit Power-up) on the number of cards in Code Review, as a visual indicator for when the team needs to prioritize reviews rather than picking up new work. \n\n6. Once cards move through **Testing** and eventually ship to production, move them to **Done** and celebrate!\n",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "trello-boards-list.json",
|
||||
"id": "5db72d5517a6135e166fd862",
|
||||
"nodeId": "ari:cloud:trello::board/workspace/60ae020570a89b46695aae66/5db72d5517a6135e166fd862",
|
||||
"name": "0 Business: Cossmass Infinities",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "trello-boards.json",
|
||||
"id": "5abbe4b7ddc1b351ef961414",
|
||||
"name": "Trello Platform Changes",
|
||||
"desc": "Track changes to Trello's Platform on this board.",
|
||||
|
|
67
src/tests/responses/trello-card-get-no-description.json
Normal file
67
src/tests/responses/trello-card-get-no-description.json
Normal file
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"foo": "trello-card-get-no-description.json",
|
||||
"id": "65ad94865aed24f70ecdced1",
|
||||
"badges": {
|
||||
"attachmentsByType": {
|
||||
"trello": {
|
||||
"board": 0,
|
||||
"card": 0
|
||||
}
|
||||
},
|
||||
"externalSource": null,
|
||||
"location": false,
|
||||
"votes": 0,
|
||||
"viewingMemberVoted": false,
|
||||
"subscribed": false,
|
||||
"fogbugz": "",
|
||||
"checkItems": 0,
|
||||
"checkItemsChecked": 0,
|
||||
"checkItemsEarliestDue": null,
|
||||
"comments": 0,
|
||||
"attachments": 0,
|
||||
"description": false,
|
||||
"due": null,
|
||||
"dueComplete": false,
|
||||
"start": null,
|
||||
"lastUpdatedByAi": false
|
||||
},
|
||||
"checkItemStates": [],
|
||||
"closed": false,
|
||||
"dueComplete": false,
|
||||
"dateLastActivity": "2024-12-25T08:40:22.054Z",
|
||||
"desc": "",
|
||||
"descData": null,
|
||||
"due": null,
|
||||
"dueReminder": null,
|
||||
"email": null,
|
||||
"idBoard": "65ad94865aed24f70ecdce4b",
|
||||
"idChecklists": [],
|
||||
"idList": "65ad94865aed24f70ecdce4c",
|
||||
"idMembers": [],
|
||||
"idMembersVoted": [],
|
||||
"idShort": 12,
|
||||
"idAttachmentCover": null,
|
||||
"labels": [],
|
||||
"idLabels": [],
|
||||
"manualCoverAttachment": false,
|
||||
"name": "Task - no description, labels or attachments",
|
||||
"pinned": false,
|
||||
"pos": 81920,
|
||||
"shortLink": "kqHXwwev",
|
||||
"shortUrl": "https://trello.com/c/kqHXwwev",
|
||||
"start": null,
|
||||
"subscribed": false,
|
||||
"url": "https://trello.com/c/kqHXwwev/12-task-no-description-labels-or-attachments",
|
||||
"cover": {
|
||||
"idAttachment": null,
|
||||
"color": null,
|
||||
"idUploadedBackground": null,
|
||||
"size": "normal",
|
||||
"brightness": "light",
|
||||
"idPlugin": null
|
||||
},
|
||||
"isTemplate": false,
|
||||
"cardRole": null,
|
||||
"mirrorSourceId": null,
|
||||
"attachments": []
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"foo": "trello-card-get.json",
|
||||
"id": "65ad94865aed24f70ecdcebb",
|
||||
"badges": {
|
||||
"attachmentsByType": {
|
||||
|
@ -12,7 +13,6 @@
|
|||
"votes": 0,
|
||||
"viewingMemberVoted": false,
|
||||
"subscribed": false,
|
||||
"lastUpdatedByAi": false,
|
||||
"fogbugz": "",
|
||||
"checkItems": 0,
|
||||
"checkItemsChecked": 0,
|
||||
|
@ -22,12 +22,13 @@
|
|||
"description": true,
|
||||
"due": null,
|
||||
"dueComplete": false,
|
||||
"start": null
|
||||
"start": null,
|
||||
"lastUpdatedByAi": false
|
||||
},
|
||||
"checkItemStates": [],
|
||||
"closed": false,
|
||||
"dueComplete": false,
|
||||
"dateLastActivity": "2024-01-21T22:02:47.582Z",
|
||||
"dateLastActivity": "2024-12-25T08:40:39.500Z",
|
||||
"desc": "A list of the things we think we want to do, maybe not quite ready for work, but high likelihood of being worked on.\n\nThis is the staging area where specs should get fleshed out.\n\nNo limit on the list size, but we should reconsider if it gets long.",
|
||||
"descData": null,
|
||||
"due": null,
|
||||
|
@ -40,17 +41,29 @@
|
|||
"idMembersVoted": [],
|
||||
"idShort": 1,
|
||||
"idAttachmentCover": "65ad94875aed24f70ecdd037",
|
||||
"labels": [],
|
||||
"idLabels": [],
|
||||
"labels": [
|
||||
{
|
||||
"id": "65ad94865aed24f70ecdcee2",
|
||||
"idBoard": "65ad94865aed24f70ecdce4b",
|
||||
"idOrganization": "60ae034415aa230ab2ef596d",
|
||||
"name": "Green",
|
||||
"nodeId": "ari:cloud:trello::label/workspace/60ae034415aa230ab2ef596d/65ad94865aed24f70ecdcee2",
|
||||
"color": "green",
|
||||
"uses": 1
|
||||
}
|
||||
],
|
||||
"idLabels": [
|
||||
"65ad94865aed24f70ecdcee2"
|
||||
],
|
||||
"manualCoverAttachment": false,
|
||||
"name": "Backlog",
|
||||
"name": "Task - with description, label and attachment",
|
||||
"pinned": false,
|
||||
"pos": 16384,
|
||||
"shortLink": "Z7CTyW2I",
|
||||
"shortUrl": "https://trello.com/c/Z7CTyW2I",
|
||||
"start": null,
|
||||
"subscribed": false,
|
||||
"url": "https://trello.com/c/Z7CTyW2I/1-backlog",
|
||||
"url": "https://trello.com/c/Z7CTyW2I/1-task-with-description-label-and-attachment",
|
||||
"cover": {
|
||||
"idAttachment": "65ad94875aed24f70ecdd037",
|
||||
"color": null,
|
||||
|
|
67
src/tests/responses/trello-list-get-no-desc-or-label.json
Normal file
67
src/tests/responses/trello-list-get-no-desc-or-label.json
Normal file
|
@ -0,0 +1,67 @@
|
|||
[
|
||||
{
|
||||
"foo": "trello-list-get-no-desc-or-label.json",
|
||||
"id": "65ad94865aed24f70ecdcebb",
|
||||
"badges": {
|
||||
"attachmentsByType": {
|
||||
"trello": {
|
||||
"board": 0,
|
||||
"card": 0
|
||||
}
|
||||
},
|
||||
"externalSource": null,
|
||||
"location": false,
|
||||
"votes": 0,
|
||||
"viewingMemberVoted": false,
|
||||
"subscribed": false,
|
||||
"fogbugz": "",
|
||||
"checkItems": 0,
|
||||
"checkItemsChecked": 0,
|
||||
"checkItemsEarliestDue": null,
|
||||
"comments": 0,
|
||||
"attachments": 1,
|
||||
"description": true,
|
||||
"due": null,
|
||||
"dueComplete": false,
|
||||
"start": null,
|
||||
"lastUpdatedByAi": false
|
||||
},
|
||||
"checkItemStates": [],
|
||||
"closed": false,
|
||||
"dueComplete": false,
|
||||
"dateLastActivity": "2024-01-21T22:02:47.582Z",
|
||||
"desc": "",
|
||||
"descData": null,
|
||||
"due": null,
|
||||
"dueReminder": null,
|
||||
"email": null,
|
||||
"idBoard": "65ad94865aed24f70ecdce4b",
|
||||
"idChecklists": [],
|
||||
"idList": "65ad94865aed24f70ecdce4c",
|
||||
"idMembers": [],
|
||||
"idMembersVoted": [],
|
||||
"idShort": 1,
|
||||
"idAttachmentCover": "65ad94875aed24f70ecdd037",
|
||||
"labels": [],
|
||||
"idLabels": [],
|
||||
"manualCoverAttachment": false,
|
||||
"name": "Backlog",
|
||||
"pinned": false,
|
||||
"pos": 16384,
|
||||
"shortLink": "Z7CTyW2I",
|
||||
"shortUrl": "https://trello.com/c/Z7CTyW2I",
|
||||
"start": null,
|
||||
"subscribed": false,
|
||||
"url": "https://trello.com/c/Z7CTyW2I/1-backlog",
|
||||
"cover": {
|
||||
"idAttachment": "65ad94875aed24f70ecdd037",
|
||||
"color": null,
|
||||
"idUploadedBackground": null,
|
||||
"size": "normal",
|
||||
"brightness": "light",
|
||||
"idPlugin": null
|
||||
},
|
||||
"isTemplate": false,
|
||||
"cardRole": null
|
||||
}
|
||||
]
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "trello-list-get.json",
|
||||
"id": "65ad94865aed24f70ecdcebb",
|
||||
"badges": {
|
||||
"attachmentsByType": {
|
||||
|
@ -41,7 +42,17 @@
|
|||
"idMembersVoted": [],
|
||||
"idShort": 1,
|
||||
"idAttachmentCover": "65ad94875aed24f70ecdd037",
|
||||
"labels": [],
|
||||
"labels": [
|
||||
{
|
||||
"id": "65ad94865aed24f70ecdcee2",
|
||||
"idBoard": "65ad94865aed24f70ecdce4b",
|
||||
"idOrganization": "60ae034415aa230ab2ef596d",
|
||||
"name": "Green",
|
||||
"nodeId": "ari:cloud:trello::label/workspace/60ae034415aa230ab2ef596d/65ad94865aed24f70ecdcee2",
|
||||
"color": "green",
|
||||
"uses": 1
|
||||
}
|
||||
],
|
||||
"idLabels": [],
|
||||
"manualCoverAttachment": false,
|
||||
"name": "Backlog",
|
||||
|
@ -62,69 +73,5 @@
|
|||
},
|
||||
"isTemplate": false,
|
||||
"cardRole": null
|
||||
},
|
||||
{
|
||||
"id": "65ad94865aed24f70ecdced1",
|
||||
"badges": {
|
||||
"attachmentsByType": {
|
||||
"trello": {
|
||||
"board": 0,
|
||||
"card": 0
|
||||
}
|
||||
},
|
||||
"externalSource": null,
|
||||
"location": false,
|
||||
"votes": 0,
|
||||
"viewingMemberVoted": false,
|
||||
"subscribed": false,
|
||||
"fogbugz": "",
|
||||
"checkItems": 0,
|
||||
"checkItemsChecked": 0,
|
||||
"checkItemsEarliestDue": null,
|
||||
"comments": 0,
|
||||
"attachments": 0,
|
||||
"description": false,
|
||||
"due": null,
|
||||
"dueComplete": false,
|
||||
"start": null,
|
||||
"lastUpdatedByAi": false
|
||||
},
|
||||
"checkItemStates": [],
|
||||
"closed": false,
|
||||
"dueComplete": false,
|
||||
"dateLastActivity": "2024-01-21T22:02:47.112Z",
|
||||
"desc": "",
|
||||
"descData": null,
|
||||
"due": null,
|
||||
"dueReminder": null,
|
||||
"email": null,
|
||||
"idBoard": "65ad94865aed24f70ecdce4b",
|
||||
"idChecklists": [],
|
||||
"idList": "65ad94865aed24f70ecdce4c",
|
||||
"idMembers": [],
|
||||
"idMembersVoted": [],
|
||||
"idShort": 12,
|
||||
"idAttachmentCover": null,
|
||||
"labels": [],
|
||||
"idLabels": [],
|
||||
"manualCoverAttachment": false,
|
||||
"name": "[Example task]",
|
||||
"pinned": false,
|
||||
"pos": 81920,
|
||||
"shortLink": "kqHXwwev",
|
||||
"shortUrl": "https://trello.com/c/kqHXwwev",
|
||||
"start": null,
|
||||
"subscribed": false,
|
||||
"url": "https://trello.com/c/kqHXwwev/12-example-task",
|
||||
"cover": {
|
||||
"idAttachment": null,
|
||||
"color": null,
|
||||
"idUploadedBackground": null,
|
||||
"size": "normal",
|
||||
"brightness": "light",
|
||||
"idPlugin": null
|
||||
},
|
||||
"isTemplate": false,
|
||||
"cardRole": null
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "trello-member-get.json",
|
||||
"id": "5db72d5517a6135e166fd862",
|
||||
"nodeId": "ari:cloud:trello::board/workspace/60ae020570a89b46695aae66/5db72d5517a6135e166fd862",
|
||||
"name": "0 Business: Cossmass Infinities",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "trello-stack-get.json",
|
||||
"id": "674e03794ef7340ece3ebb5f",
|
||||
"badges": {
|
||||
"attachmentsByType": {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[
|
||||
{
|
||||
"foo": "trello-stack-list.json",
|
||||
"id": "65ad94865aed24f70ecdce4c",
|
||||
"name": "Backlog",
|
||||
"closed": false,
|
||||
|
|
Loading…
Reference in a new issue