gitee-cli-rs 0.2.2

A gh-like command-line client for Gitee
Documentation
use gitee_cli_rs::api::client::Client;
use serde::Deserialize;

#[derive(Debug, Deserialize, PartialEq, Eq)]
struct PageItem {
    id: u32,
}

fn client(server: &mockito::ServerGuard) -> Client {
    Client::new(format!("{}/api/v5", server.url()), "fake-token".into())
}

fn api_path(path: &str) -> String {
    format!("/api/v5{path}")
}

fn page_items(count: usize) -> String {
    let items: Vec<String> = (0..count)
        .map(|i| format!(r#"{{"id":{i}}}"#))
        .collect();
    format!("[{}]", items.join(","))
}

#[test]
fn get_paged_fetches_full_page_then_empty_page() {
    let mut server = mockito::Server::new();
    let path = "/repos/owner/repo/issues";

    let page1 = server
        .mock("GET", api_path(path).as_str())
        .match_query(mockito::Matcher::AllOf(vec![
            mockito::Matcher::UrlEncoded("page".into(), "1".into()),
            mockito::Matcher::UrlEncoded("per_page".into(), "100".into()),
        ]))
        .with_status(200)
        .with_header("content-type", "application/json")
        .with_body(page_items(100))
        .create();

    let page2 = server
        .mock("GET", api_path(path).as_str())
        .match_query(mockito::Matcher::AllOf(vec![
            mockito::Matcher::UrlEncoded("page".into(), "2".into()),
            mockito::Matcher::UrlEncoded("per_page".into(), "100".into()),
        ]))
        .with_status(200)
        .with_header("content-type", "application/json")
        .with_body("[]")
        .create();

    let client = client(&server);
    let items: Vec<PageItem> = client
        .get_paged(path, &[], 200)
        .expect("paged fetch should succeed");

    page1.assert();
    page2.assert();
    assert_eq!(items.len(), 100);
    assert_eq!(items[0], PageItem { id: 0 });
    assert_eq!(items[99], PageItem { id: 99 });
}

#[test]
fn get_paged_limit_truncates_results() {
    let mut server = mockito::Server::new();
    let path = "/repos/owner/repo/issues";

    let page1 = server
        .mock("GET", api_path(path).as_str())
        .match_query(mockito::Matcher::AllOf(vec![
            mockito::Matcher::UrlEncoded("page".into(), "1".into()),
            mockito::Matcher::UrlEncoded("per_page".into(), "100".into()),
        ]))
        .with_status(200)
        .with_header("content-type", "application/json")
        .with_body(page_items(100))
        .create();

    let client = client(&server);
    let items: Vec<PageItem> = client
        .get_paged(path, &[], 30)
        .expect("paged fetch should succeed");

    page1.assert();
    assert_eq!(items.len(), 30);
    assert_eq!(items[29], PageItem { id: 29 });
}

#[test]
fn get_paged_increments_page_query_param() {
    let mut server = mockito::Server::new();
    let path = "/repos/owner/repo/pulls";

    let page1 = server
        .mock("GET", api_path(path).as_str())
        .match_query(mockito::Matcher::AllOf(vec![
            mockito::Matcher::UrlEncoded("page".into(), "1".into()),
            mockito::Matcher::UrlEncoded("per_page".into(), "100".into()),
            mockito::Matcher::UrlEncoded("state".into(), "open".into()),
        ]))
        .with_status(200)
        .with_header("content-type", "application/json")
        .with_body(page_items(100))
        .create();

    let page2 = server
        .mock("GET", api_path(path).as_str())
        .match_query(mockito::Matcher::AllOf(vec![
            mockito::Matcher::UrlEncoded("page".into(), "2".into()),
            mockito::Matcher::UrlEncoded("per_page".into(), "100".into()),
            mockito::Matcher::UrlEncoded("state".into(), "open".into()),
        ]))
        .with_status(200)
        .with_header("content-type", "application/json")
        .with_body(r#"[{"id":100}]"#)
        .create();

    let client = client(&server);
    let items: Vec<PageItem> = client
        .get_paged(path, &[("state", "open")], 150)
        .expect("paged fetch should succeed");

    page1.assert();
    page2.assert();
    assert_eq!(items.len(), 101);
    assert_eq!(items[100], PageItem { id: 100 });
}