UPDATE: Adds 'user model' API (#27)
* bump version for documentation * Fixes wrong doc comment * renames old APIs to be consistent
This commit is contained in:
committed by
GitHub
parent
e9fc41541b
commit
d445553d85
@@ -1,6 +1,7 @@
|
||||
mod test_actions;
|
||||
mod test_binary_search;
|
||||
mod test_cell;
|
||||
mod test_cell_clear_contents;
|
||||
mod test_circular_references;
|
||||
mod test_column_width;
|
||||
mod test_criteria;
|
||||
@@ -28,9 +29,8 @@ mod test_frozen_rows_columns;
|
||||
mod test_general;
|
||||
mod test_math;
|
||||
mod test_metadata;
|
||||
mod test_model_delete_cell;
|
||||
mod test_model_cell_clear_all;
|
||||
mod test_model_is_empty_cell;
|
||||
mod test_model_set_cell_empty;
|
||||
mod test_move_formula;
|
||||
mod test_quote_prefix;
|
||||
mod test_set_user_input;
|
||||
@@ -53,3 +53,4 @@ mod test_frozen_rows_and_columns;
|
||||
mod test_get_cell_content;
|
||||
mod test_percentage;
|
||||
mod test_today;
|
||||
mod user_model;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use crate::constants::LAST_COLUMN;
|
||||
use crate::model::Model;
|
||||
use crate::test::util::new_empty_model;
|
||||
use crate::types::Col;
|
||||
|
||||
#[test]
|
||||
fn test_insert_columns() {
|
||||
@@ -195,6 +196,250 @@ fn test_delete_columns() {
|
||||
assert_eq!(model._get_formula("A3"), *"=SUM(#REF!:K4)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_column_width() {
|
||||
let mut model = new_empty_model();
|
||||
let (sheet, column) = (0, 5);
|
||||
let normal_width = model.get_column_width(sheet, column).unwrap();
|
||||
// Set the width of one column to 5 times the normal width
|
||||
assert!(model
|
||||
.set_column_width(sheet, column, normal_width * 5.0)
|
||||
.is_ok());
|
||||
|
||||
// delete it
|
||||
assert!(model.delete_columns(sheet, column, 1).is_ok());
|
||||
|
||||
// all the columns around have the expected width
|
||||
assert_eq!(
|
||||
model.get_column_width(sheet, column - 1).unwrap(),
|
||||
normal_width
|
||||
);
|
||||
assert_eq!(model.get_column_width(sheet, column).unwrap(), normal_width);
|
||||
assert_eq!(
|
||||
model.get_column_width(sheet, column + 1).unwrap(),
|
||||
normal_width
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// We set the style of columns 4 to 7 and delete column 4
|
||||
// We check that columns 4 to 6 have the new style
|
||||
fn test_delete_first_column_width() {
|
||||
let mut model = new_empty_model();
|
||||
model.workbook.worksheets[0].cols = vec![Col {
|
||||
min: 4,
|
||||
max: 7,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None,
|
||||
}];
|
||||
let (sheet, column) = (0, 4);
|
||||
assert!(model.delete_columns(sheet, column, 1).is_ok());
|
||||
let cols = &model.workbook.worksheets[0].cols;
|
||||
assert_eq!(cols.len(), 1);
|
||||
assert_eq!(
|
||||
cols[0],
|
||||
Col {
|
||||
min: 4,
|
||||
max: 6,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Delete the last column in the range
|
||||
fn test_delete_last_column_width() {
|
||||
let mut model = new_empty_model();
|
||||
model.workbook.worksheets[0].cols = vec![Col {
|
||||
min: 4,
|
||||
max: 7,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None,
|
||||
}];
|
||||
let (sheet, column) = (0, 7);
|
||||
assert!(model.delete_columns(sheet, column, 1).is_ok());
|
||||
let cols = &model.workbook.worksheets[0].cols;
|
||||
assert_eq!(cols.len(), 1);
|
||||
assert_eq!(
|
||||
cols[0],
|
||||
Col {
|
||||
min: 4,
|
||||
max: 6,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Deletes columns at the end
|
||||
fn test_delete_last_few_columns_width() {
|
||||
let mut model = new_empty_model();
|
||||
model.workbook.worksheets[0].cols = vec![Col {
|
||||
min: 4,
|
||||
max: 17,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None,
|
||||
}];
|
||||
let (sheet, column) = (0, 13);
|
||||
assert!(model.delete_columns(sheet, column, 10).is_ok());
|
||||
let cols = &model.workbook.worksheets[0].cols;
|
||||
assert_eq!(cols.len(), 1);
|
||||
assert_eq!(
|
||||
cols[0],
|
||||
Col {
|
||||
min: 4,
|
||||
max: 12,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_columns_non_overlapping_left() {
|
||||
let mut model = new_empty_model();
|
||||
model.workbook.worksheets[0].cols = vec![Col {
|
||||
min: 10,
|
||||
max: 17,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None,
|
||||
}];
|
||||
let (sheet, column) = (0, 3);
|
||||
assert!(model.delete_columns(sheet, column, 4).is_ok());
|
||||
let cols = &model.workbook.worksheets[0].cols;
|
||||
assert_eq!(cols.len(), 1);
|
||||
assert_eq!(
|
||||
cols[0],
|
||||
Col {
|
||||
min: 6,
|
||||
max: 13,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_columns_overlapping_left() {
|
||||
let mut model = new_empty_model();
|
||||
model.workbook.worksheets[0].cols = vec![Col {
|
||||
min: 10,
|
||||
max: 20,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None,
|
||||
}];
|
||||
let (sheet, column) = (0, 8);
|
||||
assert!(model.delete_columns(sheet, column, 4).is_ok());
|
||||
let cols = &model.workbook.worksheets[0].cols;
|
||||
assert_eq!(cols.len(), 1);
|
||||
assert_eq!(
|
||||
cols[0],
|
||||
Col {
|
||||
min: 8,
|
||||
max: 16,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_columns_non_overlapping_right() {
|
||||
let mut model = new_empty_model();
|
||||
model.workbook.worksheets[0].cols = vec![Col {
|
||||
min: 10,
|
||||
max: 17,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None,
|
||||
}];
|
||||
let (sheet, column) = (0, 23);
|
||||
assert!(model.delete_columns(sheet, column, 4).is_ok());
|
||||
let cols = &model.workbook.worksheets[0].cols;
|
||||
assert_eq!(cols.len(), 1);
|
||||
assert_eq!(
|
||||
cols[0],
|
||||
Col {
|
||||
min: 10,
|
||||
max: 17,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// deletes some columns in the middle of the range
|
||||
fn test_delete_middle_column_width() {
|
||||
let mut model = new_empty_model();
|
||||
// styled columns [4, 17]
|
||||
model.workbook.worksheets[0].cols = vec![Col {
|
||||
min: 4,
|
||||
max: 17,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None,
|
||||
}];
|
||||
|
||||
// deletes columns 10, 11, 12
|
||||
let (sheet, column) = (0, 10);
|
||||
assert!(model.delete_columns(sheet, column, 3).is_ok());
|
||||
let cols = &model.workbook.worksheets[0].cols;
|
||||
assert_eq!(cols.len(), 1);
|
||||
assert_eq!(
|
||||
cols[0],
|
||||
Col {
|
||||
min: 4,
|
||||
max: 14,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// the range is inside the deleted columns
|
||||
fn delete_range_in_columns() {
|
||||
let mut model = new_empty_model();
|
||||
// styled columns [6, 10]
|
||||
model.workbook.worksheets[0].cols = vec![Col {
|
||||
min: 6,
|
||||
max: 10,
|
||||
width: 300.0,
|
||||
custom_width: true,
|
||||
style: None,
|
||||
}];
|
||||
|
||||
// deletes columns [4, 17]
|
||||
let (sheet, column) = (0, 4);
|
||||
assert!(model.delete_columns(sheet, column, 8).is_ok());
|
||||
let cols = &model.workbook.worksheets[0].cols;
|
||||
assert_eq!(cols.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_columns_error() {
|
||||
let mut model = new_empty_model();
|
||||
let (sheet, column) = (0, 5);
|
||||
assert!(model.delete_columns(sheet, column, -1).is_err());
|
||||
assert!(model.delete_columns(sheet, column, 0).is_err());
|
||||
assert!(model.delete_columns(sheet, column, 1).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_rows() {
|
||||
let mut model = new_empty_model();
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
use crate::test::util::new_empty_model;
|
||||
|
||||
#[test]
|
||||
fn test_set_cell_empty_non_existing_sheet() {
|
||||
fn test_cell_clear_contents_non_existing_sheet() {
|
||||
let mut model = new_empty_model();
|
||||
assert_eq!(
|
||||
model.set_cell_empty(13, 1, 1),
|
||||
model.cell_clear_contents(13, 1, 1),
|
||||
Err("Invalid sheet index".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_cell_empty_unset_cell() {
|
||||
fn test_cell_clear_contents_unset_cell() {
|
||||
let mut model = new_empty_model();
|
||||
model.set_cell_empty(0, 1, 1).unwrap();
|
||||
model.cell_clear_contents(0, 1, 1).unwrap();
|
||||
assert_eq!(model.is_empty_cell(0, 1, 1), Ok(true));
|
||||
model.evaluate();
|
||||
assert_eq!(model._get_text_at(0, 1, 1), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_cell_empty_with_value() {
|
||||
fn test_cell_clear_contents_with_value() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("A1", "hello");
|
||||
model.evaluate();
|
||||
@@ -28,7 +28,7 @@ fn test_set_cell_empty_with_value() {
|
||||
assert_eq!(model._get_text_at(0, 1, 1), "hello");
|
||||
assert_eq!(model.is_empty_cell(0, 1, 1), Ok(false));
|
||||
|
||||
model.set_cell_empty(0, 1, 1).unwrap();
|
||||
model.cell_clear_contents(0, 1, 1).unwrap();
|
||||
model.evaluate();
|
||||
|
||||
assert_eq!(model._get_text_at(0, 1, 1), "");
|
||||
@@ -36,7 +36,7 @@ fn test_set_cell_empty_with_value() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_cell_empty_referenced_elsewhere() {
|
||||
fn test_cell_clear_contents_referenced_elsewhere() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("A1", "35");
|
||||
model._set("A2", "=2*A1");
|
||||
@@ -47,7 +47,7 @@ fn test_set_cell_empty_referenced_elsewhere() {
|
||||
assert_eq!(model.is_empty_cell(0, 1, 1), Ok(false));
|
||||
assert_eq!(model.is_empty_cell(0, 2, 1), Ok(false));
|
||||
|
||||
model.set_cell_empty(0, 1, 1).unwrap();
|
||||
model.cell_clear_contents(0, 1, 1).unwrap();
|
||||
model.evaluate();
|
||||
|
||||
assert_eq!(model._get_text_at(0, 1, 1), "");
|
||||
@@ -23,9 +23,9 @@ fn test_column_width() {
|
||||
.unwrap();
|
||||
assert_eq!(model.workbook.worksheets[0].cols.len(), 3);
|
||||
let worksheet = model.workbook.worksheet(0).unwrap();
|
||||
assert!((worksheet.column_width(1).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON);
|
||||
assert!((worksheet.column_width(2).unwrap() - 30.0).abs() < f64::EPSILON);
|
||||
assert!((worksheet.column_width(3).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON);
|
||||
assert!((worksheet.get_column_width(1).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON);
|
||||
assert!((worksheet.get_column_width(2).unwrap() - 30.0).abs() < f64::EPSILON);
|
||||
assert!((worksheet.get_column_width(3).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON);
|
||||
assert_eq!(model.get_cell_style_index(0, 23, 2), 6);
|
||||
}
|
||||
|
||||
@@ -48,9 +48,11 @@ fn test_column_width_lower_edge() {
|
||||
.unwrap();
|
||||
assert_eq!(model.workbook.worksheets[0].cols.len(), 2);
|
||||
let worksheet = model.workbook.worksheet(0).unwrap();
|
||||
assert!((worksheet.column_width(4).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON);
|
||||
assert!((worksheet.column_width(5).unwrap() - 30.0).abs() < f64::EPSILON);
|
||||
assert!((worksheet.column_width(6).unwrap() - 10.0 * COLUMN_WIDTH_FACTOR).abs() < f64::EPSILON);
|
||||
assert!((worksheet.get_column_width(4).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON);
|
||||
assert!((worksheet.get_column_width(5).unwrap() - 30.0).abs() < f64::EPSILON);
|
||||
assert!(
|
||||
(worksheet.get_column_width(6).unwrap() - 10.0 * COLUMN_WIDTH_FACTOR).abs() < f64::EPSILON
|
||||
);
|
||||
assert_eq!(model.get_cell_style_index(0, 23, 5), 1);
|
||||
}
|
||||
|
||||
@@ -74,9 +76,9 @@ fn test_column_width_higher_edge() {
|
||||
assert_eq!(model.workbook.worksheets[0].cols.len(), 2);
|
||||
let worksheet = model.workbook.worksheet(0).unwrap();
|
||||
assert!(
|
||||
(worksheet.column_width(15).unwrap() - 10.0 * COLUMN_WIDTH_FACTOR).abs() < f64::EPSILON
|
||||
(worksheet.get_column_width(15).unwrap() - 10.0 * COLUMN_WIDTH_FACTOR).abs() < f64::EPSILON
|
||||
);
|
||||
assert!((worksheet.column_width(16).unwrap() - 30.0).abs() < f64::EPSILON);
|
||||
assert!((worksheet.column_width(17).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON);
|
||||
assert!((worksheet.get_column_width(16).unwrap() - 30.0).abs() < f64::EPSILON);
|
||||
assert!((worksheet.get_column_width(17).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON);
|
||||
assert_eq!(model.get_cell_style_index(0, 23, 16), 1);
|
||||
}
|
||||
|
||||
@@ -8,34 +8,37 @@ use crate::{
|
||||
#[test]
|
||||
fn test_empty_model() {
|
||||
let mut model = new_empty_model();
|
||||
assert_eq!(model.get_frozen_rows(0), Ok(0));
|
||||
assert_eq!(model.get_frozen_columns(0), Ok(0));
|
||||
assert_eq!(model.get_frozen_rows_count(0), Ok(0));
|
||||
assert_eq!(model.get_frozen_columns_count(0), Ok(0));
|
||||
|
||||
let e = model.set_frozen_rows(0, 3);
|
||||
assert!(e.is_ok());
|
||||
assert_eq!(model.get_frozen_rows(0), Ok(3));
|
||||
assert_eq!(model.get_frozen_columns(0), Ok(0));
|
||||
assert_eq!(model.get_frozen_rows_count(0), Ok(3));
|
||||
assert_eq!(model.get_frozen_columns_count(0), Ok(0));
|
||||
|
||||
let e = model.set_frozen_columns(0, 53);
|
||||
assert!(e.is_ok());
|
||||
assert_eq!(model.get_frozen_rows(0), Ok(3));
|
||||
assert_eq!(model.get_frozen_columns(0), Ok(53));
|
||||
assert_eq!(model.get_frozen_rows_count(0), Ok(3));
|
||||
assert_eq!(model.get_frozen_columns_count(0), Ok(53));
|
||||
|
||||
// Set them back to zero
|
||||
let e = model.set_frozen_rows(0, 0);
|
||||
assert!(e.is_ok());
|
||||
let e = model.set_frozen_columns(0, 0);
|
||||
assert!(e.is_ok());
|
||||
assert_eq!(model.get_frozen_rows(0), Ok(0));
|
||||
assert_eq!(model.get_frozen_columns(0), Ok(0));
|
||||
assert_eq!(model.get_frozen_rows_count(0), Ok(0));
|
||||
assert_eq!(model.get_frozen_columns_count(0), Ok(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_sheet() {
|
||||
let mut model = new_empty_model();
|
||||
assert_eq!(model.get_frozen_rows(1), Err("Invalid sheet".to_string()));
|
||||
assert_eq!(
|
||||
model.get_frozen_columns(3),
|
||||
model.get_frozen_rows_count(1),
|
||||
Err("Invalid sheet".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.get_frozen_columns_count(3),
|
||||
Err("Invalid sheet".to_string())
|
||||
);
|
||||
|
||||
|
||||
@@ -411,11 +411,11 @@ fn test_get_formatted_cell_value() {
|
||||
|
||||
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");
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1).unwrap(), "foobar");
|
||||
assert_eq!(model.get_formatted_cell_value(0, 2, 1).unwrap(), "TRUE");
|
||||
assert_eq!(model.get_formatted_cell_value(0, 3, 1).unwrap(), "");
|
||||
assert_eq!(model.get_formatted_cell_value(0, 4, 1).unwrap(), "123.456");
|
||||
assert_eq!(model.get_formatted_cell_value(0, 5, 1).unwrap(), "$123.46");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -426,20 +426,20 @@ fn test_cell_formula() {
|
||||
model.evaluate();
|
||||
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 1, 1), // A1
|
||||
model.get_cell_formula(0, 1, 1), // A1
|
||||
Ok(Some("=1+2+3".to_string())),
|
||||
);
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 2, 1), // A2
|
||||
model.get_cell_formula(0, 2, 1), // A2
|
||||
Ok(None),
|
||||
);
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 3, 1), // A3 - empty cell
|
||||
model.get_cell_formula(0, 3, 1), // A3 - empty cell
|
||||
Ok(None),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.cell_formula(42, 1, 1),
|
||||
model.get_cell_formula(42, 1, 1),
|
||||
Err("Invalid sheet index".to_string()),
|
||||
);
|
||||
}
|
||||
@@ -453,16 +453,16 @@ fn test_xlfn() {
|
||||
model.evaluate();
|
||||
// Only modern formulas strip the '_xlfn.'
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 1, 1).unwrap(),
|
||||
model.get_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(),
|
||||
model.get_cell_formula(0, 2, 1).unwrap(),
|
||||
Some("=_xlfn.SINY(1)".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 3, 1).unwrap(),
|
||||
model.get_cell_formula(0, 3, 1).unwrap(),
|
||||
Some("=CONCAT(3,4)".to_string())
|
||||
);
|
||||
}
|
||||
@@ -474,11 +474,11 @@ fn test_letter_case() {
|
||||
model._set("A2", "=sIn(2)");
|
||||
model.evaluate();
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 1, 1).unwrap(),
|
||||
model.get_cell_formula(0, 1, 1).unwrap(),
|
||||
Some("=SIN(1)".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.cell_formula(0, 2, 1).unwrap(),
|
||||
model.get_cell_formula(0, 2, 1).unwrap(),
|
||||
Some("=SIN(2)".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,22 +2,22 @@
|
||||
use crate::test::util::new_empty_model;
|
||||
|
||||
#[test]
|
||||
fn test_delete_cell_non_existing_sheet() {
|
||||
fn test_cell_clear_all_non_existing_sheet() {
|
||||
let mut model = new_empty_model();
|
||||
assert_eq!(
|
||||
model.delete_cell(13, 1, 1),
|
||||
model.cell_clear_all(13, 1, 1),
|
||||
Err("Invalid sheet index".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_cell_unset_cell() {
|
||||
fn test_cell_clear_all_unset_cell() {
|
||||
let mut model = new_empty_model();
|
||||
assert!(model.delete_cell(0, 1, 1).is_ok());
|
||||
assert!(model.cell_clear_all(0, 1, 1).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_cell_with_value() {
|
||||
fn test_cell_clear_all_with_value() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("A1", "hello");
|
||||
model.evaluate();
|
||||
@@ -25,7 +25,7 @@ fn test_delete_cell_with_value() {
|
||||
assert_eq!(model._get_text_at(0, 1, 1), "hello");
|
||||
assert_eq!(model.is_empty_cell(0, 1, 1), Ok(false));
|
||||
|
||||
model.delete_cell(0, 1, 1).unwrap();
|
||||
model.cell_clear_all(0, 1, 1).unwrap();
|
||||
model.evaluate();
|
||||
|
||||
assert_eq!(model._get_text_at(0, 1, 1), "");
|
||||
@@ -33,7 +33,7 @@ fn test_delete_cell_with_value() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_cell_referenced_elsewhere() {
|
||||
fn test_cell_clear_all_referenced_elsewhere() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("A1", "35");
|
||||
model._set("A2", "=2*A1");
|
||||
@@ -44,7 +44,7 @@ fn test_delete_cell_referenced_elsewhere() {
|
||||
assert_eq!(model.is_empty_cell(0, 1, 1), Ok(false));
|
||||
assert_eq!(model.is_empty_cell(0, 2, 1), Ok(false));
|
||||
|
||||
model.delete_cell(0, 1, 1).unwrap();
|
||||
model.cell_clear_all(0, 1, 1).unwrap();
|
||||
model.evaluate();
|
||||
|
||||
assert_eq!(model._get_text_at(0, 1, 1), "");
|
||||
@@ -16,7 +16,7 @@ fn test_is_empty_cell() {
|
||||
assert!(model.is_empty_cell(0, 3, 1).unwrap());
|
||||
model.set_user_input(0, 3, 1, "Hello World".to_string());
|
||||
assert!(!model.is_empty_cell(0, 3, 1).unwrap());
|
||||
model.set_cell_empty(0, 3, 1).unwrap();
|
||||
model.cell_clear_contents(0, 3, 1).unwrap();
|
||||
assert!(model.is_empty_cell(0, 3, 1).unwrap());
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ fn test_sheet_markup() {
|
||||
model.set_cell_style(0, 4, 1, &style).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
model.sheet_markup(0),
|
||||
model.get_sheet_markup(0),
|
||||
Ok("**Item**|**Cost**\nRent|$600\nElectricity|$200\n**Total**|=SUM(B2:B3)".to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -236,3 +236,11 @@ fn test_delete_sheet_by_index() {
|
||||
assert_eq!(model.workbook.get_worksheet_names(), ["Sheet2"]);
|
||||
assert_eq!(model._get_text("Sheet2!A1"), "#REF!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_sheet_error() {
|
||||
let mut model = new_empty_model();
|
||||
model.new_sheet();
|
||||
assert!(model.delete_sheet(2).is_err());
|
||||
assert!(model.delete_sheet(1).is_ok());
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::{test::util::new_empty_model, types::SheetInfo};
|
||||
#[test]
|
||||
fn workbook_worksheets_info() {
|
||||
let model = new_empty_model();
|
||||
let sheets_info = model.workbook.get_worksheets_info();
|
||||
let sheets_info = model.get_sheets_info();
|
||||
assert_eq!(
|
||||
sheets_info[0],
|
||||
SheetInfo {
|
||||
|
||||
@@ -39,7 +39,7 @@ fn test_worksheet_dimension_single_cell() {
|
||||
fn test_worksheet_dimension_single_cell_set_empty() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("W11", "1");
|
||||
model.set_cell_empty(0, 11, 23).unwrap();
|
||||
model.cell_clear_contents(0, 11, 23).unwrap();
|
||||
assert_eq!(
|
||||
model.workbook.worksheet(0).unwrap().dimension(),
|
||||
WorksheetDimension {
|
||||
@@ -55,7 +55,7 @@ fn test_worksheet_dimension_single_cell_set_empty() {
|
||||
fn test_worksheet_dimension_single_cell_deleted() {
|
||||
let mut model = new_empty_model();
|
||||
model._set("W11", "1");
|
||||
model.delete_cell(0, 11, 23).unwrap();
|
||||
model.cell_clear_all(0, 11, 23).unwrap();
|
||||
assert_eq!(
|
||||
model.workbook.worksheet(0).unwrap().dimension(),
|
||||
WorksheetDimension {
|
||||
@@ -75,7 +75,7 @@ fn test_worksheet_dimension_multiple_cells() {
|
||||
model._set("AA17", "1");
|
||||
model._set("G17", "1");
|
||||
model._set("B19", "1");
|
||||
model.delete_cell(0, 11, 23).unwrap();
|
||||
model.cell_clear_all(0, 11, 23).unwrap();
|
||||
assert_eq!(
|
||||
model.workbook.worksheet(0).unwrap().dimension(),
|
||||
WorksheetDimension {
|
||||
|
||||
9
base/src/test/user_model/mod.rs
Normal file
9
base/src/test/user_model/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
mod test_add_delete_sheets;
|
||||
mod test_clear_cells;
|
||||
mod test_diff_queue;
|
||||
mod test_evaluation;
|
||||
mod test_general;
|
||||
mod test_rename_sheet;
|
||||
mod test_row_column;
|
||||
mod test_styles;
|
||||
mod test_undo_redo;
|
||||
58
base/src/test/user_model/test_add_delete_sheets.rs
Normal file
58
base/src/test/user_model/test_add_delete_sheets.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use crate::{constants::DEFAULT_COLUMN_WIDTH, UserModel};
|
||||
|
||||
#[test]
|
||||
fn add_undo_redo() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model.new_sheet();
|
||||
model.set_user_input(1, 1, 1, "=1 + 1").unwrap();
|
||||
model.set_user_input(1, 1, 2, "=A1*3").unwrap();
|
||||
model
|
||||
.set_column_width(1, 5, 5.0 * DEFAULT_COLUMN_WIDTH)
|
||||
.unwrap();
|
||||
model.new_sheet();
|
||||
model.set_user_input(2, 1, 1, "=Sheet2!B1").unwrap();
|
||||
|
||||
model.undo().unwrap();
|
||||
model.undo().unwrap();
|
||||
|
||||
assert!(model.get_formatted_cell_value(2, 1, 1).is_err());
|
||||
|
||||
model.redo().unwrap();
|
||||
model.redo().unwrap();
|
||||
|
||||
assert_eq!(model.get_formatted_cell_value(2, 1, 1), Ok("6".to_string()));
|
||||
|
||||
model.delete_sheet(1).unwrap();
|
||||
|
||||
assert!(!model.can_undo());
|
||||
assert!(!model.can_redo());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_sheet_propagates() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model.new_sheet();
|
||||
|
||||
let send_queue = model.flush_send_queue();
|
||||
|
||||
let mut model2 = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
let sheets_info = model2.get_sheets_info();
|
||||
assert_eq!(sheets_info.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_sheet_propagates() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model.new_sheet();
|
||||
model.delete_sheet(0).unwrap();
|
||||
|
||||
let send_queue = model.flush_send_queue();
|
||||
|
||||
let mut model2 = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
let sheets_info = model2.get_sheets_info();
|
||||
assert_eq!(sheets_info.len(), 1);
|
||||
}
|
||||
91
base/src/test/user_model/test_clear_cells.rs
Normal file
91
base/src/test/user_model/test_clear_cells.rs
Normal file
@@ -0,0 +1,91 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use crate::{expressions::types::Area, UserModel};
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model.set_user_input(0, 1, 1, "100$").unwrap();
|
||||
model
|
||||
.range_clear_contents(&Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("".to_string()));
|
||||
model.undo().unwrap();
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 1, 1),
|
||||
Ok("100$".to_string())
|
||||
);
|
||||
model.redo().unwrap();
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("".to_string()));
|
||||
|
||||
model.set_user_input(0, 1, 1, "300").unwrap();
|
||||
// clear contents keeps the formatting
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 1, 1),
|
||||
Ok("300$".to_string())
|
||||
);
|
||||
|
||||
model
|
||||
.range_clear_all(&Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("".to_string()));
|
||||
model.undo().unwrap();
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 1, 1),
|
||||
Ok("300$".to_string())
|
||||
);
|
||||
model.redo().unwrap();
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("".to_string()));
|
||||
model.set_user_input(0, 1, 1, "400").unwrap();
|
||||
// clear contents keeps the formatting
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 1, 1),
|
||||
Ok("400".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clear_empty_cell() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model
|
||||
.range_clear_contents(&Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("".to_string()));
|
||||
model.undo().unwrap();
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clear_all_empty_cell() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model
|
||||
.range_clear_all(&Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("".to_string()));
|
||||
model.undo().unwrap();
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("".to_string()));
|
||||
}
|
||||
159
base/src/test/user_model/test_diff_queue.rs
Normal file
159
base/src/test/user_model/test_diff_queue.rs
Normal file
@@ -0,0 +1,159 @@
|
||||
use crate::{
|
||||
constants::{DEFAULT_COLUMN_WIDTH, DEFAULT_ROW_HEIGHT},
|
||||
test::util::new_empty_model,
|
||||
UserModel,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn send_queue() {
|
||||
let mut model1 = UserModel::from_model(new_empty_model());
|
||||
let width = model1.get_column_width(0, 3).unwrap() * 3.0;
|
||||
model1.set_column_width(0, 3, width).unwrap();
|
||||
model1.set_user_input(0, 1, 2, "Hello IronCalc!").unwrap();
|
||||
let send_queue = model1.flush_send_queue();
|
||||
|
||||
let mut model2 = UserModel::from_model(new_empty_model());
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
|
||||
assert_eq!(model2.get_column_width(0, 3), Ok(width));
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(0, 1, 2),
|
||||
Ok("Hello IronCalc!".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn apply_external_diffs_wrong_str() {
|
||||
let mut model1 = UserModel::from_model(new_empty_model());
|
||||
assert!(model1.apply_external_diffs("invalid").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn queue_undo_redo() {
|
||||
let mut model1 = UserModel::from_model(new_empty_model());
|
||||
let width = model1.get_column_width(0, 3).unwrap() * 3.0;
|
||||
model1.set_column_width(0, 3, width).unwrap();
|
||||
model1.set_user_input(0, 1, 2, "Hello IronCalc!").unwrap();
|
||||
assert!(model1.undo().is_ok());
|
||||
assert!(model1.redo().is_ok());
|
||||
let send_queue = model1.flush_send_queue();
|
||||
|
||||
let mut model2 = UserModel::from_model(new_empty_model());
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
|
||||
assert_eq!(model2.get_column_width(0, 3), Ok(width));
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(0, 1, 2),
|
||||
Ok("Hello IronCalc!".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn queue_undo_redo_multiple() {
|
||||
let mut model1 = UserModel::from_model(new_empty_model());
|
||||
|
||||
// do a bunch of things
|
||||
model1.set_frozen_columns_count(0, 5).unwrap();
|
||||
model1.set_frozen_rows_count(0, 6).unwrap();
|
||||
model1.set_column_width(0, 7, 300.0).unwrap();
|
||||
model1.set_row_height(0, 23, 123.0).unwrap();
|
||||
model1.set_user_input(0, 55, 55, "=42+8").unwrap();
|
||||
|
||||
for row in 1..5 {
|
||||
model1.set_user_input(0, row, 17, "=ROW()").unwrap();
|
||||
}
|
||||
|
||||
model1.insert_row(0, 3).unwrap();
|
||||
model1.insert_row(0, 3).unwrap();
|
||||
|
||||
// undo al of them
|
||||
while model1.can_undo() {
|
||||
model1.undo().unwrap();
|
||||
}
|
||||
|
||||
// check it is an empty model
|
||||
assert_eq!(model1.get_frozen_columns_count(0), Ok(0));
|
||||
assert_eq!(model1.get_frozen_rows_count(0), Ok(0));
|
||||
assert_eq!(model1.get_column_width(0, 7), Ok(DEFAULT_COLUMN_WIDTH));
|
||||
assert_eq!(
|
||||
model1.get_formatted_cell_value(0, 55, 55),
|
||||
Ok("".to_string())
|
||||
);
|
||||
assert_eq!(model1.get_row_height(0, 23), Ok(DEFAULT_ROW_HEIGHT));
|
||||
assert_eq!(
|
||||
model1.get_formatted_cell_value(0, 57, 55),
|
||||
Ok("".to_string())
|
||||
);
|
||||
assert_eq!(model1.get_row_height(0, 25), Ok(DEFAULT_ROW_HEIGHT));
|
||||
|
||||
// redo all of them
|
||||
while model1.can_redo() {
|
||||
model1.redo().unwrap();
|
||||
}
|
||||
|
||||
// now send all this to a new model
|
||||
let send_queue = model1.flush_send_queue();
|
||||
let mut model2 = UserModel::from_model(new_empty_model());
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
|
||||
// Check everything is as expected
|
||||
assert_eq!(model2.get_frozen_columns_count(0), Ok(5));
|
||||
assert_eq!(model2.get_frozen_rows_count(0), Ok(6));
|
||||
assert_eq!(model2.get_column_width(0, 7), Ok(300.0));
|
||||
// I inserted two rows
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(0, 57, 55),
|
||||
Ok("50".to_string())
|
||||
);
|
||||
assert_eq!(model2.get_row_height(0, 25), Ok(123.0));
|
||||
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(0, 1, 17),
|
||||
Ok("1".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(0, 2, 17),
|
||||
Ok("2".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(0, 3, 17),
|
||||
Ok("".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(0, 4, 17),
|
||||
Ok("".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(0, 5, 17),
|
||||
Ok("5".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(0, 6, 17),
|
||||
Ok("6".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_sheet() {
|
||||
let mut model1 = UserModel::from_model(new_empty_model());
|
||||
model1.new_sheet();
|
||||
model1.set_user_input(0, 1, 1, "42").unwrap();
|
||||
model1.set_user_input(1, 1, 1, "=Sheet1!A1*2").unwrap();
|
||||
|
||||
let send_queue = model1.flush_send_queue();
|
||||
let mut model2 = UserModel::from_model(new_empty_model());
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(1, 1, 1),
|
||||
Ok("84".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_diffs_handled() {
|
||||
let mut model = UserModel::from_model(new_empty_model());
|
||||
assert!(model.apply_external_diffs("Hello world").is_err());
|
||||
}
|
||||
31
base/src/test/user_model/test_evaluation.rs
Normal file
31
base/src/test/user_model/test_evaluation.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use crate::UserModel;
|
||||
|
||||
#[test]
|
||||
fn model_evaluates_automatically() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model.set_user_input(0, 1, 1, "=1 + 1").unwrap();
|
||||
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("2".to_string()));
|
||||
assert_eq!(model.get_cell_content(0, 1, 1), Ok("=1+1".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pause_resume_evaluation() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model.pause_evaluation();
|
||||
model.set_user_input(0, 1, 1, "=1+1").unwrap();
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 1, 1),
|
||||
Ok("#ERROR!".to_string())
|
||||
);
|
||||
model.evaluate();
|
||||
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("2".to_string()));
|
||||
assert_eq!(model.get_cell_content(0, 1, 1), Ok("=1+1".to_string()));
|
||||
|
||||
model.resume_evaluation();
|
||||
model.set_user_input(0, 2, 1, "=1+4").unwrap();
|
||||
assert_eq!(model.get_formatted_cell_value(0, 2, 1), Ok("5".to_string()));
|
||||
}
|
||||
103
base/src/test/user_model/test_general.rs
Normal file
103
base/src/test/user_model/test_general.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use crate::constants::{LAST_COLUMN, LAST_ROW};
|
||||
use crate::test::util::new_empty_model;
|
||||
use crate::UserModel;
|
||||
|
||||
#[test]
|
||||
fn set_user_input_errors() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
// Wrong sheet
|
||||
assert!(model.set_user_input(1, 1, 1, "1").is_err());
|
||||
// Wrong row
|
||||
assert!(model.set_user_input(0, 0, 1, "1").is_err());
|
||||
// Wrong column
|
||||
assert!(model.set_user_input(0, 1, 0, "1").is_err());
|
||||
// row too large
|
||||
assert!(model.set_user_input(0, LAST_ROW, 1, "1").is_ok());
|
||||
assert!(model.set_user_input(0, LAST_ROW + 1, 1, "1").is_err());
|
||||
// column too large
|
||||
assert!(model.set_user_input(0, 1, LAST_COLUMN, "1").is_ok());
|
||||
assert!(model.set_user_input(0, 1, LAST_COLUMN + 1, "1").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_remove_rows() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
let height = model.get_row_height(0, 5).unwrap();
|
||||
|
||||
// Insert some data in row 5 (and change the style)
|
||||
assert!(model.set_user_input(0, 5, 1, "100$").is_ok());
|
||||
// Change the height of the column
|
||||
assert!(model.set_row_height(0, 5, 3.0 * height).is_ok());
|
||||
|
||||
// remove the row
|
||||
assert!(model.delete_row(0, 5).is_ok());
|
||||
// Row 5 has now the normal height
|
||||
assert_eq!(model.get_row_height(0, 5), Ok(height));
|
||||
// There is no value in A5
|
||||
assert_eq!(model.get_formatted_cell_value(0, 5, 1), Ok("".to_string()));
|
||||
// Setting a value will not format it
|
||||
assert!(model.set_user_input(0, 5, 1, "125").is_ok());
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 5, 1),
|
||||
Ok("125".to_string())
|
||||
);
|
||||
|
||||
// undo twice
|
||||
assert!(model.undo().is_ok());
|
||||
assert!(model.undo().is_ok());
|
||||
|
||||
assert_eq!(model.get_row_height(0, 5), Ok(3.0 * height));
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 5, 1),
|
||||
Ok("100$".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_remove_columns() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
// column E
|
||||
let column_width = model.get_column_width(0, 5).unwrap();
|
||||
println!("{column_width}");
|
||||
|
||||
// Insert some data in row 5 (and change the style) in E1
|
||||
assert!(model.set_user_input(0, 1, 5, "100$").is_ok());
|
||||
// Change the width of the column
|
||||
assert!(model.set_column_width(0, 5, 3.0 * column_width).is_ok());
|
||||
assert_eq!(model.get_column_width(0, 5).unwrap(), 3.0 * column_width);
|
||||
|
||||
// remove the column
|
||||
assert!(model.delete_column(0, 5).is_ok());
|
||||
// Column 5 has now the normal width
|
||||
assert_eq!(model.get_column_width(0, 5), Ok(column_width));
|
||||
// There is no value in E5
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 5), Ok("".to_string()));
|
||||
// Setting a value will not format it
|
||||
assert!(model.set_user_input(0, 1, 5, "125").is_ok());
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 1, 5),
|
||||
Ok("125".to_string())
|
||||
);
|
||||
|
||||
// undo twice (set_user_input and delete_column)
|
||||
assert!(model.undo().is_ok());
|
||||
assert!(model.undo().is_ok());
|
||||
|
||||
assert_eq!(model.get_column_width(0, 5), Ok(3.0 * column_width));
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 1, 5),
|
||||
Ok("100$".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_remove_cell() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let (sheet, row, column) = (0, 1, 1);
|
||||
model.set_user_input(sheet, row, column, "100$").unwrap();
|
||||
}
|
||||
39
base/src/test/user_model/test_rename_sheet.rs
Normal file
39
base/src/test/user_model/test_rename_sheet.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use crate::UserModel;
|
||||
|
||||
#[test]
|
||||
fn basic_rename() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model.rename_sheet(0, "NewSheet").unwrap();
|
||||
assert_eq!(model.get_sheets_info()[0].name, "NewSheet");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn undo_redo() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model.rename_sheet(0, "NewSheet").unwrap();
|
||||
model.undo().unwrap();
|
||||
assert_eq!(model.get_sheets_info()[0].name, "Sheet1");
|
||||
model.redo().unwrap();
|
||||
assert_eq!(model.get_sheets_info()[0].name, "NewSheet");
|
||||
|
||||
let send_queue = model.flush_send_queue();
|
||||
|
||||
let mut model2 = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
assert_eq!(model.get_sheets_info()[0].name, "NewSheet");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn errors() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
assert_eq!(
|
||||
model.rename_sheet(0, ""),
|
||||
Err("Invalid name for a sheet: ''.".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.rename_sheet(1, "Hello"),
|
||||
Err("Invalid sheet index".to_string())
|
||||
);
|
||||
}
|
||||
156
base/src/test/user_model/test_row_column.rs
Normal file
156
base/src/test/user_model/test_row_column.rs
Normal file
@@ -0,0 +1,156 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use crate::{
|
||||
constants::{DEFAULT_COLUMN_WIDTH, DEFAULT_ROW_HEIGHT, LAST_COLUMN},
|
||||
test::util::new_empty_model,
|
||||
UserModel,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn simple_insert_row() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
let (sheet, column) = (0, 5);
|
||||
for row in 1..5 {
|
||||
assert!(model.set_user_input(sheet, row, column, "123").is_ok());
|
||||
}
|
||||
assert!(model.insert_row(sheet, 3).is_ok());
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(sheet, 3, column).unwrap(),
|
||||
""
|
||||
);
|
||||
|
||||
assert!(model.undo().is_ok());
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(sheet, 3, column).unwrap(),
|
||||
"123"
|
||||
);
|
||||
assert!(model.redo().is_ok());
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(sheet, 3, column).unwrap(),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_insert_column() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
let (sheet, row) = (0, 5);
|
||||
for column in 1..5 {
|
||||
assert!(model.set_user_input(sheet, row, column, "123").is_ok());
|
||||
}
|
||||
assert!(model.insert_column(sheet, 3).is_ok());
|
||||
assert_eq!(model.get_formatted_cell_value(sheet, row, 3).unwrap(), "");
|
||||
|
||||
assert!(model.undo().is_ok());
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(sheet, row, 3).unwrap(),
|
||||
"123"
|
||||
);
|
||||
assert!(model.redo().is_ok());
|
||||
assert_eq!(model.get_formatted_cell_value(sheet, row, 3).unwrap(), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_delete_column() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
model.set_user_input(0, 1, 5, "3").unwrap();
|
||||
model.set_user_input(0, 2, 5, "=E1*2").unwrap();
|
||||
model
|
||||
.set_column_width(0, 5, DEFAULT_COLUMN_WIDTH * 3.0)
|
||||
.unwrap();
|
||||
|
||||
model.delete_column(0, 5).unwrap();
|
||||
|
||||
assert_eq!(model.get_formatted_cell_value(0, 2, 5), Ok("".to_string()));
|
||||
assert_eq!(model.get_column_width(0, 5), Ok(DEFAULT_COLUMN_WIDTH));
|
||||
|
||||
model.undo().unwrap();
|
||||
|
||||
assert_eq!(model.get_formatted_cell_value(0, 2, 5), Ok("6".to_string()));
|
||||
assert_eq!(model.get_column_width(0, 5), Ok(DEFAULT_COLUMN_WIDTH * 3.0));
|
||||
|
||||
let send_queue = model.flush_send_queue();
|
||||
|
||||
let mut model2 = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(0, 2, 5),
|
||||
Ok("6".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model2.get_column_width(0, 5),
|
||||
Ok(DEFAULT_COLUMN_WIDTH * 3.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_column_errors() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
assert_eq!(
|
||||
model.delete_column(1, 1),
|
||||
Err("Invalid sheet index".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.delete_column(0, 0),
|
||||
Err("Column number '0' is not valid.".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.delete_column(0, LAST_COLUMN + 1),
|
||||
Err("Column number '16385' is not valid.".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(model.delete_column(0, LAST_COLUMN), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_delete_row() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
model.set_user_input(0, 15, 4, "3").unwrap();
|
||||
model.set_user_input(0, 15, 6, "=D15*2").unwrap();
|
||||
|
||||
model
|
||||
.set_row_height(0, 15, DEFAULT_ROW_HEIGHT * 3.0)
|
||||
.unwrap();
|
||||
|
||||
model.delete_row(0, 15).unwrap();
|
||||
|
||||
assert_eq!(model.get_formatted_cell_value(0, 15, 6), Ok("".to_string()));
|
||||
assert_eq!(model.get_row_height(0, 15), Ok(DEFAULT_ROW_HEIGHT));
|
||||
|
||||
model.undo().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 15, 6),
|
||||
Ok("6".to_string())
|
||||
);
|
||||
assert_eq!(model.get_row_height(0, 15), Ok(DEFAULT_ROW_HEIGHT * 3.0));
|
||||
|
||||
let send_queue = model.flush_send_queue();
|
||||
|
||||
let mut model2 = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
model2.get_formatted_cell_value(0, 15, 6),
|
||||
Ok("6".to_string())
|
||||
);
|
||||
assert_eq!(model2.get_row_height(0, 15), Ok(DEFAULT_ROW_HEIGHT * 3.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_delete_row_no_style() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
model.set_user_input(0, 15, 4, "3").unwrap();
|
||||
model.set_user_input(0, 15, 6, "=D15*2").unwrap();
|
||||
model.delete_row(0, 15).unwrap();
|
||||
|
||||
assert_eq!(model.get_formatted_cell_value(0, 15, 6), Ok("".to_string()));
|
||||
}
|
||||
711
base/src/test/user_model/test_styles.rs
Normal file
711
base/src/test/user_model/test_styles.rs
Normal file
@@ -0,0 +1,711 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use crate::{
|
||||
expressions::types::Area,
|
||||
types::{Alignment, BorderItem, BorderStyle, HorizontalAlignment, VerticalAlignment},
|
||||
UserModel,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn basic_fonts() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert!(!style.font.i);
|
||||
assert!(!style.font.b);
|
||||
assert!(!style.font.u);
|
||||
assert!(!style.font.strike);
|
||||
assert_eq!(style.font.color, Some("#000000".to_owned()));
|
||||
|
||||
// bold
|
||||
model.update_range_style(&range, "font.b", "true").unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert!(style.font.b);
|
||||
|
||||
// italics
|
||||
model.update_range_style(&range, "font.i", "true").unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert!(style.font.i);
|
||||
|
||||
// underline
|
||||
model.update_range_style(&range, "font.u", "true").unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert!(style.font.u);
|
||||
|
||||
// strike
|
||||
model
|
||||
.update_range_style(&range, "font.strike", "true")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert!(style.font.strike);
|
||||
|
||||
// color
|
||||
model
|
||||
.update_range_style(&range, "font.color", "#F1F1F1")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(style.font.color, Some("#F1F1F1".to_owned()));
|
||||
|
||||
while model.can_undo() {
|
||||
model.undo().unwrap();
|
||||
}
|
||||
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert!(!style.font.i);
|
||||
assert!(!style.font.b);
|
||||
assert!(!style.font.u);
|
||||
assert!(!style.font.strike);
|
||||
assert_eq!(style.font.color, Some("#000000".to_owned()));
|
||||
|
||||
while model.can_redo() {
|
||||
model.redo().unwrap();
|
||||
}
|
||||
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert!(style.font.i);
|
||||
assert!(style.font.b);
|
||||
assert!(style.font.u);
|
||||
assert!(style.font.strike);
|
||||
assert_eq!(style.font.color, Some("#F1F1F1".to_owned()));
|
||||
|
||||
let send_queue = model.flush_send_queue();
|
||||
|
||||
let mut model2 = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
|
||||
let style = model2.get_cell_style(0, 1, 1).unwrap();
|
||||
assert!(style.font.i);
|
||||
assert!(style.font.b);
|
||||
assert!(style.font.u);
|
||||
assert!(style.font.strike);
|
||||
assert_eq!(style.font.color, Some("#F1F1F1".to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn font_errors() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "font.b", "True"),
|
||||
Err("Invalid value for boolean: 'True'.".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "font.i", "FALSE"),
|
||||
Err("Invalid value for boolean: 'FALSE'.".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "font.bold", "true"),
|
||||
Err("Invalid style path: 'font.bold'.".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "font.strike", ""),
|
||||
Err("Invalid value for boolean: ''.".to_string())
|
||||
);
|
||||
// There is no cast for booleans
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "font.b", "1"),
|
||||
Err("Invalid value for boolean: '1'.".to_string())
|
||||
);
|
||||
// colors don't work by name
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "font.color", "blue"),
|
||||
Err("Invalid color: 'blue'.".to_string())
|
||||
);
|
||||
// No short form
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "font.color", "#FFF"),
|
||||
Err("Invalid color: '#FFF'.".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_fill() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(style.fill.bg_color, None);
|
||||
|
||||
// bg_color
|
||||
model
|
||||
.update_range_style(&range, "fill.bg_color", "#F2F2F2")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(style.fill.bg_color, Some("#F2F2F2".to_owned()));
|
||||
|
||||
let send_queue = model.flush_send_queue();
|
||||
|
||||
let mut model2 = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
|
||||
let style = model2.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(style.fill.bg_color, Some("#F2F2F2".to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fill_errors() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
assert!(model
|
||||
.update_range_style(&range, "fill.bg_color", "#FFF")
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_format() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(style.num_fmt, "general");
|
||||
|
||||
model
|
||||
.update_range_style(&range, "num_fmt", "$#,##0.0000")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(style.num_fmt, "$#,##0.0000");
|
||||
|
||||
model.undo().unwrap();
|
||||
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(style.num_fmt, "general");
|
||||
|
||||
model.redo().unwrap();
|
||||
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(style.num_fmt, "$#,##0.0000");
|
||||
|
||||
let send_queue = model.flush_send_queue();
|
||||
|
||||
let mut model2 = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
|
||||
let style = model2.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(style.num_fmt, "$#,##0.0000");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_borders() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
model
|
||||
.update_range_style(&range, "border.left", "thin,#F1F1F1")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.left,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Thin,
|
||||
color: Some("#F1F1F1".to_owned()),
|
||||
})
|
||||
);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "border.left", "thin,")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.left,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Thin,
|
||||
color: None,
|
||||
})
|
||||
);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "border.right", "dotted,#F1F1F2")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.right,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Dotted,
|
||||
color: Some("#F1F1F2".to_owned()),
|
||||
})
|
||||
);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "border.top", "double,#F1F1F3")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.top,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Double,
|
||||
color: Some("#F1F1F3".to_owned()),
|
||||
})
|
||||
);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "border.bottom", "medium,#F1F1F4")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.bottom,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Medium,
|
||||
color: Some("#F1F1F4".to_owned()),
|
||||
})
|
||||
);
|
||||
|
||||
while model.can_undo() {
|
||||
model.undo().unwrap();
|
||||
}
|
||||
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(style.border.left, None);
|
||||
assert_eq!(style.border.top, None);
|
||||
assert_eq!(style.border.right, None);
|
||||
assert_eq!(style.border.bottom, None);
|
||||
|
||||
while model.can_redo() {
|
||||
model.redo().unwrap();
|
||||
}
|
||||
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.left,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Thin,
|
||||
color: None,
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
style.border.right,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Dotted,
|
||||
color: Some("#F1F1F2".to_owned()),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
style.border.top,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Double,
|
||||
color: Some("#F1F1F3".to_owned()),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
style.border.bottom,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Medium,
|
||||
color: Some("#F1F1F4".to_owned()),
|
||||
})
|
||||
);
|
||||
|
||||
let send_queue = model.flush_send_queue();
|
||||
|
||||
let mut model2 = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
model2.apply_external_diffs(&send_queue).unwrap();
|
||||
|
||||
let style = model2.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.left,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Thin,
|
||||
color: None,
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
style.border.right,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Dotted,
|
||||
color: Some("#F1F1F2".to_owned()),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
style.border.top,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Double,
|
||||
color: Some("#F1F1F3".to_owned()),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
style.border.bottom,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Medium,
|
||||
color: Some("#F1F1F4".to_owned()),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_alignment() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
let alignment = model.get_cell_style(0, 1, 1).unwrap().alignment;
|
||||
assert_eq!(alignment, None);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "alignment.horizontal", "center")
|
||||
.unwrap();
|
||||
let alignment = model.get_cell_style(0, 1, 1).unwrap().alignment;
|
||||
assert_eq!(
|
||||
alignment,
|
||||
Some(Alignment {
|
||||
horizontal: HorizontalAlignment::Center,
|
||||
vertical: VerticalAlignment::Bottom,
|
||||
wrap_text: false
|
||||
})
|
||||
);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "alignment.horizontal", "centerContinuous")
|
||||
.unwrap();
|
||||
let alignment = model.get_cell_style(0, 1, 1).unwrap().alignment;
|
||||
assert_eq!(
|
||||
alignment,
|
||||
Some(Alignment {
|
||||
horizontal: HorizontalAlignment::CenterContinuous,
|
||||
vertical: VerticalAlignment::Bottom,
|
||||
wrap_text: false
|
||||
})
|
||||
);
|
||||
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 2,
|
||||
column: 2,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
model
|
||||
.update_range_style(&range, "alignment.vertical", "distributed")
|
||||
.unwrap();
|
||||
let alignment = model.get_cell_style(0, 2, 2).unwrap().alignment;
|
||||
assert_eq!(
|
||||
alignment,
|
||||
Some(Alignment {
|
||||
horizontal: HorizontalAlignment::General,
|
||||
vertical: VerticalAlignment::Distributed,
|
||||
wrap_text: false
|
||||
})
|
||||
);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "alignment.vertical", "justify")
|
||||
.unwrap();
|
||||
let alignment = model.get_cell_style(0, 2, 2).unwrap().alignment;
|
||||
assert_eq!(
|
||||
alignment,
|
||||
Some(Alignment {
|
||||
horizontal: HorizontalAlignment::General,
|
||||
vertical: VerticalAlignment::Justify,
|
||||
wrap_text: false
|
||||
})
|
||||
);
|
||||
|
||||
model.update_range_style(&range, "alignment", "").unwrap();
|
||||
let alignment = model.get_cell_style(0, 2, 2).unwrap().alignment;
|
||||
assert_eq!(alignment, None);
|
||||
|
||||
model.undo().unwrap();
|
||||
|
||||
let alignment = model.get_cell_style(0, 2, 2).unwrap().alignment;
|
||||
assert_eq!(
|
||||
alignment,
|
||||
Some(Alignment {
|
||||
horizontal: HorizontalAlignment::General,
|
||||
vertical: VerticalAlignment::Justify,
|
||||
wrap_text: false
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alignment_errors() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "alignment", "some"),
|
||||
Err("Alignment must be empty, but found: 'some'.".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "alignment.vertical", "justified"),
|
||||
Err("Invalid value for vertical alignment: 'justified'.".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "alignment.horizontal", "unjustified"),
|
||||
Err("Invalid value for horizontal alignment: 'unjustified'.".to_string())
|
||||
);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "alignment.vertical", "justify")
|
||||
.unwrap();
|
||||
|
||||
// Also fail if there is an alignment
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "alignment", "some"),
|
||||
Err("Alignment must be empty, but found: 'some'.".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "alignment.vertical", "justified"),
|
||||
Err("Invalid value for vertical alignment: 'justified'.".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "alignment.horizontal", "unjustified"),
|
||||
Err("Invalid value for horizontal alignment: 'unjustified'.".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_wrap_text() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "alignment.wrap_text", "T"),
|
||||
Err("Invalid value for boolean: 'T'.".to_string())
|
||||
);
|
||||
model
|
||||
.update_range_style(&range, "alignment.wrap_text", "true")
|
||||
.unwrap();
|
||||
let alignment = model.get_cell_style(0, 1, 1).unwrap().alignment;
|
||||
assert_eq!(
|
||||
alignment,
|
||||
Some(Alignment {
|
||||
horizontal: HorizontalAlignment::General,
|
||||
vertical: VerticalAlignment::Bottom,
|
||||
wrap_text: true
|
||||
})
|
||||
);
|
||||
model.undo().unwrap();
|
||||
let alignment = model.get_cell_style(0, 1, 1).unwrap().alignment;
|
||||
assert_eq!(alignment, None);
|
||||
|
||||
model.redo().unwrap();
|
||||
|
||||
let alignment = model.get_cell_style(0, 1, 1).unwrap().alignment;
|
||||
assert_eq!(
|
||||
alignment,
|
||||
Some(Alignment {
|
||||
horizontal: HorizontalAlignment::General,
|
||||
vertical: VerticalAlignment::Bottom,
|
||||
wrap_text: true
|
||||
})
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "alignment.wrap_text", "True"),
|
||||
Err("Invalid value for boolean: 'True'.".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn more_basic_borders() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
model
|
||||
.update_range_style(&range, "border.left", "thick,#F1F1F1")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.left,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::Thick,
|
||||
color: Some("#F1F1F1".to_owned()),
|
||||
})
|
||||
);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "border.left", "slantDashDot,#F1F1F1")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.left,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::SlantDashDot,
|
||||
color: Some("#F1F1F1".to_owned()),
|
||||
})
|
||||
);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "border.left", "mediumDashDot,#F1F1F1")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.left,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::MediumDashDot,
|
||||
color: Some("#F1F1F1".to_owned()),
|
||||
})
|
||||
);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "border.left", "mediumDashDotDot,#F1F1F1")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.left,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::MediumDashDotDot,
|
||||
color: Some("#F1F1F1".to_owned()),
|
||||
})
|
||||
);
|
||||
|
||||
model
|
||||
.update_range_style(&range, "border.left", "mediumDashed,#F1F1F1")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.left,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::MediumDashed,
|
||||
color: Some("#F1F1F1".to_owned()),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn border_errors() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "border.lef", "thick,#F1F1F1"),
|
||||
Err("Invalid style path: 'border.lef'.".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "border.left", "thic,#F1F1F1"),
|
||||
Err("Invalid border style: 'thic'.".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "border.left", "thick,#F1F1F"),
|
||||
Err("Invalid color: '#F1F1F'.".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "border.left", " "),
|
||||
Err("Invalid border value: ' '.".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
model.update_range_style(&range, "border.left", "thick,#F1F1F1,thin"),
|
||||
Err("Invalid border value: 'thick,#F1F1F1,thin'.".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_removes_border() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
model
|
||||
.update_range_style(&range, "border.left", "mediumDashDotDot,#F1F1F1")
|
||||
.unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(
|
||||
style.border.left,
|
||||
Some(BorderItem {
|
||||
style: BorderStyle::MediumDashDotDot,
|
||||
color: Some("#F1F1F1".to_owned()),
|
||||
})
|
||||
);
|
||||
|
||||
model.update_range_style(&range, "border.left", "").unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert_eq!(style.border.left, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn false_removes_value() {
|
||||
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||
let range = Area {
|
||||
sheet: 0,
|
||||
row: 1,
|
||||
column: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
// bold
|
||||
model.update_range_style(&range, "font.b", "true").unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert!(style.font.b);
|
||||
|
||||
model.update_range_style(&range, "font.b", "false").unwrap();
|
||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||
assert!(!style.font.b);
|
||||
}
|
||||
66
base/src/test/user_model/test_undo_redo.rs
Normal file
66
base/src/test/user_model/test_undo_redo.rs
Normal file
@@ -0,0 +1,66 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use crate::{test::util::new_empty_model, UserModel};
|
||||
|
||||
#[test]
|
||||
fn simple_undo_redo() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
// at the beginning I cannot undo or redo
|
||||
assert!(!model.can_undo());
|
||||
assert!(!model.can_redo());
|
||||
assert!(model.set_user_input(0, 1, 1, "=1+2").is_ok());
|
||||
|
||||
// Once I enter a value I can undo but not redo
|
||||
assert!(model.can_undo());
|
||||
assert!(!model.can_redo());
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("3".to_string()));
|
||||
|
||||
// If I undo, I can't undo anymore, but I can redo
|
||||
assert!(model.undo().is_ok());
|
||||
assert!(!model.can_undo());
|
||||
assert!(model.can_redo());
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("".to_string()));
|
||||
|
||||
// If I redo, I have the old value and formula
|
||||
assert!(model.redo().is_ok());
|
||||
assert_eq!(model.get_formatted_cell_value(0, 1, 1), Ok("3".to_string()));
|
||||
assert_eq!(model.get_cell_content(0, 1, 1), Ok("=1+2".to_string()));
|
||||
assert!(model.can_undo());
|
||||
assert!(!model.can_redo());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn undo_redo_respect_styles() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
assert!(model.set_user_input(0, 1, 1, "100").is_ok());
|
||||
assert!(model.set_user_input(0, 1, 1, "125$").is_ok());
|
||||
// The content of the cell is just the number 125
|
||||
assert_eq!(model.get_cell_content(0, 1, 1), Ok("125".to_string()));
|
||||
assert!(model.undo().is_ok());
|
||||
// The cell has no currency number formatting
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 1, 1),
|
||||
Ok("100".to_string())
|
||||
);
|
||||
assert_eq!(model.get_cell_content(0, 1, 1), Ok("100".to_string()));
|
||||
assert!(model.redo().is_ok());
|
||||
// The cell has the number 125 formatted as '125$'
|
||||
assert_eq!(
|
||||
model.get_formatted_cell_value(0, 1, 1),
|
||||
Ok("125$".to_string())
|
||||
);
|
||||
assert_eq!(model.get_cell_content(0, 1, 1), Ok("125".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_undo_can_redo() {
|
||||
let model = new_empty_model();
|
||||
let mut model = UserModel::from_model(model);
|
||||
assert!(!model.can_undo());
|
||||
assert!(!model.can_redo());
|
||||
|
||||
assert!(model.undo().is_ok());
|
||||
assert!(model.redo().is_ok());
|
||||
}
|
||||
@@ -32,11 +32,11 @@ impl Model {
|
||||
let cell_reference = self._parse_reference(cell);
|
||||
let column = cell_reference.column;
|
||||
let row = cell_reference.row;
|
||||
self.cell_formula(cell_reference.sheet, row, column)
|
||||
self.get_cell_formula(cell_reference.sheet, row, column)
|
||||
.unwrap()
|
||||
}
|
||||
pub fn _get_text_at(&self, sheet: u32, row: i32, column: i32) -> String {
|
||||
self.formatted_cell_value(sheet, row, column).unwrap()
|
||||
self.get_formatted_cell_value(sheet, row, column).unwrap()
|
||||
}
|
||||
pub fn _get_text(&self, cell: &str) -> String {
|
||||
let CellReferenceIndex { sheet, row, column } = self._parse_reference(cell);
|
||||
|
||||
Reference in New Issue
Block a user