use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
pub(crate) const TRIAL_PATH: &str = "/data/api/v1/trial";
pub(crate) const BANNERS_PATH: &str = "/data/api/v1/overview/banners";
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TrialWire {
#[serde(rename = "licenseMode", default)]
pub license_mode: String,
#[serde(rename = "trialState", default)]
pub trial_state: String,
#[serde(rename = "trialSecondsLeft", default)]
pub trial_seconds_left: i64,
#[serde(default)]
pub expired: bool,
#[serde(default)]
pub emergency: bool,
#[serde(rename = "emergencySecondsLeft", default)]
pub emergency_seconds_left: i64,
#[serde(default)]
pub development: bool,
#[serde(rename = "developmentSecondsLeft", default)]
pub development_seconds_left: i64,
#[serde(flatten)]
pub extra: BTreeMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BannerSet {
#[serde(default)]
pub banners: Vec<Banner>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Banner {
#[serde(default)]
pub order: i64,
#[serde(rename = "type", default)]
pub r#type: String,
#[serde(default)]
pub data: BannerData,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct BannerData {
#[serde(default)]
pub severity: String,
#[serde(rename = "expireTime", default)]
pub expire_time_ms: Option<i64>,
#[serde(rename = "toolTips", default)]
pub tool_tips: Vec<serde_json::Value>,
#[serde(default)]
pub actions: Vec<serde_json::Value>,
}
#[cfg(test)]
mod tests {
use super::{BannerSet, TrialWire};
#[test]
fn trial_parses_the_live_expired_capture() {
let wire: TrialWire = serde_json::from_value(serde_json::json!({
"licenseMode": "Trial",
"trialState": "AllInDemo",
"trialSecondsLeft": 0,
"expired": true,
"emergency": false,
"emergencySecondsLeft": 0,
"development": false,
"developmentSecondsLeft": 0
}))
.expect("the live expired shape must parse");
assert_eq!(wire.license_mode, "Trial");
assert_eq!(wire.trial_state, "AllInDemo");
assert_eq!(wire.trial_seconds_left, 0, "epoch seconds");
assert!(wire.expired);
assert!(!wire.emergency);
}
#[test]
fn trial_parses_the_live_active_capture() {
let wire: TrialWire = serde_json::from_value(serde_json::json!({
"licenseMode": "Trial",
"trialState": "AllInDemo",
"trialSecondsLeft": 6727,
"expired": false,
"emergency": false,
"emergencySecondsLeft": 0,
"development": false,
"developmentSecondsLeft": 0
}))
.expect("the live active shape must parse");
assert!(!wire.expired);
assert_eq!(wire.trial_seconds_left, 6727);
}
#[test]
fn banners_parse_both_live_states() {
let expired: BannerSet = serde_json::from_value(serde_json::json!({
"banners": [{
"order": 0,
"type": "trial",
"data": { "severity": "warning", "expireTime": null,
"toolTips": [], "actions": [] }
}]
}))
.expect("the live expired banner shape must parse");
let trial = &expired.banners[0];
assert_eq!(trial.r#type, "trial");
assert_eq!(trial.data.severity, "warning");
assert_eq!(trial.data.expire_time_ms, None, "expired = null, Pitfall 7");
let active: BannerSet = serde_json::from_value(serde_json::json!({
"banners": [{
"order": 5,
"type": "trial",
"data": { "severity": "info",
"expireTime": 1787435662564i64,
"toolTips": [], "actions": [] }
}]
}))
.expect("the live active banner shape must parse");
let trial = &active.banners[0];
assert_eq!(trial.data.severity, "info");
assert_eq!(
trial.data.expire_time_ms,
Some(1_787_435_662_564),
"epoch MILLISECONDS"
);
}
}