UPDATE: Dump of initial files
This commit is contained in:
484
base/src/test/test_general.rs
Normal file
484
base/src/test/test_general.rs
Normal file
@@ -0,0 +1,484 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use crate::cell::CellValue;
|
||||
|
||||
use crate::number_format::to_excel_precision_str;
|
||||
|
||||
use crate::test::util::new_empty_model;
|
||||
|
||||
#[test]
|
||||
fn test_empty_model() {
|
||||
let model = new_empty_model();
|
||||
let names = model.workbook.get_worksheet_names();
|
||||
assert_eq!(names.len(), 1);
|
||||
assert_eq!(names[0], "Sheet1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_model_simple_evaluation() {
|
||||
let mut model = new_empty_model();
|
||||
model.set_user_input(0, 1, 1, "= 1 + 3".to_string());
|
||||
model.evaluate();
|
||||
let result = model._get_text_at(0, 1, 1);
|
||||
assert_eq!(result, *"4");
|
||||
let result = model._get_formula("A1");
|
||||
assert_eq!(result, *"=1+3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_model_simple_evaluation_order() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("A1", "=1/2/3");
|
||||
model._set("A2", "=(1/2)/3");
|
||||
model._set("A3", "=1/(2/3)");
|
||||
model.evaluate();
|
||||
assert_eq!(model._get_text("A1"), *"0.166666667");
|
||||
assert_eq!(model._get_text("A2"), *"0.166666667");
|
||||
assert_eq!(model._get_text("A3"), *"1.5");
|
||||
// Unnecessary parenthesis are lost
|
||||
assert_eq!(model._get_formula("A2"), *"=1/2/3");
|
||||
assert_eq!(model._get_formula("A3"), *"=1/(2/3)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_model_invalid_formula() {
|
||||
let mut model = new_empty_model();
|
||||
model.set_user_input(0, 1, 1, "= 1 +".to_string());
|
||||
model.evaluate();
|
||||
let result = model._get_text_at(0, 1, 1);
|
||||
assert_eq!(result, *"#ERROR!");
|
||||
let result = model._get_formula("A1");
|
||||
assert_eq!(result, *"= 1 +");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_model_dependencies() {
|
||||
let mut model = new_empty_model();
|
||||
model.set_user_input(0, 1, 1, "23".to_string()); // A1
|
||||
model.set_user_input(0, 1, 2, "= A1* 2-4".to_string()); // B1
|
||||
model.evaluate();
|
||||
let result = model._get_text_at(0, 1, 1);
|
||||
assert_eq!(result, *"23");
|
||||
assert!(!model._has_formula("A1"));
|
||||
let result = model._get_text_at(0, 1, 2);
|
||||
assert_eq!(result, *"42");
|
||||
let result = model._get_formula("B1");
|
||||
assert_eq!(result, *"=A1*2-4");
|
||||
|
||||
model.set_user_input(0, 2, 1, "=SUM(A1, B1)".to_string()); // A2
|
||||
model.evaluate();
|
||||
let result = model._get_text_at(0, 2, 1);
|
||||
assert_eq!(result, *"65");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_model_strings() {
|
||||
let mut model = new_empty_model();
|
||||
model.set_user_input(0, 1, 1, "Hello World".to_string());
|
||||
model.set_user_input(0, 1, 2, "=A1".to_string());
|
||||
model.evaluate();
|
||||
let result = model._get_text_at(0, 1, 1);
|
||||
assert_eq!(result, *"Hello World");
|
||||
let result = model._get_text_at(0, 1, 2);
|
||||
assert_eq!(result, *"Hello World");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_sheet_index_by_sheet_id() {
|
||||
let mut model = new_empty_model();
|
||||
model.new_sheet();
|
||||
|
||||
assert_eq!(model.get_sheet_index_by_sheet_id(1), Some(0));
|
||||
assert_eq!(model.get_sheet_index_by_sheet_id(2), Some(1));
|
||||
assert_eq!(model.get_sheet_index_by_sheet_id(1337), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_row_height() {
|
||||
let mut model = new_empty_model();
|
||||
let worksheet = model.workbook.worksheet_mut(0).unwrap();
|
||||
worksheet.set_row_height(5, 25.0).unwrap();
|
||||
let worksheet = model.workbook.worksheet(0).unwrap();
|
||||
assert!((25.0 - worksheet.row_height(5).unwrap()).abs() < f64::EPSILON);
|
||||
|
||||
let worksheet = model.workbook.worksheet_mut(0).unwrap();
|
||||
worksheet.set_row_height(5, 5.0).unwrap();
|
||||
let worksheet = model.workbook.worksheet(0).unwrap();
|
||||
assert!((5.0 - worksheet.row_height(5).unwrap()).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_excel_precision_str() {
|
||||
struct TestCase<'a> {
|
||||
value: f64,
|
||||
str: &'a str,
|
||||
}
|
||||
let test_cases = vec![
|
||||
TestCase {
|
||||
value: 2e-23,
|
||||
str: "2e-23",
|
||||
},
|
||||
TestCase {
|
||||
value: 42.0,
|
||||
str: "42",
|
||||
},
|
||||
TestCase {
|
||||
value: 200.0e-23,
|
||||
str: "2e-21",
|
||||
},
|
||||
TestCase {
|
||||
value: -200e-23,
|
||||
str: "-2e-21",
|
||||
},
|
||||
TestCase {
|
||||
value: 10.002,
|
||||
str: "10.002",
|
||||
},
|
||||
TestCase {
|
||||
value: f64::INFINITY,
|
||||
str: "inf",
|
||||
},
|
||||
TestCase {
|
||||
value: f64::NAN,
|
||||
str: "NaN",
|
||||
},
|
||||
];
|
||||
for test_case in test_cases {
|
||||
let str = to_excel_precision_str(test_case.value);
|
||||
assert_eq!(str, test_case.str);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_booleans() {
|
||||
let mut model = new_empty_model();
|
||||
model.set_user_input(0, 1, 1, "true".to_string());
|
||||
model.set_user_input(0, 2, 1, "TRUE".to_string());
|
||||
model.set_user_input(0, 3, 1, "True".to_string());
|
||||
model.set_user_input(0, 4, 1, "false".to_string());
|
||||
model.set_user_input(0, 5, 1, "FALSE".to_string());
|
||||
model.set_user_input(0, 6, 1, "False".to_string());
|
||||
|
||||
model.set_user_input(0, 1, 2, "=ISLOGICAL(A1)".to_string());
|
||||
model.set_user_input(0, 2, 2, "=ISLOGICAL(A2)".to_string());
|
||||
model.set_user_input(0, 3, 2, "=ISLOGICAL(A3)".to_string());
|
||||
model.set_user_input(0, 4, 2, "=ISLOGICAL(A4)".to_string());
|
||||
model.set_user_input(0, 5, 2, "=ISLOGICAL(A5)".to_string());
|
||||
model.set_user_input(0, 6, 2, "=ISLOGICAL(A6)".to_string());
|
||||
|
||||
model.set_user_input(0, 1, 5, "=IF(false, True, FALSe)".to_string());
|
||||
|
||||
model.evaluate();
|
||||
|
||||
assert_eq!(model._get_text_at(0, 1, 1), *"TRUE");
|
||||
assert_eq!(model._get_text_at(0, 2, 1), *"TRUE");
|
||||
assert_eq!(model._get_text_at(0, 3, 1), *"TRUE");
|
||||
|
||||
assert_eq!(model._get_text_at(0, 4, 1), *"FALSE");
|
||||
assert_eq!(model._get_text_at(0, 5, 1), *"FALSE");
|
||||
assert_eq!(model._get_text_at(0, 6, 1), *"FALSE");
|
||||
|
||||
assert_eq!(model._get_text_at(0, 1, 2), *"TRUE");
|
||||
assert_eq!(model._get_text_at(0, 2, 2), *"TRUE");
|
||||
assert_eq!(model._get_text_at(0, 3, 2), *"TRUE");
|
||||
assert_eq!(model._get_text_at(0, 4, 2), *"TRUE");
|
||||
assert_eq!(model._get_text_at(0, 5, 2), *"TRUE");
|
||||
assert_eq!(model._get_text_at(0, 6, 2), *"TRUE");
|
||||
|
||||
assert_eq!(model._get_formula("E1"), *"=IF(FALSE,TRUE,FALSE)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_cell_style() {
|
||||
let mut model = new_empty_model();
|
||||
let mut style = model.get_style_for_cell(0, 1, 1);
|
||||
assert!(!style.font.b);
|
||||
|
||||
style.font.b = true;
|
||||
assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
|
||||
|
||||
let mut style = model.get_style_for_cell(0, 1, 1);
|
||||
assert!(style.font.b);
|
||||
|
||||
style.font.b = false;
|
||||
assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
|
||||
|
||||
let style = model.get_style_for_cell(0, 1, 1);
|
||||
assert!(!style.font.b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_copy_cell_style() {
|
||||
let mut model = new_empty_model();
|
||||
|
||||
let mut style = model.get_style_for_cell(0, 1, 1);
|
||||
style.font.b = true;
|
||||
assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
|
||||
|
||||
let mut style = model.get_style_for_cell(0, 1, 2);
|
||||
style.font.i = true;
|
||||
assert!(model.set_cell_style(0, 1, 2, &style).is_ok());
|
||||
|
||||
assert!(model.copy_cell_style((0, 1, 1), (0, 1, 2)).is_ok());
|
||||
|
||||
let style = model.get_style_for_cell(0, 1, 1);
|
||||
assert!(style.font.b);
|
||||
assert!(!style.font.i);
|
||||
|
||||
let style = model.get_style_for_cell(0, 1, 2);
|
||||
assert!(style.font.b);
|
||||
assert!(!style.font.i);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_cell_style_index() {
|
||||
let mut model = new_empty_model();
|
||||
|
||||
let mut style = model.get_style_for_cell(0, 1, 1);
|
||||
let style_index = model.get_cell_style_index(0, 1, 1);
|
||||
assert_eq!(style_index, 0);
|
||||
assert!(!style.font.b);
|
||||
|
||||
style.font.b = true;
|
||||
assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
|
||||
|
||||
let style_index = model.get_cell_style_index(0, 1, 1);
|
||||
assert_eq!(style_index, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_model_set_cells_with_values_styles() {
|
||||
let mut model = new_empty_model();
|
||||
// Inputs
|
||||
model.set_user_input(0, 1, 1, "21".to_string()); // A1
|
||||
model.set_user_input(0, 2, 1, "2".to_string()); // A2
|
||||
|
||||
let style_index = model.get_cell_style_index(0, 1, 1);
|
||||
assert_eq!(style_index, 0);
|
||||
let mut style = model.get_style_for_cell(0, 1, 1);
|
||||
style.font.b = true;
|
||||
assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
|
||||
assert!(model.set_cell_style(0, 2, 1, &style).is_ok());
|
||||
let style_index = model.get_cell_style_index(0, 1, 1);
|
||||
assert_eq!(style_index, 1);
|
||||
let style_index = model.get_cell_style_index(0, 2, 1);
|
||||
assert_eq!(style_index, 1);
|
||||
|
||||
model.update_cell_with_number(0, 1, 2, 1.0);
|
||||
model.update_cell_with_number(0, 2, 1, 2.0);
|
||||
|
||||
model.evaluate();
|
||||
|
||||
// Styles are not modified
|
||||
let style_index = model.get_cell_style_index(0, 1, 1);
|
||||
assert_eq!(style_index, 1);
|
||||
let style_index = model.get_cell_style_index(0, 2, 1);
|
||||
assert_eq!(style_index, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_style_fmt_id() {
|
||||
let mut model = new_empty_model();
|
||||
|
||||
let mut style = model.get_style_for_cell(0, 1, 1);
|
||||
style.num_fmt = "#.##".to_string();
|
||||
assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
|
||||
let style = model.get_style_for_cell(0, 1, 1);
|
||||
assert_eq!(style.num_fmt, "#.##");
|
||||
|
||||
let mut style = model.get_style_for_cell(0, 10, 1);
|
||||
style.num_fmt = "$$#,##0.0000".to_string();
|
||||
assert!(model.set_cell_style(0, 10, 1, &style).is_ok());
|
||||
let style = model.get_style_for_cell(0, 10, 1);
|
||||
assert_eq!(style.num_fmt, "$$#,##0.0000");
|
||||
|
||||
// Make sure old style is not touched
|
||||
let style = model.get_style_for_cell(0, 1, 1);
|
||||
assert_eq!(style.num_fmt, "#.##");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_sheet_color() {
|
||||
let mut model = new_empty_model();
|
||||
assert_eq!(model.workbook.worksheet(0).unwrap().color, None);
|
||||
assert!(model.set_sheet_color(0, "#FFFAAA").is_ok());
|
||||
|
||||
// Test new tab color is properly set
|
||||
assert_eq!(
|
||||
model.workbook.worksheet(0).unwrap().color,
|
||||
Some("#FFFAAA".to_string())
|
||||
);
|
||||
|
||||
// Test we can remove it
|
||||
assert!(model.set_sheet_color(0, "").is_ok());
|
||||
assert_eq!(model.workbook.worksheet(0).unwrap().color, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_sheet_color_invalid_sheet() {
|
||||
let mut model = new_empty_model();
|
||||
assert_eq!(
|
||||
model.set_sheet_color(10, "#FFFAAA"),
|
||||
Err("Invalid sheet index".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_sheet_color_invalid() {
|
||||
let mut model = new_empty_model();
|
||||
// Boundaries
|
||||
assert!(model.set_sheet_color(0, "#FFFFFF").is_ok());
|
||||
assert!(model.set_sheet_color(0, "#000000").is_ok());
|
||||
|
||||
assert_eq!(
|
||||
model.set_sheet_color(0, "#FFF"),
|
||||
Err("Invalid color: #FFF".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.set_sheet_color(0, "-#FFF"),
|
||||
Err("Invalid color: -#FFF".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.set_sheet_color(0, "#-FFF"),
|
||||
Err("Invalid color: #-FFF".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.set_sheet_color(0, "2FFFFFF"),
|
||||
Err("Invalid color: 2FFFFFF".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.set_sheet_color(0, "#FFFFFF1"),
|
||||
Err("Invalid color: #FFFFFF1".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_input_autocomplete() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("A1", "1");
|
||||
model._set("A2", "2");
|
||||
model.set_user_input(0, 3, 1, "=SUM(A1:A2".to_string());
|
||||
// This will fail anyway
|
||||
model.set_user_input(0, 4, 1, "=SUM(A1*".to_string());
|
||||
model.evaluate();
|
||||
|
||||
assert_eq!(model._get_formula("A3"), "=SUM(A1:A2)");
|
||||
assert_eq!(model._get_text("A3"), "3");
|
||||
|
||||
assert_eq!(model._get_formula("A4"), "=SUM(A1*");
|
||||
assert_eq!(model._get_text("A4"), "#ERROR!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_cell_value_by_ref() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("A1", "1");
|
||||
model._set("A2", "2");
|
||||
model.evaluate();
|
||||
|
||||
// Correct
|
||||
assert_eq!(
|
||||
model.get_cell_value_by_ref("Sheet1!A1"),
|
||||
Ok(CellValue::Number(1.0))
|
||||
);
|
||||
|
||||
// You need to specify full reference
|
||||
assert_eq!(
|
||||
model.get_cell_value_by_ref("A1"),
|
||||
Err("Error parsing reference: 'A1'".to_string())
|
||||
);
|
||||
|
||||
// Error, it has a trailing space
|
||||
assert_eq!(
|
||||
model.get_cell_value_by_ref("Sheet1!A1 "),
|
||||
Err("Error parsing reference: 'Sheet1!A1 '".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_formatted_cell_value() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("A1", "foobar");
|
||||
model._set("A2", "true");
|
||||
model._set("A3", "");
|
||||
model._set("A4", "123.456");
|
||||
model._set("A5", "123.456");
|
||||
|
||||
// change A5 format
|
||||
let mut style = model.get_style_for_cell(0, 5, 1);
|
||||
style.num_fmt = "$#,##0.00".to_string();
|
||||
model.set_cell_style(0, 5, 1, &style).unwrap();
|
||||
|
||||
model.evaluate();
|
||||
|
||||
assert_eq!(model.formatted_cell_value(0, 1, 1).unwrap(), "foobar");
|
||||
assert_eq!(model.formatted_cell_value(0, 2, 1).unwrap(), "TRUE");
|
||||
assert_eq!(model.formatted_cell_value(0, 3, 1).unwrap(), "");
|
||||
assert_eq!(model.formatted_cell_value(0, 4, 1).unwrap(), "123.456");
|
||||
assert_eq!(model.formatted_cell_value(0, 5, 1).unwrap(), "$123.46");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cell_formula() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("A1", "=1+2+3");
|
||||
model._set("A2", "foobar");
|
||||
model.evaluate();
|
||||
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 1, 1), // A1
|
||||
Ok(Some("=1+2+3".to_string())),
|
||||
);
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 2, 1), // A2
|
||||
Ok(None),
|
||||
);
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 3, 1), // A3 - empty cell
|
||||
Ok(None),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.cell_formula(42, 1, 1),
|
||||
Err("Invalid sheet index".to_string()),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_xlfn() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("A1", "=_xlfn.SIN(1)");
|
||||
model._set("A2", "=_xlfn.SINY(1)");
|
||||
model._set("A3", "=_xlfn.CONCAT(3, 4.0)");
|
||||
model.evaluate();
|
||||
// Only modern formulas strip the '_xlfn.'
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 1, 1).unwrap(),
|
||||
Some("=_xlfn.SIN(1)".to_string())
|
||||
);
|
||||
// unknown formulas keep the '_xlfn.' prefix
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 2, 1).unwrap(),
|
||||
Some("=_xlfn.SINY(1)".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 3, 1).unwrap(),
|
||||
Some("=CONCAT(3,4)".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_letter_case() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("A1", "=sin(1)");
|
||||
model._set("A2", "=sIn(2)");
|
||||
model.evaluate();
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 1, 1).unwrap(),
|
||||
Some("=SIN(1)".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 2, 1).unwrap(),
|
||||
Some("=SIN(2)".to_string())
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user