From 8f36c35519da4f624d4932a5a2f6d38c9152d555 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 10 Apr 2025 20:49:25 -0700 Subject: [PATCH] Work on tests (new one fails) --- rust/pspp/src/output/pivot/mod.rs | 37 +++++++- rust/pspp/src/output/pivot/test.rs | 141 ++++++++++++++++++++++++++++- 2 files changed, 169 insertions(+), 9 deletions(-) diff --git a/rust/pspp/src/output/pivot/mod.rs b/rust/pspp/src/output/pivot/mod.rs index 64e806b8ce..f00cdd77f6 100644 --- a/rust/pspp/src/output/pivot/mod.rs +++ b/rust/pspp/src/output/pivot/mod.rs @@ -298,6 +298,9 @@ impl Iterator for AxisIterator { } impl PivotTable { + fn builder(title: impl Into, dimensions: &[DimensionBuilder]) -> PivotTableBuilder { + PivotTableBuilder::new(title, dimensions) + } fn axis_values(&self, axis: Axis3) -> AxisIterator { AxisIterator { indexes: repeat_n(0, self.axes[axis].dimensions.len()).collect(), @@ -358,6 +361,10 @@ impl Dimension { pub fn len(&self) -> usize { self.data_leaves.len() } + + pub fn builder(axis: Axis3, root: GroupBuilder) -> DimensionBuilder { + DimensionBuilder::new(axis, root) + } } #[derive(Clone, Debug)] @@ -376,6 +383,10 @@ pub struct Group { } impl Group { + pub fn builder(name: impl Into) -> GroupBuilder { + GroupBuilder::new(name) + } + pub fn parent(&self) -> Option> { self.parent.as_ref().map(|parent| parent.upgrade().unwrap()) } @@ -423,9 +434,9 @@ pub struct GroupBuilder { } impl GroupBuilder { - pub fn new(name: Value) -> Self { + pub fn new(name: impl Into) -> Self { Self { - name: Box::new(name), + name: Box::new(name.into()), children: Vec::new(), show_label: None, } @@ -529,6 +540,14 @@ impl From<(Value, Class)> for CategoryBuilder { } } +impl From<&str> for CategoryBuilder { + fn from(name: &str) -> Self { + Self::Leaf { + name: Box::new(Value::new_text(name)), + class: None, + } + } +} pub struct PivotTableBuilder { look: Arc, title: Box, @@ -537,10 +556,10 @@ pub struct PivotTableBuilder { } impl PivotTableBuilder { - pub fn new(title: Value, dimensions: &[DimensionBuilder]) -> Self { + pub fn new(title: impl Into, dimensions: &[DimensionBuilder]) -> Self { Self { look: Settings::global().look.clone(), - title: Box::new(title), + title: Box::new(title.into()), dimensions: dimensions.to_vec(), cells: HashMap::new(), } @@ -748,6 +767,10 @@ impl Look { self.row_label_position = row_label_position; self } + pub fn with_borders(mut self, borders: EnumMap) -> Self { + self.borders = borders; + self + } } impl Default for Look { @@ -1746,6 +1769,12 @@ impl Value { } } +impl From<&str> for Value { + fn from(value: &str) -> Self { + Self::new_text(value) + } +} + pub struct DisplayValue<'a> { inner: &'a ValueInner, markup: bool, diff --git a/rust/pspp/src/output/pivot/test.rs b/rust/pspp/src/output/pivot/test.rs index 92318a2b74..c0667f1049 100644 --- a/rust/pspp/src/output/pivot/test.rs +++ b/rust/pspp/src/output/pivot/test.rs @@ -1,6 +1,11 @@ use std::sync::Arc; -use crate::output::pivot::{Area, Color, LabelPosition, Look, PivotTable}; +use enum_map::EnumMap; + +use crate::output::pivot::{ + Area, Axis2, Border, BorderStyle, Color, Dimension, Group, HeadingRegion, LabelPosition, Look, + PivotTable, RowColBorder, Stroke, +}; use super::{Axis3, DimensionBuilder, GroupBuilder, PivotTableBuilder, Value}; @@ -582,9 +587,135 @@ fn empty_dimensions() { .with(Value::new_text("c1")) .with(Value::new_text("c2")), ); - let pivot_table = - PivotTableBuilder::new(Value::new_text("Three Dimensions, Two Empty"), &[d1, d2, d3]) - .with_look(look.clone()) - .build(); + let pivot_table = PivotTableBuilder::new( + Value::new_text("Three Dimensions, Two Empty"), + &[d1, d2, d3], + ) + .with_look(look.clone()) + .build(); assert_rendering(&pivot_table, "Three Dimensions, Two Empty\n"); } + +#[test] +fn empty_groups() { + let mut a = GroupBuilder::new(Value::new_text("a")) + .with(Value::new_text("a1")) + .with(GroupBuilder::new(Value::new_text("a2"))) + .with(Value::new_text("a3")); + let d1 = DimensionBuilder::new(Axis3::X, a); + + let mut b = GroupBuilder::new(Value::new_text("b")) + .with(GroupBuilder::new(Value::new_text("b1"))) + .with(Value::new_text("b2")) + .with(Value::new_text("b3")); + let d2 = DimensionBuilder::new(Axis3::Y, b); + + let mut pt = PivotTableBuilder::new(Value::new_text("Empty Groups"), &[d1, d2]); + let mut i = 0; + for b in 0..2 { + for a in 0..2 { + pt.insert(&[a, b], Value::new_integer(Some(i as f64))); + i += 1; + } + } + let pivot_table = pt + .with_look(Arc::new(test_look().with_omit_empty(false))) + .build(); + assert_rendering( + &pivot_table, + "\ +Empty Groups +╭──┬──┬──╮ +│ │a1│a3│ +├──┼──┼──┤ +│b2│ 0│ 1│ +│b3│ 2│ 3│ +╰──┴──┴──╯ +", + ); +} + +#[test] +fn borders() { + let a = Dimension::builder( + Axis3::X, + Group::builder("a") + .with_label_shown() + .with("a1") + .with(Group::builder("ag1").with("a2").with("a3")), + ); + let b = Dimension::builder( + Axis3::X, + Group::builder("b") + .with_label_shown() + .with(Group::builder("bg1").with("b1").with("b2")) + .with("b3"), + ); + let c = Dimension::builder( + Axis3::Y, + Group::builder("c") + .with_label_shown() + .with("c1") + .with(Group::builder("cg1").with("c2").with("c3")), + ); + let d = Dimension::builder( + Axis3::Y, + Group::builder("d") + .with_label_shown() + .with(Group::builder("dg1").with("d1").with("d2")) + .with("d3"), + ); + let borders = EnumMap::from_fn(|border| match border { + Border::Dimension(RowColBorder(HeadingRegion::Rows, Axis2::X)) + | Border::Dimension(RowColBorder(HeadingRegion::Columns, Axis2::Y)) => BorderStyle { + stroke: Stroke::Solid, + color: Color { + alpha: 255, + r: 0, + g: 0, + b: 255, + }, + }, + _ => BorderStyle::none(), + }); + let mut pivot_table = PivotTable::builder("Dimension Borders 1", &[a, b, c, d]) + .with_look(Arc::new(test_look().with_borders(borders))); + let mut i = 0; + for d in 0..3 { + for c in 0..3 { + for b in 0..3 { + for a in 0..3 { + pivot_table.insert(&[a, b, c, d], Value::new_integer(Some(i as f64))); + i += 1; + } + } + } + } + let pivot_table = pivot_table.build(); + assert_rendering( + &pivot_table, + "\ +Dimension Borders 1 + b + bg1 │ + b1 │ b2 │ b3 + a │ a │ a + │ ag1 │ │ ag1 │ │ ag1 +d c a1│a2 a3│a1│a2 a3│a1│a2 a3 +dg1 d1 c1 0│ 1 2│ 3│ 4 5│ 6│ 7 8 + ╶─────────┼─────┼──┼─────┼──┼───── + cg1 c2 9│10 11│12│13 14│15│16 17 + c3 18│19 20│21│22 23│24│25 26 + ╶────────────┼─────┼──┼─────┼──┼───── + d2 c1 27│28 29│30│31 32│33│34 35 + ╶─────────┼─────┼──┼─────┼──┼───── + cg1 c2 36│37 38│39│40 41│42│43 44 + c3 45│46 47│48│49 50│51│52 53 +────────────────┼─────┼──┼─────┼──┼───── +d3 c1 54│55 56│57│58 59│60│61 62 + ╶─────────┼─────┼──┼─────┼──┼───── + cg1 c2 63│64 65│66│67 68│69│70 71 + c3 72│73 74│75│76 77│78│79 80 +", + ); +} -- 2.30.2