use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, Deserialize, PartialEq, Eq)] pub struct Issue { pub id: u64, pub number: u64, pub title: String, #[serde(default)] pub body: Option, } #[derive(Clone, Debug, Deserialize, PartialEq, Eq)] pub struct Comment { pub id: u64, pub body: String, #[serde(default)] pub user: Option, } #[derive(Clone, Debug, Deserialize, PartialEq, Eq)] pub struct CommentUser { pub login: String, } #[derive(Debug, Serialize, PartialEq, Eq)] pub struct CommentPayload { pub body: String, } #[derive(Debug, Serialize, PartialEq, Eq)] pub struct CreateIssuePayload { pub title: String, pub body: String, pub projects: Vec, } #[derive(Clone, Debug, Serialize, PartialEq, Eq)] pub struct EditIssuePayload { pub title: String, pub body: String, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct ColumnSpec { pub id: u64, pub title: String, } #[derive(Clone, Debug, Deserialize, PartialEq, Eq)] pub struct Project { pub id: u64, pub title: String, #[serde(default)] pub is_closed: bool, } #[derive(Clone, Debug, Deserialize, PartialEq, Eq)] pub struct ProjectColumn { pub id: u64, pub title: String, #[serde(default)] pub color: String, #[serde(default)] pub sorting: i8, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct ProjectBoard { pub project: Project, pub columns: Vec, pub issues_by_column: Vec>, } #[derive(Debug, Serialize, PartialEq, Eq)] pub struct MoveProjectIssuePayload { pub column_id: u64, #[serde(skip_serializing_if = "Option::is_none")] pub sorting: Option, } #[cfg(test)] mod tests { use super::*; #[test] fn deserializes_native_project_data_and_move_payload() { let project: Project = serde_json::from_value(serde_json::json!({ "id": 4, "title": "Kanban", "is_closed": false })) .expect("project JSON"); let column: ProjectColumn = serde_json::from_value(serde_json::json!({ "id": 9, "title": "Doing", "sorting": 1 })) .expect("column JSON"); let issue: Issue = serde_json::from_value(serde_json::json!({ "id": 70, "number": 7, "title": "Fix it" })) .expect("issue JSON"); let payload = MoveProjectIssuePayload { column_id: column.id, sorting: Some(3), }; assert_eq!(project.title, "Kanban"); assert_eq!(issue.id, 70); assert_eq!( serde_json::to_value(payload).expect("move payload"), serde_json::json!({"column_id": 9, "sorting": 3}) ); } #[test] fn serializes_issue_create_and_edit_payloads() { let create = CreateIssuePayload { title: "New issue".to_owned(), body: "Details".to_owned(), projects: vec![4], }; let edit = EditIssuePayload { title: "Updated".to_owned(), body: "Changed".to_owned(), }; assert_eq!( serde_json::to_value(create).expect("create payload"), serde_json::json!({"title": "New issue", "body": "Details", "projects": [4]}) ); assert_eq!( serde_json::to_value(edit).expect("edit payload"), serde_json::json!({"title": "Updated", "body": "Changed"}) ); } #[test] fn serializes_and_deserializes_comment_data() { let comment: Comment = serde_json::from_value(serde_json::json!({ "id": 9001, "body": "Investigating", "user": {"login": "alice"} })) .expect("comment JSON"); let payload = CommentPayload { body: "Resolved".to_owned(), }; assert_eq!(comment.id, 9001); assert_eq!(comment.user.expect("comment user").login, "alice"); assert_eq!( serde_json::to_value(payload).expect("comment payload"), serde_json::json!({"body": "Resolved"}) ); } }