1use axum::{
2 response::{IntoResponse, Response},
3 Json,
4};
5use serde::Serialize;
6
7#[derive(Debug, Clone, Serialize)]
34pub struct ListResponse<T: Serialize> {
35 pub data: Vec<T>,
37 pub total: i64,
39 pub limit: u32,
41 pub offset: u32,
43}
44
45impl<T: Serialize> IntoResponse for ListResponse<T> {
46 fn into_response(self) -> Response {
47 Json(self).into_response()
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54 use serde_json::json;
55
56 #[derive(Serialize)]
57 struct Item {
58 id: String,
59 }
60
61 #[test]
62 fn serializes_fields_correctly() {
63 let resp = ListResponse {
64 data: vec![Item { id: "abc".into() }],
65 total: 10,
66 limit: 25,
67 offset: 0,
68 };
69 let v = serde_json::to_value(&resp).unwrap();
70 assert_eq!(v["total"], 10);
71 assert_eq!(v["limit"], 25);
72 assert_eq!(v["offset"], 0);
73 assert_eq!(v["data"][0]["id"], "abc");
74 }
75
76 #[test]
77 fn empty_data_serializes() {
78 let resp: ListResponse<Item> = ListResponse {
79 data: vec![],
80 total: 0,
81 limit: 50,
82 offset: 0,
83 };
84 let v = serde_json::to_value(&resp).unwrap();
85 assert_eq!(v["data"], json!([]));
86 assert_eq!(v["total"], 0);
87 }
88
89 #[test]
90 fn offset_pagination_fields() {
91 let resp: ListResponse<Item> = ListResponse {
92 data: vec![],
93 total: 100,
94 limit: 10,
95 offset: 30,
96 };
97 let v = serde_json::to_value(&resp).unwrap();
98 assert_eq!(v["limit"], 10);
99 assert_eq!(v["offset"], 30);
100 }
101}