mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add transform field tests (#1504)
Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
parent
925ef48a83
commit
acaaabee2a
@ -117,7 +117,7 @@ pub(crate) async fn update_field_type_option_handler(
|
||||
let editor = manager.get_grid_editor(¶ms.grid_id).await?;
|
||||
let old_field_rev = editor.get_field_rev(¶ms.field_id).await;
|
||||
let _ = editor
|
||||
.did_update_field_type_option(
|
||||
.update_field_type_option(
|
||||
¶ms.grid_id,
|
||||
¶ms.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, ¶ms.field_type).await?;
|
||||
let _ = editor
|
||||
.did_update_field_type_option(¶ms.grid_id, &new_field_rev.id, type_option_data, old_field_rev)
|
||||
.update_field_type_option(¶ms.grid_id, &new_field_rev.id, type_option_data, old_field_rev)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
|
@ -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?;
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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(¤t_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(¶ms.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(¶ms.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)?))
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user