chore: add transform field tests (#1504)

Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
Nathan.fooo 2022-11-29 13:34:10 +08:00 committed by GitHub
parent 925ef48a83
commit acaaabee2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 156 additions and 101 deletions

View File

@ -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(())

View File

@ -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?;
}

View File

@ -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(),
}

View File

@ -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,

View File

@ -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

View File

@ -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)?))

View File

@ -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);
}

View File

@ -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));
}

View File

@ -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);

View File

@ -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 {

View File

@ -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(),

View File

@ -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
}

View File

@ -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);