dimescheduler 0.1.0

Official Rust client library for the Dime.Scheduler API.
Documentation
use serde_json::json;
use wiremock::matchers::{body_json, method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};

use crate::transport::Transport;
use crate::{entities, DimeSchedulerClient};

pub(crate) async fn client(server: &MockServer) -> DimeSchedulerClient {
    DimeSchedulerClient::from_transport(Transport::new(server.uri(), "secret-key".into()))
}

fn ok() -> ResponseTemplate {
    ResponseTemplate::new(200)
        .set_body_json(json!({ "success": true, "message": "ok", "status": 200 }))
}

#[tokio::test]
async fn create_posts_single_entity() {
    let server = MockServer::start().await;
    Mock::given(method("POST"))
        .and(path("/category"))
        .and(body_json(
            json!({ "name": "INSTALL", "displayName": "Install", "color": "#22d3ee" }),
        ))
        .respond_with(ok())
        .expect(1)
        .mount(&server)
        .await;

    let cat = entities::Category {
        name: "INSTALL".into(),
        display_name: "Install".into(),
        color: "#22d3ee".into(),
    };
    let resp = client(&server).await.categories.create(&cat).await.unwrap();
    assert_eq!(resp.success, Some(true));
}

#[tokio::test]
async fn many_variants_send_arrays_with_put_and_delete() {
    let server = MockServer::start().await;
    Mock::given(method("PUT"))
        .and(path("/tag"))
        .and(body_json(json!([{ "code": "A" }, { "code": "B" }])))
        .respond_with(ok())
        .expect(1)
        .mount(&server)
        .await;
    Mock::given(method("DELETE"))
        .and(path("/tag"))
        .and(body_json(json!([{ "code": "A" }])))
        .respond_with(ok())
        .expect(1)
        .mount(&server)
        .await;

    let c = client(&server).await;
    let a = entities::Tag {
        code: "A".into(),
        ..Default::default()
    };
    let b = entities::Tag {
        code: "B".into(),
        ..Default::default()
    };
    c.tags.update_many(&[a.clone(), b]).await.unwrap();
    c.tags.delete_many(&[a]).await.unwrap();
}

#[tokio::test]
async fn get_all_decodes_dto_list() {
    let server = MockServer::start().await;
    Mock::given(method("GET"))
        .and(path("/tag"))
        .respond_with(
            ResponseTemplate::new(200)
                .set_body_json(json!([{ "id": 1, "code": "VIP", "hiddenToUser": false }])),
        )
        .mount(&server)
        .await;

    let tags = client(&server).await.tags.get_all().await.unwrap();
    assert_eq!(tags.len(), 1);
    assert_eq!(tags[0].code.as_deref(), Some("VIP"));
}

#[tokio::test]
async fn every_crud_accessor_is_on_its_route() {
    let server = MockServer::start().await;
    let c = client(&server).await;
    let routes = [
        c.action_uris.route(),
        c.appointment_categories.route(),
        c.appointment_contents.route(),
        c.appointment_containers.route(),
        c.appointment_field_values.route(),
        c.appointment_importances.route(),
        c.appointment_locked.route(),
        c.appointment_planning_quantities.route(),
        c.appointment_time_markers.route(),
        c.appointment_uris.route(),
        c.assignments.route(),
        c.captions.route(),
        c.categories.route(),
        c.containers.route(),
        c.filter_groups.route(),
        c.filter_values.route(),
        c.pins.route(),
        c.project_members.route(),
        c.resources.route(),
        c.resource_calendars.route(),
        c.resource_certificates.route(),
        c.resource_filter_values.route(),
        c.resource_gps_trackings.route(),
        c.resource_uris.route(),
        c.tags.route(),
        c.task_containers.route(),
        c.task_dependencies.route(),
        c.task_filter_values.route(),
        c.task_locked.route(),
        c.task_uris.route(),
        c.time_markers.route(),
    ];
    assert_eq!(
        routes,
        [
            "/actionUri",
            "/appointmentCategory",
            "/appointmentcontent",
            "/appointmentContainer",
            "/appointmentFieldValue",
            "/appointmentImportance",
            "/appointmentLocked",
            "/appointmentPlanningQuantity",
            "/appointmentTimeMarker",
            "/appointmentUri",
            "/assignment",
            "/caption",
            "/category",
            "/container",
            "/filterGroup",
            "/filterValue",
            "/pin",
            "/projectMember",
            "/resource",
            "/resourceCalendar",
            "/resourceCertificate",
            "/resourceFilterValue",
            "/resourceGpsTracking",
            "/resourceUri",
            "/tag",
            "/taskContainer",
            "/taskDependency",
            "/taskFilterValue",
            "/taskLocked",
            "/taskUri",
            "/timeMarker",
        ]
    );
}