use super::{unique_series_names, AxisConfig, DataSeries, ValidateXYChart};
use crate::errors::ValidationErrorKind;
use crate::validators::*;
use serde::Serialize;
use slack_messaging_derive::Builder;
#[derive(Debug, Clone, Serialize, PartialEq, Builder)]
#[builder(validate = "validate")]
#[serde(tag = "type", rename = "area")]
pub struct AreaChart {
#[builder(
push_item = "push_series",
validate("required", "list::not_empty", "list::max_item_6", "unique_series_names")
)]
pub(crate) series: Option<Vec<DataSeries>>,
#[builder(validate("required"))]
pub(crate) axis_config: Option<AxisConfig>,
}
impl ValidateXYChart for AreaChart {
fn series(&self) -> Option<&[DataSeries]> {
self.series.as_deref()
}
fn axis_config(&self) -> Option<&AxisConfig> {
self.axis_config.as_ref()
}
}
fn validate(val: &AreaChart) -> Vec<ValidationErrorKind> {
val.validate()
}
#[cfg(test)]
mod tests {
use super::*;
use super::super::data_points;
use crate::errors::*;
#[test]
fn it_implements_builder() {
let expected = AreaChart {
series: Some(vec![data_series("Pie")]),
axis_config: Some(axis_config()),
};
let val = AreaChart::builder()
.set_series(Some(vec![data_series("Pie")]))
.set_axis_config(Some(axis_config()))
.build()
.unwrap();
assert_eq!(val, expected);
let val = AreaChart::builder()
.series(vec![data_series("Pie")])
.axis_config(axis_config())
.build()
.unwrap();
assert_eq!(val, expected);
}
#[test]
fn it_implements_push_item_method() {
let expected = AreaChart {
series: Some(vec![data_series("Pie")]),
axis_config: Some(axis_config()),
};
let val = AreaChart::builder()
.push_series(data_series("Pie"))
.axis_config(axis_config())
.build()
.unwrap();
assert_eq!(val, expected);
}
#[test]
fn it_requires_series_field() {
let err = AreaChart::builder()
.axis_config(axis_config())
.build()
.unwrap_err();
assert_eq!(err.object(), "AreaChart");
let errors = err.field("series");
assert!(errors.includes(ValidationErrorKind::Required));
}
#[test]
fn it_requires_series_field_to_have_at_least_one_item() {
let err = AreaChart::builder()
.series(vec![] as Vec<DataSeries>)
.axis_config(axis_config())
.build()
.unwrap_err();
assert_eq!(err.object(), "AreaChart");
let errors = err.field("series");
assert!(errors.includes(ValidationErrorKind::EmptyArray));
}
#[test]
fn it_requires_series_field_to_have_no_more_than_six_items() {
let err = AreaChart::builder()
.series(vec![
data_series("Series 1"),
data_series("Series 2"),
data_series("Series 3"),
data_series("Series 4"),
data_series("Series 5"),
data_series("Series 6"),
data_series("Series 7"),
])
.axis_config(axis_config())
.build()
.unwrap_err();
assert_eq!(err.object(), "AreaChart");
let errors = err.field("series");
assert!(errors.includes(ValidationErrorKind::MaxArraySize(6)));
}
#[test]
fn it_requires_axis_config_field() {
let err = AreaChart::builder()
.series(vec![data_series("Pie")])
.build()
.unwrap_err();
assert_eq!(err.object(), "AreaChart");
let errors = err.field("axis_config");
assert!(errors.includes(ValidationErrorKind::Required));
}
#[test]
fn it_requires_series_names_to_be_unique() {
let err = AreaChart::builder()
.series(vec![
data_series("Sales"),
data_series("Revenue"),
data_series("Sales"),
])
.axis_config(axis_config())
.build()
.unwrap_err();
assert_eq!(err.object(), "AreaChart");
let errors = err.field("series");
assert!(errors.includes(ValidationErrorKind::UniqueSeriesName));
}
#[test]
fn it_requires_series_labels_to_match_axis_categories() {
let err = AreaChart::builder()
.series(vec![
data_series("Pie"),
DataSeries::builder()
.name("Cake")
.data(data_points(vec![
("Chocolate", 90),
("Vanilla", 80),
]).unwrap())
.build()
.unwrap(),
])
.axis_config(axis_config())
.build()
.unwrap_err();
assert_eq!(err.object(), "AreaChart");
let errors = err.across_fields();
assert!(errors.includes(ValidationErrorKind::DataPointLabelMatching));
}
fn data_series(name: &str) -> DataSeries {
DataSeries::builder()
.name(name)
.data(data_points(vec![
("Strawberry Rhubarb", 85),
("Pumpkin", 70),
]).unwrap())
.build()
.unwrap()
}
fn axis_config() -> AxisConfig {
AxisConfig::builder()
.categories(vec![
"Strawberry Rhubarb",
"Pumpkin",
])
.x_label("Pies")
.y_label("Percentage of Tastiness")
.build()
.unwrap()
}
}