use std::marker::PhantomData;
use super::EntityLink;
use crate::{EntityProperties, EntitySetEndpoint, ExpandQuery, SingletonEndpoint};
use chrono::{DateTime, FixedOffset};
use iso8601::Duration;
use odata_client_util::deserialize_with::Iso8601DurationDeserialize;
use serde::Deserialize;
use serde_with::serde_as;
use uuid::Uuid;
const TRIP_PIN_SERVICE_URL: &str = "https://services.odata.org/V4/TripPinService";
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct Person {
user_name: String,
first_name: String,
last_name: String,
#[serde(default)]
emails: Vec<String>,
#[serde(default)]
address_info: Vec<Location>,
gender: Option<PersonGender>,
concurrency: i64,
friends: Vec<EntityLink<Person>>,
trips: Vec<Trip>,
photo: Option<EntityLink<Photo>>,
}
impl EntityProperties for Person {
const EXPAND_QUERY: ExpandQuery =
ExpandQuery::Expand("Friends/$ref,Trips($expand=Photos/$ref,PlanItems),Photo/$ref");
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct Location {
address: String,
city: City,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct City {
country_region: String,
name: String,
region: String,
}
#[derive(Debug, Deserialize)]
enum PersonGender {
Male = 0,
Female = 1,
Unknown = 2,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct Trip {
trip_id: i32,
share_id: Option<Uuid>,
description: Option<String>,
name: String,
budget: f32,
starts_at: DateTime<FixedOffset>,
ends_at: DateTime<FixedOffset>,
tags: Vec<String>,
photos: Vec<EntityLink<Photo>>,
plan_items: Vec<PlanItem>,
}
impl EntityProperties for Trip {
const EXPAND_QUERY: ExpandQuery = ExpandQuery::Expand("Photos/$ref,PlanItems");
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct Photo {
id: i64,
name: Option<String>,
}
impl EntityProperties for Photo {
const EXPAND_QUERY: ExpandQuery = ExpandQuery::None;
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct PlanItem {
plan_item_id: i32,
confirmation_code: Option<String>,
starts_at: Option<DateTime<FixedOffset>>,
ends_at: Option<DateTime<FixedOffset>>,
#[serde_as(as = "Option<Iso8601DurationDeserialize>")]
duration: Option<Duration>,
}
impl EntityProperties for PlanItem {
const EXPAND_QUERY: ExpandQuery = ExpandQuery::None;
}
const PEOPLE: EntitySetEndpoint<Person> = EntitySetEndpoint {
service_url: TRIP_PIN_SERVICE_URL,
name: "People",
marker: PhantomData,
};
const ME: SingletonEndpoint<Person> = SingletonEndpoint {
service_url: TRIP_PIN_SERVICE_URL,
name: "Me",
marker: PhantomData,
};
#[tokio::test]
async fn retrieve_entity_set_succeeds() {
let client = get_client();
PEOPLE.retrieve(&client).await.unwrap();
}
#[tokio::test]
async fn retrieve_entity_set_gets_all_pages() {
let client = get_client();
let entity_set = PEOPLE.retrieve(&client).await.unwrap();
assert_eq!(
20,
entity_set.len(),
"Retrieved entity set count is incorrect"
)
}
#[tokio::test]
async fn retrieve_entity_from_set_succeeds() {
let client = get_client();
PEOPLE
.retrieve_entity(&client, "russellwhyte")
.await
.unwrap();
}
#[tokio::test]
async fn retrieve_singleton_entity_succeeds() {
let client = get_client();
ME.get(&client).await.unwrap();
}
fn get_client() -> reqwest::Client {
reqwest::Client::builder()
.danger_accept_invalid_certs(true)
.build()
.unwrap()
}