Browse Source

chore: add transform field tests (#1504)

Co-authored-by: nathan <[email protected]>
Nathan.fooo 2 years ago
parent
commit
acaaabee2a

+ 2 - 2
frontend/rust-lib/flowy-grid/src/event_handler.rs

@@ -117,7 +117,7 @@ pub(crate) async fn update_field_type_option_handler(
     let editor = manager.get_grid_editor(&params.grid_id).await?;
     let old_field_rev = editor.get_field_rev(&params.field_id).await;
     let _ = editor
-        .did_update_field_type_option(
+        .update_field_type_option(
             &params.grid_id,
             &params.field_id,
             params.type_option_data,
@@ -159,7 +159,7 @@ pub(crate) async fn switch_to_field_handler(
     // Update the type-option data after the field type has been changed
     let type_option_data = get_type_option_data(&new_field_rev, &params.field_type).await?;
     let _ = editor
-        .did_update_field_type_option(&params.grid_id, &new_field_rev.id, type_option_data, old_field_rev)
+        .update_field_type_option(&params.grid_id, &new_field_rev.id, type_option_data, old_field_rev)
         .await?;
 
     Ok(())

+ 1 - 1
frontend/rust-lib/flowy-grid/src/services/field/field_operation.rs

@@ -23,7 +23,7 @@ where
         action(&mut type_option);
         let bytes = type_option.protobuf_bytes().to_vec();
         let _ = editor
-            .did_update_field_type_option(&editor.grid_id, field_id, bytes, old_field_rev)
+            .update_field_type_option(&editor.grid_id, field_id, bytes, old_field_rev)
             .await?;
     }
 

+ 5 - 1
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_type_option.rs

@@ -27,10 +27,14 @@ pub struct SelectOptionPB {
     pub color: SelectOptionColorPB,
 }
 
+pub fn gen_option_id() -> String {
+    nanoid!(4)
+}
+
 impl SelectOptionPB {
     pub fn new(name: &str) -> Self {
         SelectOptionPB {
-            id: nanoid!(4),
+            id: gen_option_id(),
             name: name.to_owned(),
             color: SelectOptionColorPB::default(),
         }

+ 7 - 0
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/type_option_transform.rs

@@ -9,6 +9,13 @@ use grid_rev_model::FieldRevision;
 /// Handles how to transform the cell data when switching between different field types
 pub struct SelectOptionTypeOptionTransformer();
 impl SelectOptionTypeOptionTransformer {
+    /// Transform the TypeOptionData from 'field_type' to single select option type.
+    ///
+    /// # Arguments
+    ///
+    /// * `field_type`: the FieldType of the passed-in TypeOptionData
+    /// * `type_option_data`: the data that can be parsed into corresponding TypeOptionData.
+    ///
     pub fn transform_type_option<T>(shared: &mut T, field_type: &FieldType, _type_option_data: String)
     where
         T: SelectTypeOptionSharedAction,

+ 2 - 2
frontend/rust-lib/flowy-grid/src/services/filter/controller.rs

@@ -328,11 +328,11 @@ fn filter_row(
     }
 
     let is_visible = filter_result.is_visible();
-    return if old_is_visible != is_visible {
+    if old_is_visible != is_visible {
         Some((row_rev.id.clone(), is_visible))
     } else {
         None
-    };
+    }
 }
 
 // Returns None if there is no change in this cell after applying the filter

+ 6 - 72
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -108,7 +108,7 @@ impl GridRevisionEditor {
     /// * `type_option_data`: the updated type-option data. The `type-option` data might be empty
     /// if there is no type-option config for that field. For example, the `RichTextTypeOptionPB`.
     ///  
-    pub async fn did_update_field_type_option(
+    pub async fn update_field_type_option(
         &self,
         _grid_id: &str,
         field_id: &str,
@@ -271,11 +271,11 @@ impl GridRevisionEditor {
         };
 
         let type_option_transform =
-            |prev_field_type: FieldTypeRevision, prev_type_option: Option<String>, current_type_option: String| {
-                let prev_field_type: FieldType = prev_field_type.into();
-                let mut type_option_builder = type_option_builder_from_json_str(&current_type_option, new_field_type);
-                if let Some(prev_type_option) = prev_type_option {
-                    type_option_builder.transform(&prev_field_type, prev_type_option)
+            |old_field_type: FieldTypeRevision, old_type_option: Option<String>, new_type_option: String| {
+                let old_field_type: FieldType = old_field_type.into();
+                let mut type_option_builder = type_option_builder_from_json_str(&new_type_option, new_field_type);
+                if let Some(old_type_option) = old_type_option {
+                    type_option_builder.transform(&old_field_type, old_type_option)
                 }
                 type_option_builder.serializer().json_str()
             };
@@ -330,72 +330,6 @@ impl GridRevisionEditor {
         Ok(field_revs)
     }
 
-    // /// Apply the changeset to field. Including the `name`,`field_type`,`width`,`visibility`,and `type_option_data`.
-    // /// Do nothing if the passed-in params doesn't carry any changes.
-    // ///
-    // /// # Arguments
-    // ///
-    // /// * `params`: contains the changesets that is going to applied to the field.
-    // /// Ignore the change if one of the properties is None.
-    // ///
-    // /// * `field_type`: is used by `TypeOptionJsonDeserializer` to deserialize the type_option_data
-    // ///
-    // #[tracing::instrument(level = "debug", skip_all, err)]
-    // async fn did_update_field_rev(
-    //     &self,
-    //     params: FieldChangesetParams,
-    //     field_type: FieldType,
-    //     old_field_rev: Option<Arc<FieldRevision>>,
-    // ) -> FlowyResult<()> {
-    //     let mut is_type_option_changed = false;
-    //     let _ = self
-    //         .modify(|grid| {
-    //             let changeset = grid.modify_field(&params.field_id, |field| {
-    //                 if let Some(name) = params.name {
-    //                     field.name = name;
-    //                 }
-    //                 if let Some(desc) = params.desc {
-    //                     field.desc = desc;
-    //                 }
-    //                 if let Some(field_type) = params.field_type {
-    //                     field.ty = field_type;
-    //                 }
-    //                 if let Some(frozen) = params.frozen {
-    //                     field.frozen = frozen;
-    //                 }
-    //                 if let Some(visibility) = params.visibility {
-    //                     field.visibility = visibility;
-    //                 }
-    //                 if let Some(width) = params.width {
-    //                     field.width = width;
-    //                 }
-    //                 if let Some(type_option_data) = params.type_option_data {
-    //                     let deserializer = TypeOptionJsonDeserializer(field_type);
-    //                     is_type_option_changed = true;
-    //                     match deserializer.deserialize(type_option_data) {
-    //                         Ok(json_str) => {
-    //                             let field_type = field.ty;
-    //                             field.insert_type_option_str(&field_type, json_str);
-    //                         }
-    //                         Err(err) => {
-    //                             tracing::error!("Deserialize data to type option json failed: {}", err);
-    //                         }
-    //                     }
-    //                 }
-    //                 Ok(Some(()))
-    //             })?;
-    //             Ok(changeset)
-    //         })
-    //         .await?;
-    //     if is_type_option_changed {
-    //         let _ = self
-    //             .view_manager
-    //             .did_update_view_field_type_option(&params.field_id, old_field_rev)
-    //             .await?;
-    //     }
-    //     Ok(())
-    // }
-
     pub async fn create_block(&self, block_meta_rev: GridBlockMetaRevision) -> FlowyResult<()> {
         let _ = self
             .modify(|grid_pad| Ok(grid_pad.create_block_meta_rev(block_meta_rev)?))

+ 28 - 1
frontend/rust-lib/flowy-grid/tests/grid/field_test/script.rs

@@ -1,5 +1,5 @@
 use crate::grid::grid_editor::GridEditorTest;
-use flowy_grid::entities::{CreateFieldParams, FieldChangesetParams};
+use flowy_grid::entities::{CreateFieldParams, FieldChangesetParams, FieldType};
 use grid_rev_model::FieldRevision;
 
 pub enum FieldScript {
@@ -12,6 +12,14 @@ pub enum FieldScript {
     DeleteField {
         field_rev: FieldRevision,
     },
+    SwitchToField {
+        field_id: String,
+        new_field_type: FieldType,
+    },
+    UpdateTypeOption {
+        field_id: String,
+        type_option: Vec<u8>,
+    },
     AssertFieldCount(usize),
     AssertFieldFrozen {
         field_index: usize,
@@ -71,6 +79,25 @@ impl GridFieldTest {
                 self.field_revs = self.editor.get_field_revs(None).await.unwrap();
                 assert_eq!(self.field_count, self.field_revs.len());
             }
+            FieldScript::SwitchToField {
+                field_id,
+                new_field_type,
+            } => {
+                //
+                self.editor
+                    .switch_to_field_type(&field_id, &new_field_type)
+                    .await
+                    .unwrap();
+                self.field_revs = self.editor.get_field_revs(None).await.unwrap();
+            }
+            FieldScript::UpdateTypeOption { field_id, type_option } => {
+                //
+                self.editor
+                    .update_field_type_option(&self.grid_id, &field_id, type_option, None)
+                    .await
+                    .unwrap();
+                self.field_revs = self.editor.get_field_revs(None).await.unwrap();
+            }
             FieldScript::AssertFieldCount(count) => {
                 assert_eq!(self.editor.get_field_revs(None).await.unwrap().len(), count);
             }

+ 60 - 2
frontend/rust-lib/flowy-grid/tests/grid/field_test/test.rs

@@ -1,9 +1,10 @@
 use crate::grid::field_test::script::FieldScript::*;
 use crate::grid::field_test::script::GridFieldTest;
 use crate::grid::field_test::util::*;
-use flowy_grid::entities::FieldChangesetParams;
+use bytes::Bytes;
+use flowy_grid::entities::{FieldChangesetParams, FieldType};
 use flowy_grid::services::field::selection_type_option::SelectOptionPB;
-use flowy_grid::services::field::SingleSelectTypeOptionPB;
+use flowy_grid::services::field::{gen_option_id, SingleSelectTypeOptionPB, CHECK, UNCHECK};
 
 #[tokio::test]
 async fn grid_create_field() {
@@ -121,3 +122,60 @@ async fn grid_delete_field() {
     ];
     test.run_scripts(scripts).await;
 }
+
+#[tokio::test]
+async fn grid_switch_from_select_option_to_checkbox_test() {
+    let mut test = GridFieldTest::new().await;
+    let field_rev = test.get_first_field_rev(FieldType::SingleSelect);
+
+    // Update the type option data of single select option
+    let mut single_select_type_option = test.get_single_select_type_option(&field_rev.id);
+    single_select_type_option.options.clear();
+    // Add a new option with name CHECK
+    single_select_type_option.options.push(SelectOptionPB {
+        id: gen_option_id(),
+        name: CHECK.to_string(),
+        color: Default::default(),
+    });
+    // Add a new option with name UNCHECK
+    single_select_type_option.options.push(SelectOptionPB {
+        id: gen_option_id(),
+        name: UNCHECK.to_string(),
+        color: Default::default(),
+    });
+
+    let bytes: Bytes = single_select_type_option.try_into().unwrap();
+    let scripts = vec![
+        UpdateTypeOption {
+            field_id: field_rev.id.clone(),
+            type_option: bytes.to_vec(),
+        },
+        SwitchToField {
+            field_id: field_rev.id.clone(),
+            new_field_type: FieldType::Checkbox,
+        },
+    ];
+    test.run_scripts(scripts).await;
+}
+
+#[tokio::test]
+async fn grid_switch_from_checkbox_to_select_option_test() {
+    let mut test = GridFieldTest::new().await;
+    let field_rev = test.get_first_field_rev(FieldType::Checkbox).clone();
+    let scripts = vec![SwitchToField {
+        field_id: field_rev.id.clone(),
+        new_field_type: FieldType::SingleSelect,
+    }];
+    test.run_scripts(scripts).await;
+
+    let single_select_type_option = test.get_single_select_type_option(&field_rev.id);
+    assert_eq!(single_select_type_option.options.len(), 2);
+    assert!(single_select_type_option
+        .options
+        .iter()
+        .any(|option| option.name == UNCHECK));
+    assert!(single_select_type_option
+        .options
+        .iter()
+        .any(|option| option.name == CHECK));
+}

+ 6 - 6
frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs

@@ -119,7 +119,7 @@ impl GridFilterTest {
             }
             FilterScript::CreateTextFilter { condition, content} => {
 
-                let field_rev = self.get_field_rev(FieldType::RichText);
+                let field_rev = self.get_first_field_rev(FieldType::RichText);
                 let text_filter= TextFilterPB {
                     condition,
                     content
@@ -139,7 +139,7 @@ impl GridFilterTest {
                 self.editor.create_or_update_filter(params).await.unwrap();
             }
             FilterScript::CreateNumberFilter {condition, content} => {
-                let field_rev = self.get_field_rev(FieldType::Number);
+                let field_rev = self.get_first_field_rev(FieldType::Number);
                 let number_filter = NumberFilterPB {
                     condition,
                     content
@@ -149,7 +149,7 @@ impl GridFilterTest {
                 self.insert_filter(payload).await;
             }
             FilterScript::CreateCheckboxFilter {condition} => {
-                let field_rev = self.get_field_rev(FieldType::Checkbox);
+                let field_rev = self.get_first_field_rev(FieldType::Checkbox);
                 let checkbox_filter = CheckboxFilterPB {
                     condition
                 };
@@ -158,7 +158,7 @@ impl GridFilterTest {
                 self.insert_filter(payload).await;
             }
             FilterScript::CreateDateFilter { condition, start, end, timestamp} => {
-                let field_rev = self.get_field_rev(FieldType::DateTime);
+                let field_rev = self.get_first_field_rev(FieldType::DateTime);
                 let date_filter = DateFilterPB {
                     condition,
                     start,
@@ -171,14 +171,14 @@ impl GridFilterTest {
                 self.insert_filter(payload).await;
             }
             FilterScript::CreateMultiSelectFilter { condition, option_ids} => {
-                let field_rev = self.get_field_rev(FieldType::MultiSelect);
+                let field_rev = self.get_first_field_rev(FieldType::MultiSelect);
                 let filter = SelectOptionFilterPB { condition, option_ids };
                 let payload =
                     AlterFilterPayloadPB::new(field_rev, filter);
                 self.insert_filter(payload).await;
             }
             FilterScript::CreateSingleSelectFilter { condition, option_ids} => {
-                let field_rev = self.get_field_rev(FieldType::SingleSelect);
+                let field_rev = self.get_first_field_rev(FieldType::SingleSelect);
                 let filter = SelectOptionFilterPB { condition, option_ids };
                 let payload =
                     AlterFilterPayloadPB::new(field_rev, filter);

+ 9 - 5
frontend/rust-lib/flowy-grid/tests/grid/filter_test/select_option_filter_test.rs

@@ -1,6 +1,6 @@
 use crate::grid::filter_test::script::FilterScript::*;
 use crate::grid::filter_test::script::GridFilterTest;
-use flowy_grid::entities::SelectOptionCondition;
+use flowy_grid::entities::{FieldType, SelectOptionCondition};
 
 #[tokio::test]
 async fn grid_filter_multi_select_is_empty_test() {
@@ -31,7 +31,8 @@ async fn grid_filter_multi_select_is_not_empty_test() {
 #[tokio::test]
 async fn grid_filter_multi_select_is_test() {
     let mut test = GridFilterTest::new().await;
-    let mut options = test.get_multi_select_type_option();
+    let field_rev = test.get_first_field_rev(FieldType::MultiSelect);
+    let mut options = test.get_multi_select_type_option(&field_rev.id);
     let scripts = vec![
         CreateMultiSelectFilter {
             condition: SelectOptionCondition::OptionIs,
@@ -45,7 +46,8 @@ async fn grid_filter_multi_select_is_test() {
 #[tokio::test]
 async fn grid_filter_multi_select_is_test2() {
     let mut test = GridFilterTest::new().await;
-    let mut options = test.get_multi_select_type_option();
+    let field_rev = test.get_first_field_rev(FieldType::MultiSelect);
+    let mut options = test.get_multi_select_type_option(&field_rev.id);
     let scripts = vec![
         CreateMultiSelectFilter {
             condition: SelectOptionCondition::OptionIs,
@@ -72,7 +74,8 @@ async fn grid_filter_single_select_is_empty_test() {
 #[tokio::test]
 async fn grid_filter_single_select_is_test() {
     let mut test = GridFilterTest::new().await;
-    let mut options = test.get_single_select_type_option();
+    let field_rev = test.get_first_field_rev(FieldType::SingleSelect);
+    let mut options = test.get_single_select_type_option(&field_rev.id).options;
     let scripts = vec![
         CreateSingleSelectFilter {
             condition: SelectOptionCondition::OptionIs,
@@ -86,7 +89,8 @@ async fn grid_filter_single_select_is_test() {
 #[tokio::test]
 async fn grid_filter_single_select_is_test2() {
     let mut test = GridFilterTest::new().await;
-    let mut options = test.get_single_select_type_option();
+    let field_rev = test.get_first_field_rev(FieldType::SingleSelect);
+    let mut options = test.get_single_select_type_option(&field_rev.id).options;
     let option = options.remove(0);
     let scripts = vec![
         CreateSingleSelectFilter {

+ 2 - 2
frontend/rust-lib/flowy-grid/tests/grid/filter_test/text_filter_test.rs

@@ -38,7 +38,7 @@ async fn grid_filter_text_is_not_empty_test() {
     test.run_scripts(scripts).await;
 
     let filter = test.grid_filters().await.pop().unwrap();
-    let field_rev = test.get_field_rev(FieldType::RichText).clone();
+    let field_rev = test.get_first_field_rev(FieldType::RichText).clone();
     test.run_scripts(vec![
         DeleteFilter {
             filter_id: filter.id,
@@ -184,7 +184,7 @@ async fn grid_update_text_filter_test() {
 #[tokio::test]
 async fn grid_filter_delete_test() {
     let mut test = GridFilterTest::new().await;
-    let field_rev = test.get_field_rev(FieldType::RichText).clone();
+    let field_rev = test.get_first_field_rev(FieldType::RichText).clone();
     let text_filter = TextFilterPB {
         condition: TextFilterCondition::TextIsEmpty,
         content: "".to_string(),

+ 28 - 6
frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs

@@ -89,7 +89,19 @@ impl GridEditorTest {
         self.editor.get_all_filters().await.unwrap()
     }
 
-    pub fn get_field_rev(&self, field_type: FieldType) -> &Arc<FieldRevision> {
+    pub fn get_field_rev(&self, field_id: &str, field_type: FieldType) -> &Arc<FieldRevision> {
+        self.field_revs
+            .iter()
+            .filter(|field_rev| {
+                let t_field_type: FieldType = field_rev.ty.into();
+                field_rev.id == field_id && t_field_type == field_type
+            })
+            .collect::<Vec<_>>()
+            .pop()
+            .unwrap()
+    }
+
+    pub fn get_first_field_rev(&self, field_type: FieldType) -> &Arc<FieldRevision> {
         self.field_revs
             .iter()
             .filter(|field_rev| {
@@ -101,23 +113,33 @@ impl GridEditorTest {
             .unwrap()
     }
 
-    pub fn get_multi_select_type_option(&self) -> Vec<SelectOptionPB> {
+    pub fn get_multi_select_type_option(&self, field_id: &str) -> Vec<SelectOptionPB> {
         let field_type = FieldType::MultiSelect;
-        let field_rev = self.get_field_rev(field_type.clone());
+        let field_rev = self.get_field_rev(field_id, field_type.clone());
         let type_option = field_rev
             .get_type_option::<MultiSelectTypeOptionPB>(field_type.into())
             .unwrap();
         type_option.options
     }
 
-    pub fn get_single_select_type_option(&self) -> Vec<SelectOptionPB> {
+    pub fn get_single_select_type_option(&self, field_id: &str) -> SingleSelectTypeOptionPB {
         let field_type = FieldType::SingleSelect;
-        let field_rev = self.get_field_rev(field_type.clone());
+        let field_rev = self.get_field_rev(field_id, field_type.clone());
         let type_option = field_rev
             .get_type_option::<SingleSelectTypeOptionPB>(field_type.into())
             .unwrap();
-        type_option.options
+        type_option
+    }
+
+    pub fn get_checkbox_type_option(&self, field_id: &str) -> CheckboxTypeOptionPB {
+        let field_type = FieldType::Checkbox;
+        let field_rev = self.get_field_rev(field_id, field_type.clone());
+        let type_option = field_rev
+            .get_type_option::<CheckboxTypeOptionPB>(field_type.into())
+            .unwrap();
+        type_option
     }
+
     pub fn block_id(&self) -> &str {
         &self.block_meta_revs.last().unwrap().block_id
     }

+ 0 - 1
shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs

@@ -168,7 +168,6 @@ impl GridRevisionPad {
                     let old_field_type_option = mut_field_rev.get_type_option_str(mut_field_rev.ty);
                     match mut_field_rev.get_type_option_str(new_field_type) {
                         Some(new_field_type_option) => {
-                            //
                             let transformed_type_option =
                                 type_option_transform(old_field_type_rev, old_field_type_option, new_field_type_option);
                             mut_field_rev.insert_type_option_str(&new_field_type, transformed_type_option);