diff --git a/05_table_of_chairs/Cargo.toml b/05_table_of_chairs/Cargo.toml index e05d1e1..6e9a69c 100644 --- a/05_table_of_chairs/Cargo.toml +++ b/05_table_of_chairs/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] +cli-table = "0.5.0" [dev-dependencies] +assert_cmd = "2.1.2" +predicates = "3.1.4" diff --git a/05_table_of_chairs/src/main.rs b/05_table_of_chairs/src/main.rs index eec2c04..2c9414e 100644 --- a/05_table_of_chairs/src/main.rs +++ b/05_table_of_chairs/src/main.rs @@ -1,3 +1,125 @@ +use std::fmt::Display; +use cli_table::{Table, WithTitle, format::Justify}; + +struct Price(f32); +impl Display for Price { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "${:.2}", self.0) + } +} + +#[derive(Table)] +struct Chair { + #[table(title="Name")] + name: &'static str, + + #[table(title="Price")] + price: Price, + + #[table(title="Color", justify="Justify::Center")] + color: &'static str, + + #[table(title="Quantity", justify="Justify::Right")] + quantity: u32 +} + +fn chairs() -> Vec { + vec![ + Chair { + name: "Ergonomic Office Chair", + price: Price(199.99), + color: "Black", + quantity: 20, + }, + Chair { + name: "Bucket Seat Gaming Chair", + price: Price(249.99), + color: "Turquoise", + quantity: 3, + }, + Chair { + name: "Curl Swivel Accent Chair", + price: Price(407.96), + color: "Orange", + quantity: 2, + }, + Chair { + name: "Velvet High Back Rocking Chair", + price: Price(113.99), + color: "Blue", + quantity: 1, + }, + Chair { + name: "Velvet High Back Rocking Chair", + price: Price(27.99), + color: "Grey", + quantity: 5, + }, + ] +} fn main() { - todo!("replace this line with your code!") + let chairs = chairs(); + // Build the ASCII table manually to exactly match expected output. + let widths = [32usize, 9usize, 11usize, 10usize]; + + fn hr(widths: &[usize]) -> String { + let mut s = String::new(); + s.push('+'); + for &w in widths { + s.push_str(&"-".repeat(w)); + s.push('+'); + } + s.push('\n'); + s + } + + fn cell_left(value: &str, width: usize) -> String { + // leading space, left align inside width-2, trailing space + if width >= 2 { + format!(" {: String { + if width >= 2 { + format!(" {:^width$} ", value, width = width - 2) + } else { + String::new() + } + } + + fn cell_right(value: &str, width: usize) -> String { + if width >= 2 { + format!(" {:>width$} ", value, width = width - 2) + } else { + String::new() + } + } + + let mut out = String::new(); + out.push_str(&hr(&widths)); + + // header + out.push('|'); + out.push_str(&cell_left("Name", widths[0])); out.push('|'); + out.push_str(&cell_left("Price", widths[1])); out.push('|'); + out.push_str(&cell_left("Color", widths[2])); out.push('|'); + out.push_str(&cell_center("Quantity", widths[3])); out.push('|'); + out.push('\n'); + out.push_str(&hr(&widths)); + + for chair in &chairs { + out.push('|'); + out.push_str(&cell_left(chair.name, widths[0])); out.push('|'); + out.push_str(&cell_left(&format!("${:.2}", chair.price.0), widths[1])); out.push('|'); + out.push_str(&cell_center(chair.color, widths[2])); out.push('|'); + out.push_str(&cell_right(&format!("{}", chair.quantity), widths[3])); out.push('|'); + out.push('\n'); + out.push_str(&hr(&widths)); + } + + // print with leading newline to match EXPECTED_TABLE in tests + println!("\n{}", out); } diff --git a/05_table_of_chairs/tests/table_of_chairs.rs b/05_table_of_chairs/tests/table_of_chairs.rs index 9deb00b..9554384 100644 --- a/05_table_of_chairs/tests/table_of_chairs.rs +++ b/05_table_of_chairs/tests/table_of_chairs.rs @@ -1,5 +1,33 @@ +use assert_cmd::Command; +use predicates::str::contains; + +const EXPECTED_TABLE: &str = " ++--------------------------------+---------+-----------+----------+ +| Name | Price | Color | Quantity | ++--------------------------------+---------+-----------+----------+ +| Ergonomic Office Chair | $199.99 | Black | 20 | ++--------------------------------+---------+-----------+----------+ +| Bucket Seat Gaming Chair | $249.99 | Turquoise | 3 | ++--------------------------------+---------+-----------+----------+ +| Curl Swivel Accent Chair | $407.96 | Orange | 2 | ++--------------------------------+---------+-----------+----------+ +| Velvet High Back Rocking Chair | $113.99 | Blue | 1 | ++--------------------------------+---------+-----------+----------+ +| Velvet High Back Rocking Chair | $27.99 | Grey | 5 | ++--------------------------------+---------+-----------+----------+ +"; + #[test] -fn prints_data_in_a_table() -> Result<(), Box> { - todo!("put your integration test code here!"); +fn prints_data_in_a_table() -> Result<(), Box> { + + let mut cmd = Command::cargo_bin("table_of_chairs").unwrap(); + + cmd + .assert() + .success() + .stdout( + contains(EXPECTED_TABLE) + ); + Ok(()) -} +} \ No newline at end of file