From 2573f9ba276929c3c8a0eee661e50b67e3676cf0 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 20 Jun 2022 10:24:43 +0800 Subject: [PATCH] chore: separate tests from grid_test file --- .../presentation/plugins/board/board.dart | 2 +- .../rust-lib/flowy-grid/src/event_handler.rs | 2 +- .../flowy-grid/src/services/grid_editor.rs | 8 +- .../src/services/row/row_builder.rs | 14 +- .../flowy-grid/tests/grid/block_test.rs | 40 ++ .../flowy-grid/tests/grid/cell_test.rs | 48 +++ .../flowy-grid/tests/grid/field_test.rs | 113 ++++++ .../flowy-grid/tests/grid/grid_test.rs | 381 ------------------ .../rust-lib/flowy-grid/tests/grid/mod.rs | 6 +- .../flowy-grid/tests/grid/row_test.rs | 147 +++++++ .../rust-lib/flowy-grid/tests/grid/script.rs | 98 +++-- .../flowy-grid/tests/grid/setting_test.rs | 1 + .../src/revision/grid_rev.rs | 2 + .../{grid_info_rev.rs => grid_setting_rev.rs} | 8 +- .../flowy-grid-data-model/src/revision/mod.rs | 4 +- .../src/client_grid/grid_revision_pad.rs | 2 +- .../src/code_gen/protobuf_file/ast.rs | 12 +- .../src/code_gen/protobuf_file/proto_gen.rs | 2 +- .../src/code_gen/protobuf_file/proto_info.rs | 2 +- 19 files changed, 446 insertions(+), 446 deletions(-) create mode 100644 frontend/rust-lib/flowy-grid/tests/grid/block_test.rs create mode 100644 frontend/rust-lib/flowy-grid/tests/grid/cell_test.rs create mode 100644 frontend/rust-lib/flowy-grid/tests/grid/field_test.rs delete mode 100644 frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs create mode 100644 frontend/rust-lib/flowy-grid/tests/grid/row_test.rs create mode 100644 frontend/rust-lib/flowy-grid/tests/grid/setting_test.rs rename shared-lib/flowy-grid-data-model/src/revision/{grid_info_rev.rs => grid_setting_rev.rs} (91%) diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/board/board.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/board/board.dart index fb55fc70c1..041f1c4713 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/board/board.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/board/board.dart @@ -28,7 +28,7 @@ class BoardPluginBuilder implements PluginBuilder { class BoardPluginConfig implements PluginConfig { @override - bool get creatable => true; + bool get creatable => false; } class BoardPlugin extends Plugin { diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index d02b2d59ca..79181732d7 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -27,7 +27,7 @@ pub(crate) async fn get_grid_setting_handler( let grid_id: GridId = data.into_inner(); let editor = manager.open_grid(grid_id).await?; let grid_setting = editor.get_grid_setting().await?; - data_result(grid_setting) + data_result(grid_setting.into()) } #[tracing::instrument(level = "trace", skip(data, manager), err)] diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index 33d260f1d3..b7392adb6e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -262,7 +262,7 @@ impl GridRevisionEditor { let block_id = self.block_id().await?; // insert empty row below the row whose id is upper_row_id - let row_rev_ctx = CreateRowMetaBuilder::new(&field_revs).build(); + let row_rev_ctx = CreateRowRevisionBuilder::new(&field_revs).build(); let row_rev = make_row_rev_from_context(&block_id, row_rev_ctx); let row_order = RowOrder::from(&row_rev); @@ -275,7 +275,7 @@ impl GridRevisionEditor { Ok(row_order) } - pub async fn insert_rows(&self, contexts: Vec) -> FlowyResult> { + pub async fn insert_rows(&self, contexts: Vec) -> FlowyResult> { let block_id = self.block_id().await?; let mut rows_by_block_id: HashMap> = HashMap::new(); let mut row_orders = vec![]; @@ -438,10 +438,10 @@ impl GridRevisionEditor { }) } - pub async fn get_grid_setting(&self) -> FlowyResult { + pub async fn get_grid_setting(&self) -> FlowyResult { let pad_read_guard = self.grid_pad.read().await; let grid_setting_rev = pad_read_guard.get_grid_setting_rev(); - Ok(grid_setting_rev.into()) + Ok(grid_setting_rev) } pub async fn update_grid_setting(&self, params: GridSettingChangesetParams) -> FlowyResult<()> { diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs index a4f30ca1c2..83301b3fb2 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs @@ -5,19 +5,19 @@ use flowy_grid_data_model::revision::{gen_row_id, CellRevision, FieldRevision, R use indexmap::IndexMap; use std::collections::HashMap; -pub struct CreateRowMetaBuilder<'a> { +pub struct CreateRowRevisionBuilder<'a> { field_rev_map: HashMap<&'a String, &'a FieldRevision>, - payload: CreateRowMetaPayload, + payload: CreateRowRevisionPayload, } -impl<'a> CreateRowMetaBuilder<'a> { +impl<'a> CreateRowRevisionBuilder<'a> { pub fn new(fields: &'a [FieldRevision]) -> Self { let field_rev_map = fields .iter() .map(|field| (&field.id, field)) .collect::>(); - let payload = CreateRowMetaPayload { + let payload = CreateRowRevisionPayload { row_id: gen_row_id(), cell_by_field_id: Default::default(), height: DEFAULT_ROW_HEIGHT, @@ -70,12 +70,12 @@ impl<'a> CreateRowMetaBuilder<'a> { self } - pub fn build(self) -> CreateRowMetaPayload { + pub fn build(self) -> CreateRowRevisionPayload { self.payload } } -pub fn make_row_rev_from_context(block_id: &str, payload: CreateRowMetaPayload) -> RowRevision { +pub fn make_row_rev_from_context(block_id: &str, payload: CreateRowRevisionPayload) -> RowRevision { RowRevision { id: payload.row_id, block_id: block_id.to_owned(), @@ -85,7 +85,7 @@ pub fn make_row_rev_from_context(block_id: &str, payload: CreateRowMetaPayload) } } -pub struct CreateRowMetaPayload { +pub struct CreateRowRevisionPayload { pub row_id: String, pub cell_by_field_id: IndexMap, pub height: i32, diff --git a/frontend/rust-lib/flowy-grid/tests/grid/block_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/block_test.rs new file mode 100644 index 0000000000..308cf62773 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/tests/grid/block_test.rs @@ -0,0 +1,40 @@ +use crate::grid::script::EditorScript::*; +use crate::grid::script::*; +use flowy_grid_data_model::revision::{GridBlockRevision, GridBlockRevisionChangeset}; + +#[tokio::test] +async fn grid_create_block() { + let grid_block = GridBlockRevision::new(); + let scripts = vec![ + AssertBlockCount(1), + CreateBlock { block: grid_block }, + AssertBlockCount(2), + ]; + GridEditorTest::new().await.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_update_block() { + let grid_block = GridBlockRevision::new(); + let mut cloned_grid_block = grid_block.clone(); + let changeset = GridBlockRevisionChangeset { + block_id: grid_block.block_id.clone(), + start_row_index: Some(2), + row_count: Some(10), + }; + + cloned_grid_block.start_row_index = 2; + cloned_grid_block.row_count = 10; + + let scripts = vec![ + AssertBlockCount(1), + CreateBlock { block: grid_block }, + UpdateBlock { changeset }, + AssertBlockCount(2), + AssertBlockEqual { + block_index: 1, + block: cloned_grid_block, + }, + ]; + GridEditorTest::new().await.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-grid/tests/grid/cell_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/cell_test.rs new file mode 100644 index 0000000000..29fecf8f29 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/tests/grid/cell_test.rs @@ -0,0 +1,48 @@ +use crate::grid::script::EditorScript::*; +use crate::grid::script::*; +use flowy_grid::services::field::{MultiSelectTypeOption, SelectOptionCellContentChangeset, SingleSelectTypeOption}; +use flowy_grid_data_model::entities::{CellChangeset, FieldType}; + +#[tokio::test] +async fn grid_cell_update() { + let mut test = GridEditorTest::new().await; + let field_revs = &test.field_revs; + let row_revs = &test.row_revs; + let grid_blocks = &test.grid_block_revs; + + // For the moment, We only have one block to store rows + let block_id = &grid_blocks.first().unwrap().block_id; + + let mut scripts = vec![]; + for (_, row_rev) in row_revs.iter().enumerate() { + for field_rev in field_revs { + let data = match field_rev.field_type { + FieldType::RichText => "".to_string(), + FieldType::Number => "123".to_string(), + FieldType::DateTime => make_date_cell_string("123"), + FieldType::SingleSelect => { + let type_option = SingleSelectTypeOption::from(field_rev); + SelectOptionCellContentChangeset::from_insert(&type_option.options.first().unwrap().id).to_str() + } + FieldType::MultiSelect => { + let type_option = MultiSelectTypeOption::from(field_rev); + SelectOptionCellContentChangeset::from_insert(&type_option.options.first().unwrap().id).to_str() + } + FieldType::Checkbox => "1".to_string(), + FieldType::URL => "1".to_string(), + }; + + scripts.push(UpdateCell { + changeset: CellChangeset { + grid_id: block_id.to_string(), + row_id: row_rev.id.clone(), + field_id: field_rev.id.clone(), + cell_content_changeset: Some(data), + }, + is_err: false, + }); + } + } + + test.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-grid/tests/grid/field_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/field_test.rs new file mode 100644 index 0000000000..5fe5d599d6 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/tests/grid/field_test.rs @@ -0,0 +1,113 @@ +use crate::grid::script::EditorScript::*; +use crate::grid::script::*; +use flowy_grid::services::field::{SelectOption, SingleSelectTypeOption}; +use flowy_grid_data_model::entities::FieldChangesetParams; +use flowy_grid_data_model::revision::TypeOptionDataEntry; + +#[tokio::test] +async fn grid_create_field() { + let mut test = GridEditorTest::new().await; + let (params, field_rev) = create_text_field(&test.grid_id); + + let scripts = vec![ + CreateField { params }, + AssertFieldEqual { + field_index: test.field_count, + field_rev, + }, + ]; + test.run_scripts(scripts).await; + + let (params, field_rev) = create_single_select_field(&test.grid_id); + let scripts = vec![ + CreateField { params }, + AssertFieldEqual { + field_index: test.field_count, + field_rev, + }, + ]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_create_duplicate_field() { + let mut test = GridEditorTest::new().await; + let (params, _) = create_text_field(&test.grid_id); + let field_count = test.field_count; + let expected_field_count = field_count + 1; + let scripts = vec![ + CreateField { params: params.clone() }, + CreateField { params }, + AssertFieldCount(expected_field_count), + ]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_update_field_with_empty_change() { + let mut test = GridEditorTest::new().await; + let (params, field_rev) = create_single_select_field(&test.grid_id); + let changeset = FieldChangesetParams { + field_id: field_rev.id.clone(), + grid_id: test.grid_id.clone(), + ..Default::default() + }; + + let scripts = vec![ + CreateField { params }, + UpdateField { changeset }, + AssertFieldEqual { + field_index: test.field_count, + field_rev, + }, + ]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_update_field() { + let mut test = GridEditorTest::new().await; + let (params, single_select_field) = create_single_select_field(&test.grid_id); + + let mut single_select_type_option = SingleSelectTypeOption::from(&single_select_field); + single_select_type_option.options.push(SelectOption::new("Unknown")); + let changeset = FieldChangesetParams { + field_id: single_select_field.id.clone(), + grid_id: test.grid_id.clone(), + frozen: Some(true), + width: Some(1000), + type_option_data: Some(single_select_type_option.protobuf_bytes().to_vec()), + ..Default::default() + }; + + // The expected_field must be equal to the field that applied the changeset + let mut expected_field_rev = single_select_field.clone(); + expected_field_rev.frozen = true; + expected_field_rev.width = 1000; + expected_field_rev.insert_type_option_entry(&single_select_type_option); + + let scripts = vec![ + CreateField { params }, + UpdateField { changeset }, + AssertFieldEqual { + field_index: test.field_count, + field_rev: expected_field_rev, + }, + ]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_delete_field() { + let mut test = GridEditorTest::new().await; + let original_field_count = test.field_count; + let (params, text_field_rev) = create_text_field(&test.grid_id); + let scripts = vec![ + CreateField { params }, + DeleteField { + field_rev: text_field_rev, + }, + AssertFieldCount(original_field_count), + ]; + test.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs deleted file mode 100644 index f7f7cc9e94..0000000000 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ /dev/null @@ -1,381 +0,0 @@ -use crate::grid::script::EditorScript::*; -use crate::grid::script::*; -use chrono::NaiveDateTime; -use flowy_grid::services::field::{ - DateCellContentChangeset, DateCellData, MultiSelectTypeOption, SelectOption, SelectOptionCellContentChangeset, - SingleSelectTypeOption, SELECTION_IDS_SEPARATOR, -}; -use flowy_grid::services::row::{decode_cell_data_from_type_option_cell_data, CreateRowMetaBuilder}; -use flowy_grid_data_model::entities::{CellChangeset, FieldChangesetParams, FieldType}; -use flowy_grid_data_model::revision::{ - GridBlockRevision, GridBlockRevisionChangeset, RowMetaChangeset, TypeOptionDataEntry, -}; - -#[tokio::test] -async fn grid_create_field() { - let mut test = GridEditorTest::new().await; - let (text_field_params, text_field_rev) = create_text_field(&test.grid_id); - let (single_select_params, single_select_field) = create_single_select_field(&test.grid_id); - let scripts = vec![ - CreateField { - params: text_field_params, - }, - AssertFieldEqual { - field_index: test.field_count, - field_rev: text_field_rev, - }, - ]; - test.run_scripts(scripts).await; - - let scripts = vec![ - CreateField { - params: single_select_params, - }, - AssertFieldEqual { - field_index: test.field_count, - field_rev: single_select_field, - }, - ]; - test.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_create_duplicate_field() { - let mut test = GridEditorTest::new().await; - let (params, _) = create_text_field(&test.grid_id); - let field_count = test.field_count; - let expected_field_count = field_count + 1; - let scripts = vec![ - CreateField { params: params.clone() }, - CreateField { params }, - AssertFieldCount(expected_field_count), - ]; - test.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_update_field_with_empty_change() { - let mut test = GridEditorTest::new().await; - let (params, field_rev) = create_single_select_field(&test.grid_id); - let changeset = FieldChangesetParams { - field_id: field_rev.id.clone(), - grid_id: test.grid_id.clone(), - ..Default::default() - }; - - let scripts = vec![ - CreateField { params }, - UpdateField { changeset }, - AssertFieldEqual { - field_index: test.field_count, - field_rev, - }, - ]; - test.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_update_field() { - let mut test = GridEditorTest::new().await; - let (single_select_params, single_select_field) = create_single_select_field(&test.grid_id); - let mut cloned_field = single_select_field.clone(); - - let mut single_select_type_option = SingleSelectTypeOption::from(&single_select_field); - single_select_type_option.options.push(SelectOption::new("Unknown")); - let changeset = FieldChangesetParams { - field_id: single_select_field.id.clone(), - grid_id: test.grid_id.clone(), - frozen: Some(true), - width: Some(1000), - type_option_data: Some(single_select_type_option.protobuf_bytes().to_vec()), - ..Default::default() - }; - - cloned_field.frozen = true; - cloned_field.width = 1000; - cloned_field.insert_type_option_entry(&single_select_type_option); - - let scripts = vec![ - CreateField { - params: single_select_params, - }, - UpdateField { changeset }, - AssertFieldEqual { - field_index: test.field_count, - field_rev: cloned_field, - }, - ]; - test.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_delete_field() { - let mut test = GridEditorTest::new().await; - let expected_field_count = test.field_count; - let (text_params, text_field) = create_text_field(&test.grid_id); - let scripts = vec![ - CreateField { params: text_params }, - DeleteField { field_rev: text_field }, - AssertFieldCount(expected_field_count), - ]; - test.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_create_block() { - let grid_block = GridBlockRevision::new(); - let scripts = vec![ - AssertBlockCount(1), - CreateBlock { block: grid_block }, - AssertBlockCount(2), - ]; - GridEditorTest::new().await.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_update_block() { - let grid_block = GridBlockRevision::new(); - let mut cloned_grid_block = grid_block.clone(); - let changeset = GridBlockRevisionChangeset { - block_id: grid_block.block_id.clone(), - start_row_index: Some(2), - row_count: Some(10), - }; - - cloned_grid_block.start_row_index = 2; - cloned_grid_block.row_count = 10; - - let scripts = vec![ - AssertBlockCount(1), - CreateBlock { block: grid_block }, - UpdateBlock { changeset }, - AssertBlockCount(2), - AssertBlockEqual { - block_index: 1, - block: cloned_grid_block, - }, - ]; - GridEditorTest::new().await.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_create_row() { - let scripts = vec![AssertRowCount(3), CreateEmptyRow, CreateEmptyRow, AssertRowCount(5)]; - GridEditorTest::new().await.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_create_row2() { - let mut test = GridEditorTest::new().await; - let create_row_context = CreateRowMetaBuilder::new(&test.field_revs).build(); - let scripts = vec![ - AssertRowCount(3), - CreateRow { - context: create_row_context, - }, - AssertRowCount(4), - ]; - test.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_update_row() { - let mut test = GridEditorTest::new().await; - let context = CreateRowMetaBuilder::new(&test.field_revs).build(); - let changeset = RowMetaChangeset { - row_id: context.row_id.clone(), - height: None, - visibility: None, - cell_by_field_id: Default::default(), - }; - - let scripts = vec![ - AssertRowCount(3), - CreateRow { context }, - UpdateRow { - changeset: changeset.clone(), - }, - AssertRow { changeset }, - AssertRowCount(4), - ]; - test.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_delete_row() { - let mut test = GridEditorTest::new().await; - let context_1 = CreateRowMetaBuilder::new(&test.field_revs).build(); - let context_2 = CreateRowMetaBuilder::new(&test.field_revs).build(); - let row_ids = vec![context_1.row_id.clone(), context_2.row_id.clone()]; - let scripts = vec![ - AssertRowCount(3), - CreateRow { context: context_1 }, - CreateRow { context: context_2 }, - AssertBlockCount(1), - AssertBlock { - block_index: 0, - row_count: 5, - start_row_index: 0, - }, - DeleteRow { row_ids }, - AssertBlock { - block_index: 0, - row_count: 3, - start_row_index: 0, - }, - ]; - test.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_row_add_cells_test() { - let mut test = GridEditorTest::new().await; - let mut builder = CreateRowMetaBuilder::new(&test.field_revs); - for field in &test.field_revs { - match field.field_type { - FieldType::RichText => { - builder.add_cell(&field.id, "hello world".to_owned()).unwrap(); - } - FieldType::Number => { - builder.add_cell(&field.id, "18,443".to_owned()).unwrap(); - } - FieldType::DateTime => { - builder - .add_cell(&field.id, make_date_cell_string("1647251762")) - .unwrap(); - } - FieldType::SingleSelect => { - let type_option = SingleSelectTypeOption::from(field); - let option = type_option.options.first().unwrap(); - builder.add_select_option_cell(&field.id, option.id.clone()).unwrap(); - } - FieldType::MultiSelect => { - let type_option = MultiSelectTypeOption::from(field); - let ops_ids = type_option - .options - .iter() - .map(|option| option.id.clone()) - .collect::>() - .join(SELECTION_IDS_SEPARATOR); - builder.add_select_option_cell(&field.id, ops_ids).unwrap(); - } - FieldType::Checkbox => { - builder.add_cell(&field.id, "false".to_string()).unwrap(); - } - FieldType::URL => { - builder.add_cell(&field.id, "1".to_string()).unwrap(); - } - } - } - let context = builder.build(); - let scripts = vec![CreateRow { context }, AssertGridMetaPad]; - test.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_row_add_date_cell_test() { - let mut test = GridEditorTest::new().await; - let mut builder = CreateRowMetaBuilder::new(&test.field_revs); - let mut date_field = None; - let timestamp = 1647390674; - for field in &test.field_revs { - if field.field_type == FieldType::DateTime { - date_field = Some(field.clone()); - NaiveDateTime::from_timestamp(123, 0); - // The data should not be empty - assert!(builder.add_cell(&field.id, "".to_string()).is_err()); - assert!(builder.add_cell(&field.id, make_date_cell_string("123")).is_ok()); - assert!(builder - .add_cell(&field.id, make_date_cell_string(×tamp.to_string())) - .is_ok()); - } - } - let context = builder.build(); - let date_field = date_field.unwrap(); - let cell_data = context.cell_by_field_id.get(&date_field.id).unwrap().clone(); - assert_eq!( - decode_cell_data_from_type_option_cell_data(cell_data.data.clone(), &date_field, &date_field.field_type) - .parse::() - .unwrap() - .date, - "2022/03/16", - ); - let scripts = vec![CreateRow { context }]; - test.run_scripts(scripts).await; -} - -#[tokio::test] -async fn grid_cell_update() { - let mut test = GridEditorTest::new().await; - let field_revs = &test.field_revs; - let row_revs = &test.row_revs; - let grid_blocks = &test.grid_block_revs; - assert_eq!(row_revs.len(), 3); - assert_eq!(grid_blocks.len(), 1); - - let block_id = &grid_blocks.first().unwrap().block_id; - let mut scripts = vec![]; - for (index, row_rev) in row_revs.iter().enumerate() { - for field_rev in field_revs { - if index == 0 { - let data = match field_rev.field_type { - FieldType::RichText => "".to_string(), - FieldType::Number => "123".to_string(), - FieldType::DateTime => make_date_cell_string("123"), - FieldType::SingleSelect => { - let type_option = SingleSelectTypeOption::from(field_rev); - SelectOptionCellContentChangeset::from_insert(&type_option.options.first().unwrap().id).to_str() - } - FieldType::MultiSelect => { - let type_option = MultiSelectTypeOption::from(field_rev); - SelectOptionCellContentChangeset::from_insert(&type_option.options.first().unwrap().id).to_str() - } - FieldType::Checkbox => "1".to_string(), - FieldType::URL => "1".to_string(), - }; - - scripts.push(UpdateCell { - changeset: CellChangeset { - grid_id: block_id.to_string(), - row_id: row_rev.id.clone(), - field_id: field_rev.id.clone(), - cell_content_changeset: Some(data), - }, - is_err: false, - }); - } - - if index == 1 { - let (data, is_err) = match field_rev.field_type { - FieldType::RichText => ("1".to_string().repeat(10001), true), - FieldType::Number => ("abc".to_string(), true), - FieldType::DateTime => ("abc".to_string(), true), - FieldType::SingleSelect => (SelectOptionCellContentChangeset::from_insert("abc").to_str(), false), - FieldType::MultiSelect => (SelectOptionCellContentChangeset::from_insert("abc").to_str(), false), - FieldType::Checkbox => ("2".to_string(), false), - FieldType::URL => ("2".to_string(), false), - }; - - scripts.push(UpdateCell { - changeset: CellChangeset { - grid_id: block_id.to_string(), - row_id: row_rev.id.clone(), - field_id: field_rev.id.clone(), - cell_content_changeset: Some(data), - }, - is_err, - }); - } - } - } - - test.run_scripts(scripts).await; -} - -fn make_date_cell_string(s: &str) -> String { - serde_json::to_string(&DateCellContentChangeset { - date: Some(s.to_string()), - time: None, - }) - .unwrap() -} diff --git a/frontend/rust-lib/flowy-grid/tests/grid/mod.rs b/frontend/rust-lib/flowy-grid/tests/grid/mod.rs index 04b16720e5..1ca8ad3983 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/mod.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/mod.rs @@ -1,2 +1,6 @@ -mod grid_test; +mod block_test; +mod cell_test; +mod field_test; +mod row_test; mod script; +mod setting_test; diff --git a/frontend/rust-lib/flowy-grid/tests/grid/row_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/row_test.rs new file mode 100644 index 0000000000..735ed91202 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/tests/grid/row_test.rs @@ -0,0 +1,147 @@ +use crate::grid::script::EditorScript::*; +use crate::grid::script::*; +use chrono::NaiveDateTime; +use flowy_grid::services::field::{ + DateCellData, MultiSelectTypeOption, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR, +}; +use flowy_grid::services::row::{decode_cell_data_from_type_option_cell_data, CreateRowRevisionBuilder}; +use flowy_grid_data_model::entities::FieldType; +use flowy_grid_data_model::revision::RowMetaChangeset; + +#[tokio::test] +async fn grid_create_row_count_test() { + let test = GridEditorTest::new().await; + let create_row_context = CreateRowRevisionBuilder::new(&test.field_revs).build(); + let scripts = vec![ + AssertRowCount(3), + CreateEmptyRow, + CreateEmptyRow, + CreateRow { + context: create_row_context, + }, + AssertRowCount(6), + ]; + GridEditorTest::new().await.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_update_row() { + let mut test = GridEditorTest::new().await; + let context = CreateRowRevisionBuilder::new(&test.field_revs).build(); + let changeset = RowMetaChangeset { + row_id: context.row_id.clone(), + height: None, + visibility: None, + cell_by_field_id: Default::default(), + }; + + let scripts = vec![AssertRowCount(3), CreateRow { context }, UpdateRow { changeset }]; + test.run_scripts(scripts).await; + + let expected_row = (&*test.row_revs.last().cloned().unwrap()).clone(); + let scripts = vec![AssertRow { expected_row }, AssertRowCount(4)]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_delete_row() { + let mut test = GridEditorTest::new().await; + let context_1 = CreateRowRevisionBuilder::new(&test.field_revs).build(); + let context_2 = CreateRowRevisionBuilder::new(&test.field_revs).build(); + let row_ids = vec![context_1.row_id.clone(), context_2.row_id.clone()]; + let scripts = vec![ + AssertRowCount(3), + CreateRow { context: context_1 }, + CreateRow { context: context_2 }, + AssertBlockCount(1), + AssertBlock { + block_index: 0, + row_count: 5, + start_row_index: 0, + }, + DeleteRows { row_ids }, + AssertBlock { + block_index: 0, + row_count: 3, + start_row_index: 0, + }, + ]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_row_add_cells_test() { + let mut test = GridEditorTest::new().await; + let mut builder = CreateRowRevisionBuilder::new(&test.field_revs); + for field in &test.field_revs { + match field.field_type { + FieldType::RichText => { + builder.add_cell(&field.id, "hello world".to_owned()).unwrap(); + } + FieldType::Number => { + builder.add_cell(&field.id, "18,443".to_owned()).unwrap(); + } + FieldType::DateTime => { + builder + .add_cell(&field.id, make_date_cell_string("1647251762")) + .unwrap(); + } + FieldType::SingleSelect => { + let type_option = SingleSelectTypeOption::from(field); + let option = type_option.options.first().unwrap(); + builder.add_select_option_cell(&field.id, option.id.clone()).unwrap(); + } + FieldType::MultiSelect => { + let type_option = MultiSelectTypeOption::from(field); + let ops_ids = type_option + .options + .iter() + .map(|option| option.id.clone()) + .collect::>() + .join(SELECTION_IDS_SEPARATOR); + builder.add_select_option_cell(&field.id, ops_ids).unwrap(); + } + FieldType::Checkbox => { + builder.add_cell(&field.id, "false".to_string()).unwrap(); + } + FieldType::URL => { + builder.add_cell(&field.id, "1".to_string()).unwrap(); + } + } + } + let context = builder.build(); + let scripts = vec![CreateRow { context }, AssertGridRevisionPad]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_row_add_date_cell_test() { + let mut test = GridEditorTest::new().await; + let mut builder = CreateRowRevisionBuilder::new(&test.field_revs); + let mut date_field = None; + let timestamp = 1647390674; + for field in &test.field_revs { + if field.field_type == FieldType::DateTime { + date_field = Some(field.clone()); + NaiveDateTime::from_timestamp(123, 0); + // The data should not be empty + assert!(builder.add_cell(&field.id, "".to_string()).is_err()); + assert!(builder.add_cell(&field.id, make_date_cell_string("123")).is_ok()); + assert!(builder + .add_cell(&field.id, make_date_cell_string(×tamp.to_string())) + .is_ok()); + } + } + let context = builder.build(); + let date_field = date_field.unwrap(); + let cell_data = context.cell_by_field_id.get(&date_field.id).unwrap().clone(); + assert_eq!( + decode_cell_data_from_type_option_cell_data(cell_data.data.clone(), &date_field, &date_field.field_type) + .parse::() + .unwrap() + .date, + "2022/03/16", + ); + let scripts = vec![CreateRow { context }]; + test.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index a6e7d1fc2c..eb00e88e2b 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -1,14 +1,9 @@ use bytes::Bytes; use flowy_grid::services::field::*; use flowy_grid::services::grid_editor::{GridPadBuilder, GridRevisionEditor}; -use flowy_grid::services::row::CreateRowMetaPayload; -use flowy_grid_data_model::entities::{ - CellChangeset, Field, FieldChangesetParams, FieldOrder, FieldType, InsertFieldParams, RowOrder, -}; -use flowy_grid_data_model::revision::{ - BuildGridContext, FieldRevision, GridBlockRevision, GridBlockRevisionChangeset, RowMetaChangeset, RowRevision, - TypeOptionDataEntry, -}; +use flowy_grid::services::row::CreateRowRevisionPayload; +use flowy_grid_data_model::entities::*; +use flowy_grid_data_model::revision::*; use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS; use flowy_sync::client_grid::GridBuilder; use flowy_test::helper::ViewTest; @@ -52,15 +47,15 @@ pub enum EditorScript { }, CreateEmptyRow, CreateRow { - context: CreateRowMetaPayload, + context: CreateRowRevisionPayload, }, UpdateRow { changeset: RowMetaChangeset, }, AssertRow { - changeset: RowMetaChangeset, + expected_row: RowRevision, }, - DeleteRow { + DeleteRows { row_ids: Vec, }, UpdateCell { @@ -68,8 +63,13 @@ pub enum EditorScript { is_err: bool, }, AssertRowCount(usize), - // AssertRowEqual{ row_index: usize, row: RowMeta}, - AssertGridMetaPad, + UpdateGridSetting { + params: GridSettingChangesetParams, + }, + AssertGridSetting { + expected_setting: GridSettingRevision, + }, + AssertGridRevisionPad, } pub struct GridEditorTest { @@ -88,13 +88,19 @@ impl GridEditorTest { pub async fn new() -> Self { let sdk = FlowySDKTest::default(); let _ = sdk.init_user().await; - let build_context = make_template_1_grid(); + let build_context = make_test_grid(); let view_data: Bytes = build_context.into(); let test = ViewTest::new_grid_view(&sdk, view_data.to_vec()).await; let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap(); let field_revs = editor.get_field_revs::(None).await.unwrap(); let grid_blocks = editor.get_block_metas().await.unwrap(); - let row_revs = get_row_revs(&editor).await; + let row_revs = editor.grid_block_snapshots(None).await.unwrap().pop().unwrap().row_revs; + assert_eq!(row_revs.len(), 3); + assert_eq!(grid_blocks.len(), 1); + + // It seems like you should add the field in the make_test_grid() function. + // Because we assert the initialize count of the fields is equal to FieldType::COUNT. + assert_eq!(field_revs.len(), FieldType::COUNT); let grid_id = test.view.id; Self { @@ -192,7 +198,7 @@ impl GridEditorTest { self.grid_block_revs = self.editor.get_block_metas().await.unwrap(); } EditorScript::UpdateRow { changeset: change } => self.editor.update_row(change).await.unwrap(), - EditorScript::DeleteRow { row_ids } => { + EditorScript::DeleteRows { row_ids } => { let row_orders = row_ids .into_iter() .map(|row_id| self.row_order_by_row_id.get(&row_id).unwrap().clone()) @@ -202,16 +208,21 @@ impl GridEditorTest { self.row_revs = self.get_row_revs().await; self.grid_block_revs = self.editor.get_block_metas().await.unwrap(); } - EditorScript::AssertRow { changeset } => { - let row = self.row_revs.iter().find(|row| row.id == changeset.row_id).unwrap(); - - if let Some(visibility) = changeset.visibility { - assert_eq!(row.visibility, visibility); - } - - if let Some(height) = changeset.height { - assert_eq!(row.height, height); - } + EditorScript::AssertRow { expected_row } => { + let row = &*self + .row_revs + .iter() + .find(|row| row.id == expected_row.id) + .cloned() + .unwrap(); + assert_eq!(&expected_row, row); + // if let Some(visibility) = changeset.visibility { + // assert_eq!(row.visibility, visibility); + // } + // + // if let Some(height) = changeset.height { + // assert_eq!(row.height, height); + // } } EditorScript::UpdateCell { changeset, is_err } => { let result = self.editor.update_cell(changeset).await; @@ -222,10 +233,17 @@ impl GridEditorTest { self.row_revs = self.get_row_revs().await; } } - EditorScript::AssertRowCount(count) => { - assert_eq!(self.row_revs.len(), count); + EditorScript::AssertRowCount(expected_row_count) => { + assert_eq!(expected_row_count, self.row_revs.len()); } - EditorScript::AssertGridMetaPad => { + EditorScript::UpdateGridSetting { params } => { + let _ = self.editor.update_grid_setting(params).await.unwrap(); + } + EditorScript::AssertGridSetting { expected_setting } => { + let setting = self.editor.get_grid_setting().await.unwrap(); + assert_eq!(expected_setting, setting); + } + EditorScript::AssertGridRevisionPad => { sleep(Duration::from_millis(2 * REVISION_WRITE_INTERVAL_IN_MILLIS)).await; let mut grid_rev_manager = grid_manager.make_grid_rev_manager(&self.grid_id, pool.clone()).unwrap(); let grid_pad = grid_rev_manager.load::(None).await.unwrap(); @@ -235,14 +253,16 @@ impl GridEditorTest { } async fn get_row_revs(&self) -> Vec> { - get_row_revs(&self.editor).await + self.editor + .grid_block_snapshots(None) + .await + .unwrap() + .pop() + .unwrap() + .row_revs } } -async fn get_row_revs(editor: &Arc) -> Vec> { - editor.grid_block_snapshots(None).await.unwrap().pop().unwrap().row_revs -} - pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) { let field_rev = FieldBuilder::new(RichTextTypeOptionBuilder::default()) .name("Name") @@ -310,7 +330,7 @@ pub fn create_single_select_field(grid_id: &str) -> (InsertFieldParams, FieldRev (params, cloned_field_rev) } -fn make_template_1_grid() -> BuildGridContext { +fn make_test_grid() -> BuildGridContext { let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default()) .name("Name") .visibility(true) @@ -365,3 +385,11 @@ fn make_template_1_grid() -> BuildGridContext { .add_empty_row() .build() } + +pub fn make_date_cell_string(s: &str) -> String { + serde_json::to_string(&DateCellContentChangeset { + date: Some(s.to_string()), + time: None, + }) + .unwrap() +} diff --git a/frontend/rust-lib/flowy-grid/tests/grid/setting_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/setting_test.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/tests/grid/setting_test.rs @@ -0,0 +1 @@ + diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs index 669dcc48ec..310a28b843 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs @@ -31,6 +31,8 @@ pub struct GridRevision { pub grid_id: String, pub fields: Vec, pub blocks: Vec, + + #[serde(skip)] pub setting: GridSettingRevision, } diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_info_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs similarity index 91% rename from shared-lib/flowy-grid-data-model/src/revision/grid_info_rev.rs rename to shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs index 163d44eeba..fd251f3c04 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_info_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use serde_repr::*; use std::collections::HashMap; -#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] pub struct GridSettingRevision { #[serde(with = "indexmap::serde_seq")] pub filter: IndexMap, @@ -54,18 +54,18 @@ impl std::convert::From for GridLayoutRevision { } } -#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] pub struct GridFilterRevision { pub field_id: Option, } -#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] pub struct GridGroupRevision { pub group_field_id: Option, pub sub_group_field_id: Option, } -#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] pub struct GridSortRevision { pub field_id: Option, } diff --git a/shared-lib/flowy-grid-data-model/src/revision/mod.rs b/shared-lib/flowy-grid-data-model/src/revision/mod.rs index da6b857db6..a6581ad181 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/mod.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/mod.rs @@ -1,5 +1,5 @@ -mod grid_info_rev; mod grid_rev; +mod grid_setting_rev; -pub use grid_info_rev::*; pub use grid_rev::*; +pub use grid_setting_rev::*; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs index 62de70f16d..986ce35045 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs @@ -364,7 +364,7 @@ impl GridRevisionPad { if let Some(sort) = changeset.sort { grid_rev.setting.sort.insert( - layout_rev.clone(), + layout_rev, GridSortRevision { field_id: sort.field_id, }, diff --git a/shared-lib/lib-infra/src/code_gen/protobuf_file/ast.rs b/shared-lib/lib-infra/src/code_gen/protobuf_file/ast.rs index cbf2b4ffa8..03ea485716 100644 --- a/shared-lib/lib-infra/src/code_gen/protobuf_file/ast.rs +++ b/shared-lib/lib-infra/src/code_gen/protobuf_file/ast.rs @@ -15,7 +15,7 @@ use walkdir::WalkDir; pub fn parse_protobuf_context_from(crate_paths: Vec) -> Vec { let crate_infos = parse_crate_info_from_path(crate_paths); - let contexts = crate_infos + crate_infos .into_iter() .map(|crate_info| { let proto_output_path = crate_info.proto_output_path(); @@ -28,9 +28,7 @@ pub fn parse_protobuf_context_from(crate_paths: Vec) -> Vec>(); - - contexts + .collect::>() } fn parse_files_protobuf(proto_crate_path: &Path, proto_output_path: &Path) -> Vec { @@ -71,7 +69,7 @@ fn parse_files_protobuf(proto_crate_path: &Path, proto_output_path: &Path) -> Ve .iter() .filter(|field| field.attrs.pb_index().is_some()) .for_each(|field| { - ref_types.push(field.ty_as_str().to_string()); + ref_types.push(field.ty_as_str()); struct_template.set_field(field); }); @@ -95,8 +93,8 @@ fn parse_files_protobuf(proto_crate_path: &Path, proto_output_path: &Path) -> Ve if !enums.is_empty() || !structs.is_empty() { let structs: Vec = structs.iter().map(|s| s.name.clone()).collect(); let enums: Vec = enums.iter().map(|e| e.name.clone()).collect(); - ref_types.retain(|s| !structs.contains(&s)); - ref_types.retain(|s| !enums.contains(&s)); + ref_types.retain(|s| !structs.contains(s)); + ref_types.retain(|s| !enums.contains(s)); let info = ProtoFile { file_path: path.clone(), diff --git a/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_gen.rs b/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_gen.rs index ad9c769a1f..25144d2c52 100644 --- a/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_gen.rs +++ b/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_gen.rs @@ -76,7 +76,7 @@ fn write_proto_files(crate_contexts: &[ProtobufCrateContext]) { let mut file_content = file.syntax.clone(); // import - file_content.push_str(&gen_import_content(&file, &file_path_content_map)); + file_content.push_str(&gen_import_content(file, &file_path_content_map)); // content file_content.push_str(&file.content); diff --git a/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_info.rs b/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_info.rs index b4ba5cb432..d47210eaba 100644 --- a/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_info.rs +++ b/shared-lib/lib-infra/src/code_gen/protobuf_file/proto_info.rs @@ -69,7 +69,7 @@ impl ProtobufCrate { ProtobufCrate { crate_path: config.crate_path, crate_folder: config.crate_folder, - flowy_config: config.flowy_config.clone(), + flowy_config: config.flowy_config, } }