chore: unit test for cell content

This commit is contained in:
appflowy 2022-07-13 17:25:03 +08:00
parent f10e324b73
commit 602aab45e2
33 changed files with 338 additions and 175 deletions

View File

@ -1,9 +1,11 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::cell::{CellData, FromCellString};
use bytes::Bytes; use bytes::Bytes;
use flowy_error::{internal_error, FlowyError, FlowyResult}; use flowy_error::{internal_error, FlowyError, FlowyResult};
use flowy_grid_data_model::revision::CellRevision; use flowy_grid_data_model::revision::CellRevision;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::str::FromStr; use std::str::FromStr;
/// AnyCellData is a generic CellData, you can parse the cell_data according to the field_type. /// AnyCellData is a generic CellData, you can parse the cell_data according to the field_type.
/// When the type of field is changed, it's different from the field_type of AnyCellData. /// When the type of field is changed, it's different from the field_type of AnyCellData.
/// So it will return an empty data. You could check the CellDataOperation trait for more information. /// So it will return an empty data. You could check the CellDataOperation trait for more information.
@ -46,6 +48,15 @@ impl std::convert::TryFrom<CellRevision> for AnyCellData {
} }
} }
impl<T> std::convert::From<AnyCellData> for CellData<T>
where
T: FromCellString,
{
fn from(any_call_data: AnyCellData) -> Self {
CellData::from(any_call_data.data)
}
}
impl AnyCellData { impl AnyCellData {
pub fn new(content: String, field_type: FieldType) -> Self { pub fn new(content: String, field_type: FieldType) -> Self {
AnyCellData { AnyCellData {
@ -102,6 +113,11 @@ impl AnyCellData {
#[derive(Default)] #[derive(Default)]
pub struct CellBytes(pub Bytes); pub struct CellBytes(pub Bytes);
pub trait CellBytesParser {
type Object;
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object>;
}
impl CellBytes { impl CellBytes {
pub fn new<T: AsRef<[u8]>>(data: T) -> Self { pub fn new<T: AsRef<[u8]>>(data: T) -> Self {
let bytes = Bytes::from(data.as_ref().to_vec()); let bytes = Bytes::from(data.as_ref().to_vec());
@ -116,12 +132,19 @@ impl CellBytes {
Ok(Self(bytes)) Ok(Self(bytes))
} }
pub fn parse<'a, T: TryFrom<&'a [u8]>>(&'a self) -> FlowyResult<T> pub fn with_parser<P>(&self, parser: P) -> FlowyResult<P::Object>
where where
<T as TryFrom<&'a [u8]>>::Error: std::fmt::Debug, P: CellBytesParser,
{ {
T::try_from(self.0.as_ref()).map_err(internal_error) parser.parse(&self.0)
} }
// pub fn parse<'a, T: TryFrom<&'a [u8]>>(&'a self) -> FlowyResult<T>
// where
// <T as TryFrom<&'a [u8]>>::Error: std::fmt::Debug,
// {
// T::try_from(self.0.as_ref()).map_err(internal_error)
// }
} }
impl ToString for CellBytes { impl ToString for CellBytes {

View File

@ -163,9 +163,9 @@ where
} }
} }
impl std::convert::From<String> for CellData<String> { impl<T> std::convert::From<T> for CellData<T> {
fn from(s: String) -> Self { fn from(val: T) -> Self {
CellData(Some(s)) CellData(Some(val))
} }
} }

View File

@ -7,6 +7,7 @@ use flowy_derive::ProtoBuf;
use flowy_error::{FlowyError, FlowyResult}; use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry}; use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::str::FromStr;
#[derive(Default)] #[derive(Default)]
pub struct CheckboxTypeOptionBuilder(CheckboxTypeOption); pub struct CheckboxTypeOptionBuilder(CheckboxTypeOption);
@ -69,7 +70,7 @@ impl CellDataOperation<CheckboxCellData, String> for CheckboxTypeOption {
_cell_rev: Option<CellRevision>, _cell_rev: Option<CellRevision>,
) -> Result<String, FlowyError> { ) -> Result<String, FlowyError> {
let changeset = changeset.try_into_inner()?; let changeset = changeset.try_into_inner()?;
let cell_data = CheckboxCellData::from_str(&changeset); let cell_data = CheckboxCellData::from_str(&changeset)?;
Ok(cell_data.to_string()) Ok(cell_data.to_string())
} }
} }

View File

@ -1,5 +1,7 @@
use crate::services::cell::{AnyCellData, FromCellString}; use crate::services::cell::{CellBytesParser, FromCellString};
use bytes::Bytes;
use flowy_error::{FlowyError, FlowyResult}; use flowy_error::{FlowyError, FlowyResult};
use std::str::FromStr;
pub const YES: &str = "Yes"; pub const YES: &str = "Yes";
pub const NO: &str = "No"; pub const NO: &str = "No";
@ -7,7 +9,21 @@ pub const NO: &str = "No";
pub struct CheckboxCellData(pub String); pub struct CheckboxCellData(pub String);
impl CheckboxCellData { impl CheckboxCellData {
pub fn from_str(s: &str) -> Self { pub fn is_check(&self) -> bool {
self.0 == YES
}
}
impl AsRef<[u8]> for CheckboxCellData {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl FromStr for CheckboxCellData {
type Err = FlowyError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let lower_case_str: &str = &s.to_lowercase(); let lower_case_str: &str = &s.to_lowercase();
let val = match lower_case_str { let val = match lower_case_str {
"1" => Some(true), "1" => Some(true),
@ -20,29 +36,11 @@ impl CheckboxCellData {
}; };
match val { match val {
Some(true) => Self(YES.to_string()), Some(true) => Ok(Self(YES.to_string())),
Some(false) => Self(NO.to_string()), Some(false) => Ok(Self(NO.to_string())),
None => Self("".to_string()), None => Ok(Self("".to_string())),
} }
} }
pub fn is_check(&self) -> bool {
&self.0 == YES
}
}
impl AsRef<[u8]> for CheckboxCellData {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl std::convert::TryFrom<AnyCellData> for CheckboxCellData {
type Error = FlowyError;
fn try_from(value: AnyCellData) -> Result<Self, Self::Error> {
Ok(Self::from_str(&value.data))
}
} }
impl FromCellString for CheckboxCellData { impl FromCellString for CheckboxCellData {
@ -50,7 +48,7 @@ impl FromCellString for CheckboxCellData {
where where
Self: Sized, Self: Sized,
{ {
Ok(Self::from_str(s)) Self::from_str(s)
} }
} }
@ -59,3 +57,13 @@ impl ToString for CheckboxCellData {
self.0.clone() self.0.clone()
} }
} }
pub struct CheckboxCellDataParser;
impl CellBytesParser for CheckboxCellDataParser {
type Object = CheckboxCellData;
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
match String::from_utf8(bytes.to_vec()) {
Ok(s) => CheckboxCellData::from_str(&s),
Err(_) => Ok(CheckboxCellData("".to_string())),
}
}
}

View File

@ -1,6 +1,6 @@
mod checkbox_option; mod checkbox_option;
mod checkbox_option_entities; mod checkbox_option_entities;
mod tests; mod checkbox_tests;
pub use checkbox_option::*; pub use checkbox_option::*;
pub use checkbox_option_entities::*; pub use checkbox_option_entities::*;

View File

@ -1,22 +1,17 @@
use crate::entities::{FieldType}; use crate::entities::FieldType;
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{ use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
AnyCellData, CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable, FromCellChangeset,
FromCellString,
};
use crate::services::field::{ use crate::services::field::{
BoxTypeOptionBuilder, DateCellChangeset, DateCellData, DateFormat, DateTimestamp, TimeFormat, TypeOptionBuilder, BoxTypeOptionBuilder, DateCellChangeset, DateCellData, DateFormat, DateTimestamp, TimeFormat, TypeOptionBuilder,
}; };
use bytes::Bytes; use bytes::Bytes;
use chrono::format::strftime::StrftimeItems; use chrono::format::strftime::StrftimeItems;
use chrono::{NaiveDateTime, Timelike}; use chrono::{NaiveDateTime, Timelike};
use flowy_derive::{ProtoBuf}; use flowy_derive::ProtoBuf;
use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry}; use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
// Date // Date
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct DateTypeOption { pub struct DateTypeOption {
@ -129,7 +124,8 @@ impl CellDisplayable<DateTimestamp> for DateTypeOption {
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
let timestamp = cell_data.try_into_inner()?; let timestamp = cell_data.try_into_inner()?;
CellBytes::from(self.today_desc_from_timestamp(timestamp)) let date_cell_data = self.today_desc_from_timestamp(timestamp);
CellBytes::from(date_cell_data)
} }
} }

View File

@ -1,6 +1,7 @@
use crate::entities::CellChangeset; use crate::entities::CellChangeset;
use crate::entities::{CellIdentifier, CellIdentifierPayload}; use crate::entities::{CellIdentifier, CellIdentifierPayload};
use crate::services::cell::{AnyCellData, FromCellChangeset, FromCellString}; use crate::services::cell::{CellBytesParser, FromCellChangeset, FromCellString};
use bytes::Bytes;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::{internal_error, ErrorCode, FlowyResult}; use flowy_error::{internal_error, ErrorCode, FlowyResult};
@ -117,12 +118,6 @@ impl FromCellString for DateTimestamp {
} }
} }
impl std::convert::From<AnyCellData> for DateTimestamp {
fn from(data: AnyCellData) -> Self {
let num = data.data.parse::<i64>().unwrap_or(0);
DateTimestamp(num)
}
}
#[derive(Clone, Debug, Copy, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)] #[derive(Clone, Debug, Copy, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
pub enum DateFormat { pub enum DateFormat {
Local = 0, Local = 0,
@ -204,3 +199,12 @@ impl std::default::Default for TimeFormat {
TimeFormat::TwentyFourHour TimeFormat::TwentyFourHour
} }
} }
pub struct DateCellDataParser();
impl CellBytesParser for DateCellDataParser {
type Object = DateCellData;
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
DateCellData::try_from(bytes.as_ref()).map_err(internal_error)
}
}

View File

@ -2,8 +2,8 @@
mod tests { mod tests {
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::cell::{CellDataChangeset, CellDataOperation}; use crate::services::cell::{CellDataChangeset, CellDataOperation};
use crate::services::field::FieldBuilder; use crate::services::field::*;
use crate::services::field::{DateCellChangeset, DateCellData, DateFormat, DateTypeOption, TimeFormat}; // use crate::services::field::{DateCellChangeset, DateCellData, DateFormat, DateTypeOption, TimeFormat};
use flowy_grid_data_model::revision::FieldRevision; use flowy_grid_data_model::revision::FieldRevision;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
@ -260,7 +260,7 @@ mod tests {
let decoded_data = type_option let decoded_data = type_option
.decode_cell_data(encoded_data.into(), &FieldType::DateTime, field_rev) .decode_cell_data(encoded_data.into(), &FieldType::DateTime, field_rev)
.unwrap() .unwrap()
.parse::<DateCellData>() .with_parser(DateCellDataParser())
.unwrap(); .unwrap();
if type_option.include_time { if type_option.include_time {

View File

@ -1,6 +1,6 @@
mod date_option; mod date_option;
mod date_option_entities; mod date_option_entities;
mod tests; mod date_tests;
pub use date_option::*; pub use date_option::*;
pub use date_option_entities::*; pub use date_option_entities::*;

View File

@ -2,7 +2,7 @@
mod format; mod format;
mod number_option; mod number_option;
mod number_option_entities; mod number_option_entities;
mod tests; mod number_tests;
pub use format::*; pub use format::*;
pub use number_option::*; pub use number_option::*;

View File

@ -1,8 +1,6 @@
use crate::impl_type_option;
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::impl_type_option;
use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation}; use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation};
use crate::services::field::number_currency::Currency;
use crate::services::field::type_options::number_type_option::format::*; use crate::services::field::type_options::number_type_option::format::*;
use crate::services::field::{BoxTypeOptionBuilder, NumberCellData, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, NumberCellData, TypeOptionBuilder};
use bytes::Bytes; use bytes::Bytes;
@ -11,7 +9,7 @@ use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry}; use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry};
use rust_decimal::Decimal; use rust_decimal::Decimal;
use rusty_money::Money;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::str::FromStr; use std::str::FromStr;

View File

@ -1,6 +1,8 @@
use crate::services::cell::CellBytesParser;
use crate::services::field::number_currency::Currency; use crate::services::field::number_currency::Currency;
use crate::services::field::{strip_currency_symbol, NumberFormat, STRIP_SYMBOL}; use crate::services::field::{strip_currency_symbol, NumberFormat, STRIP_SYMBOL};
use flowy_error::{FlowyError, FlowyResult}; use bytes::Bytes;
use flowy_error::{internal_error, FlowyError, FlowyResult};
use rust_decimal::Decimal; use rust_decimal::Decimal;
use rusty_money::Money; use rusty_money::Money;
use std::str::FromStr; use std::str::FromStr;
@ -68,17 +70,17 @@ impl NumberCellData {
} }
} }
impl FromStr for NumberCellData { // impl FromStr for NumberCellData {
type Err = rust_decimal::Error; // type Err = FlowyError;
//
fn from_str(s: &str) -> Result<Self, Self::Err> { // fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.is_empty() { // if s.is_empty() {
return Ok(Self::default()); // return Ok(Self::default());
} // }
let decimal = Decimal::from_str(s)?; // let decimal = Decimal::from_str(s).map_err(internal_error)?;
Ok(Self::from_decimal(decimal)) // Ok(Self::from_decimal(decimal))
} // }
} // }
impl ToString for NumberCellData { impl ToString for NumberCellData {
fn to_string(&self) -> String { fn to_string(&self) -> String {
@ -91,3 +93,13 @@ impl ToString for NumberCellData {
} }
} }
} }
pub struct NumberCellDataParser(pub NumberFormat);
impl CellBytesParser for NumberCellDataParser {
type Object = NumberCellData;
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
match String::from_utf8(bytes.to_vec()) {
Ok(s) => NumberCellData::from_format_str(&s, true, &self.0),
Err(_) => Ok(NumberCellData::default()),
}
}
}

View File

@ -180,7 +180,7 @@ mod tests {
type_option type_option
.decode_cell_data(cell_data.into(), &field_type, field_rev) .decode_cell_data(cell_data.into(), &field_type, field_rev)
.unwrap() .unwrap()
.parse::<SelectOptionCellData>() .with_parser(SelectOptionCellDataParser())
.unwrap() .unwrap()
.select_options, .select_options,
); );

View File

@ -1,8 +1,9 @@
use crate::entities::{CellChangeset, CellIdentifier, CellIdentifierPayload, FieldType}; use crate::entities::{CellChangeset, CellIdentifier, CellIdentifierPayload, FieldType};
use crate::services::cell::{AnyCellData, CellBytes, CellData, CellDisplayable, FromCellChangeset, FromCellString}; use crate::services::cell::{CellBytes, CellBytesParser, CellData, CellDisplayable, FromCellChangeset, FromCellString};
use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOption}; use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOption};
use bytes::Bytes;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::{internal_error, ErrorCode, FlowyError, FlowyResult}; use flowy_error::{internal_error, ErrorCode, FlowyResult};
use flowy_grid_data_model::parser::NotEmptyStr; use flowy_grid_data_model::parser::NotEmptyStr;
use flowy_grid_data_model::revision::{FieldRevision, TypeOptionDataEntry}; use flowy_grid_data_model::revision::{FieldRevision, TypeOptionDataEntry};
use nanoid::nanoid; use nanoid::nanoid;
@ -160,20 +161,6 @@ impl SelectOptionIds {
} }
} }
impl std::convert::TryFrom<AnyCellData> for SelectOptionIds {
type Error = FlowyError;
fn try_from(value: AnyCellData) -> Result<Self, Self::Error> {
Ok(Self::from(value.data))
}
}
impl std::convert::From<AnyCellData> for CellData<SelectOptionIds> {
fn from(any_cell_data: AnyCellData) -> Self {
any_cell_data.data.into()
}
}
impl FromCellString for SelectOptionIds { impl FromCellString for SelectOptionIds {
fn from_cell_str(s: &str) -> FlowyResult<Self> fn from_cell_str(s: &str) -> FlowyResult<Self>
where where
@ -215,6 +202,25 @@ impl std::ops::DerefMut for SelectOptionIds {
&mut self.0 &mut self.0
} }
} }
pub struct SelectOptionIdsParser();
impl CellBytesParser for SelectOptionIdsParser {
type Object = SelectOptionIds;
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
match String::from_utf8(bytes.to_vec()) {
Ok(s) => Ok(SelectOptionIds::from(s)),
Err(_) => Ok(SelectOptionIds::from("".to_owned())),
}
}
}
pub struct SelectOptionCellDataParser();
impl CellBytesParser for SelectOptionCellDataParser {
type Object = SelectOptionCellData;
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
SelectOptionCellData::try_from(bytes.as_ref()).map_err(internal_error)
}
}
#[derive(Clone, Debug, Default, ProtoBuf)] #[derive(Clone, Debug, Default, ProtoBuf)]
pub struct SelectOptionCellChangesetPayload { pub struct SelectOptionCellChangesetPayload {

View File

@ -162,7 +162,7 @@ mod tests {
type_option type_option
.decode_cell_data(cell_data.into(), &field_type, field_rev) .decode_cell_data(cell_data.into(), &field_type, field_rev)
.unwrap() .unwrap()
.parse::<SelectOptionCellData>() .with_parser(SelectOptionCellDataParser())
.unwrap() .unwrap()
.select_options, .select_options,
); );

View File

@ -1,7 +1,8 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{ use crate::services::cell::{
try_decode_cell_data, AnyCellData, CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable, try_decode_cell_data, CellBytes, CellBytesParser, CellData, CellDataChangeset, CellDataOperation, CellDisplayable,
FromCellString,
}; };
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
use bytes::Bytes; use bytes::Bytes;
@ -83,11 +84,23 @@ impl AsRef<str> for TextCellData {
} }
} }
impl std::convert::TryFrom<AnyCellData> for TextCellData { impl FromCellString for TextCellData {
type Error = FlowyError; fn from_cell_str(s: &str) -> FlowyResult<Self>
where
Self: Sized,
{
Ok(TextCellData(s.to_owned()))
}
}
fn try_from(value: AnyCellData) -> Result<Self, Self::Error> { pub struct TextCellDataParser();
Ok(TextCellData(value.data)) impl CellBytesParser for TextCellDataParser {
type Object = TextCellData;
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
match String::from_utf8(bytes.to_vec()) {
Ok(s) => Ok(TextCellData(s)),
Err(_) => Ok(TextCellData("".to_owned())),
}
} }
} }
@ -111,7 +124,7 @@ mod tests {
type_option type_option
.decode_cell_data(1647251762.to_string().into(), &field_type, &date_time_field_rev) .decode_cell_data(1647251762.to_string().into(), &field_type, &date_time_field_rev)
.unwrap() .unwrap()
.parse::<DateCellData>() .with_parser(DateCellDataParser())
.unwrap() .unwrap()
.date, .date,
"Mar 14,2022".to_owned() "Mar 14,2022".to_owned()
@ -131,7 +144,7 @@ mod tests {
&single_select_field_rev &single_select_field_rev
) )
.unwrap() .unwrap()
.parse::<SelectOptionCellData>() .with_parser(SelectOptionCellDataParser())
.unwrap() .unwrap()
.select_options, .select_options,
vec![done_option], vec![done_option],
@ -154,7 +167,7 @@ mod tests {
type_option type_option
.decode_cell_data(cell_data.into(), &FieldType::MultiSelect, &multi_select_field_rev) .decode_cell_data(cell_data.into(), &FieldType::MultiSelect, &multi_select_field_rev)
.unwrap() .unwrap()
.parse::<SelectOptionCellData>() .with_parser(SelectOptionCellDataParser())
.unwrap() .unwrap()
.select_options, .select_options,
vec![google_option, facebook_option] vec![google_option, facebook_option]

View File

@ -1,6 +1,6 @@
mod tests;
mod url_option; mod url_option;
mod url_option_entities; mod url_option_entities;
mod url_tests;
pub use url_option::*; pub use url_option::*;
pub use url_option_entities::*; pub use url_option_entities::*;

View File

@ -1,13 +1,11 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{ use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
AnyCellData, CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable, FromCellString,
};
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder, URLCellData}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder, URLCellData};
use bytes::Bytes; use bytes::Bytes;
use fancy_regex::Regex; use fancy_regex::Regex;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_error::{internal_error, FlowyError, FlowyResult}; use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry}; use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -64,16 +62,12 @@ impl CellDataOperation<URLCellData, String> for URLTypeOption {
changeset: CellDataChangeset<String>, changeset: CellDataChangeset<String>,
_cell_rev: Option<CellRevision>, _cell_rev: Option<CellRevision>,
) -> Result<String, FlowyError> { ) -> Result<String, FlowyError> {
let changeset = changeset.try_into_inner()?; let content = changeset.try_into_inner()?;
let mut url = "".to_string(); let mut url = "".to_string();
if let Ok(Some(m)) = URL_REGEX.find(&changeset) { if let Ok(Some(m)) = URL_REGEX.find(&content) {
url = auto_append_scheme(m.as_str()); url = auto_append_scheme(m.as_str());
} }
URLCellData { URLCellData { url, content }.to_json()
url,
content: changeset,
}
.to_json()
} }
} }

View File

@ -1,6 +1,7 @@
use crate::services::cell::{AnyCellData, FromCellString}; use crate::services::cell::{CellBytesParser, FromCellString};
use bytes::Bytes;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_error::{internal_error, FlowyError, FlowyResult}; use flowy_error::{internal_error, FlowyResult};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
@ -25,16 +26,17 @@ impl URLCellData {
} }
} }
pub struct URLCellDataParser();
impl CellBytesParser for URLCellDataParser {
type Object = URLCellData;
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
URLCellData::try_from(bytes.as_ref()).map_err(internal_error)
}
}
impl FromCellString for URLCellData { impl FromCellString for URLCellData {
fn from_cell_str(s: &str) -> FlowyResult<Self> { fn from_cell_str(s: &str) -> FlowyResult<Self> {
serde_json::from_str::<URLCellData>(s).map_err(internal_error) serde_json::from_str::<URLCellData>(s).map_err(internal_error)
} }
} }
impl std::convert::TryFrom<AnyCellData> for URLCellData {
type Error = FlowyError;
fn try_from(data: AnyCellData) -> Result<Self, Self::Error> {
serde_json::from_str::<URLCellData>(&data.data).map_err(internal_error)
}
}

View File

@ -2,7 +2,7 @@
mod tests { mod tests {
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::cell::{CellData, CellDataOperation}; use crate::services::cell::{CellData, CellDataOperation};
use crate::services::field::FieldBuilder; use crate::services::field::{FieldBuilder, URLCellDataParser};
use crate::services::field::{URLCellData, URLTypeOption}; use crate::services::field::{URLCellData, URLTypeOption};
use flowy_grid_data_model::revision::FieldRevision; use flowy_grid_data_model::revision::FieldRevision;
@ -61,7 +61,7 @@ mod tests {
type_option type_option
.decode_cell_data(encoded_data.into(), field_type, field_rev) .decode_cell_data(encoded_data.into(), field_type, field_rev)
.unwrap() .unwrap()
.parse::<URLCellData>() .with_parser(URLCellDataParser())
.unwrap() .unwrap()
} }
} }

View File

@ -1,5 +1,5 @@
use crate::entities::{CheckboxCondition, GridCheckboxFilter}; use crate::entities::{CheckboxCondition, GridCheckboxFilter};
use crate::services::cell::{AnyCellData, CellFilterOperation}; use crate::services::cell::{AnyCellData, CellData, CellFilterOperation};
use crate::services::field::{CheckboxCellData, CheckboxTypeOption}; use crate::services::field::{CheckboxCellData, CheckboxTypeOption};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
@ -18,7 +18,8 @@ impl CellFilterOperation<GridCheckboxFilter> for CheckboxTypeOption {
if !any_cell_data.is_checkbox() { if !any_cell_data.is_checkbox() {
return Ok(true); return Ok(true);
} }
let checkbox_cell_data: CheckboxCellData = any_cell_data.try_into()?; let cell_data: CellData<CheckboxCellData> = any_cell_data.into();
let checkbox_cell_data = cell_data.try_into_inner()?;
Ok(filter.is_visible(&checkbox_cell_data)) Ok(filter.is_visible(&checkbox_cell_data))
} }
} }

View File

@ -1,5 +1,5 @@
use crate::entities::{DateFilterCondition, GridDateFilter}; use crate::entities::{DateFilterCondition, GridDateFilter};
use crate::services::cell::{AnyCellData, CellFilterOperation}; use crate::services::cell::{AnyCellData, CellData, CellFilterOperation};
use crate::services::field::{DateTimestamp, DateTypeOption}; use crate::services::field::{DateTimestamp, DateTypeOption};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
@ -34,7 +34,8 @@ impl CellFilterOperation<GridDateFilter> for DateTypeOption {
if !any_cell_data.is_date() { if !any_cell_data.is_date() {
return Ok(true); return Ok(true);
} }
let timestamp: DateTimestamp = any_cell_data.into(); let cell_data: CellData<DateTimestamp> = any_cell_data.into();
let timestamp = cell_data.try_into_inner()?;
Ok(filter.is_visible(timestamp)) Ok(filter.is_visible(timestamp))
} }
} }

View File

@ -47,9 +47,7 @@ impl CellFilterOperation<GridNumberFilter> for NumberTypeOption {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::entities::{GridNumberFilter, NumberFilterCondition}; use crate::entities::{GridNumberFilter, NumberFilterCondition};
use crate::services::field::{NumberCellData, NumberFormat}; use crate::services::field::{NumberCellData, NumberFormat};
use std::str::FromStr;
#[test] #[test]
fn number_filter_equal_test() { fn number_filter_equal_test() {
let number_filter = GridNumberFilter { let number_filter = GridNumberFilter {
@ -58,7 +56,7 @@ mod tests {
}; };
for (num_str, visible) in [("123", true), ("1234", false), ("", false)] { for (num_str, visible) in [("123", true), ("1234", false), ("", false)] {
let data = NumberCellData::from_str(num_str).unwrap(); let data = NumberCellData::from_format_str(num_str, true, &NumberFormat::Num).unwrap();
assert_eq!(number_filter.is_visible(&data), visible); assert_eq!(number_filter.is_visible(&data), visible);
} }
@ -75,7 +73,7 @@ mod tests {
content: Some("12".to_owned()), content: Some("12".to_owned()),
}; };
for (num_str, visible) in [("123", true), ("10", false), ("30", true), ("", false)] { for (num_str, visible) in [("123", true), ("10", false), ("30", true), ("", false)] {
let data = NumberCellData::from_str(num_str).unwrap(); let data = NumberCellData::from_format_str(num_str, true, &NumberFormat::Num).unwrap();
assert_eq!(number_filter.is_visible(&data), visible); assert_eq!(number_filter.is_visible(&data), visible);
} }
} }
@ -87,7 +85,7 @@ mod tests {
content: Some("100".to_owned()), content: Some("100".to_owned()),
}; };
for (num_str, visible) in [("12", true), ("1234", false), ("30", true), ("", true)] { for (num_str, visible) in [("12", true), ("1234", false), ("30", true), ("", true)] {
let data = NumberCellData::from_str(num_str).unwrap(); let data = NumberCellData::from_format_str(num_str, true, &NumberFormat::Num).unwrap();
assert_eq!(number_filter.is_visible(&data), visible); assert_eq!(number_filter.is_visible(&data), visible);
} }
} }

View File

@ -1,5 +1,5 @@
use crate::entities::{GridTextFilter, TextFilterCondition}; use crate::entities::{GridTextFilter, TextFilterCondition};
use crate::services::cell::{AnyCellData, CellFilterOperation}; use crate::services::cell::{AnyCellData, CellData, CellFilterOperation};
use crate::services::field::{RichTextTypeOption, TextCellData}; use crate::services::field::{RichTextTypeOption, TextCellData};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
@ -30,7 +30,8 @@ impl CellFilterOperation<GridTextFilter> for RichTextTypeOption {
return Ok(true); return Ok(true);
} }
let text_cell_data: TextCellData = any_cell_data.try_into()?; let cell_data: CellData<TextCellData> = any_cell_data.into();
let text_cell_data = cell_data.try_into_inner()?;
Ok(filter.is_visible(text_cell_data)) Ok(filter.is_visible(text_cell_data))
} }
} }

View File

@ -1,5 +1,5 @@
use crate::entities::GridTextFilter; use crate::entities::GridTextFilter;
use crate::services::cell::{AnyCellData, CellFilterOperation}; use crate::services::cell::{AnyCellData, CellData, CellFilterOperation};
use crate::services::field::{TextCellData, URLTypeOption}; use crate::services::field::{TextCellData, URLTypeOption};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
@ -9,7 +9,8 @@ impl CellFilterOperation<GridTextFilter> for URLTypeOption {
return Ok(true); return Ok(true);
} }
let text_cell_data: TextCellData = any_cell_data.try_into()?; let cell_data: CellData<TextCellData> = any_cell_data.into();
let text_cell_data = cell_data.try_into_inner()?;
Ok(filter.is_visible(&text_cell_data)) Ok(filter.is_visible(&text_cell_data))
} }
} }

View File

@ -3,7 +3,7 @@ use crate::entities::CellIdentifier;
use crate::entities::*; use crate::entities::*;
use crate::manager::{GridTaskSchedulerRwLock, GridUser}; use crate::manager::{GridTaskSchedulerRwLock, GridUser};
use crate::services::block_manager::GridBlockManager; use crate::services::block_manager::GridBlockManager;
use crate::services::cell::{apply_cell_data_changeset, decode_any_cell_data}; use crate::services::cell::{apply_cell_data_changeset, decode_any_cell_data, CellBytes};
use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder}; use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder};
use crate::services::filter::{GridFilterChangeset, GridFilterService}; use crate::services::filter::{GridFilterChangeset, GridFilterService};
use crate::services::persistence::block_index::BlockIndexCache; use crate::services::persistence::block_index::BlockIndexCache;
@ -340,16 +340,16 @@ impl GridRevisionEditor {
} }
pub async fn get_cell(&self, params: &CellIdentifier) -> Option<Cell> { pub async fn get_cell(&self, params: &CellIdentifier) -> Option<Cell> {
let cell_bytes = self.get_cell_bytes(params).await?;
Some(Cell::new(&params.field_id, cell_bytes.to_vec()))
}
pub async fn get_cell_bytes(&self, params: &CellIdentifier) -> Option<CellBytes> {
let field_rev = self.get_field_rev(&params.field_id).await?; let field_rev = self.get_field_rev(&params.field_id).await?;
let row_rev = self.block_manager.get_row_rev(&params.row_id).await.ok()??; let row_rev = self.block_manager.get_row_rev(&params.row_id).await.ok()??;
let cell_rev = row_rev.cells.get(&params.field_id)?.clone(); let cell_rev = row_rev.cells.get(&params.field_id)?.clone();
let data = decode_any_cell_data(cell_rev.data, &field_rev).to_vec(); Some(decode_any_cell_data(cell_rev.data, &field_rev))
Some(Cell::new(&params.field_id, data))
}
pub async fn get_cell_display(&self, _params: &CellIdentifier) -> Option<String> {
todo!()
} }
pub async fn get_cell_rev(&self, row_id: &str, field_id: &str) -> FlowyResult<Option<CellRevision>> { pub async fn get_cell_rev(&self, row_id: &str, field_id: &str) -> FlowyResult<Option<CellRevision>> {

View File

@ -1,5 +1,6 @@
use crate::grid::block_test::script::GridRowTest; use crate::grid::block_test::script::GridRowTest;
use crate::grid::block_test::script::RowScript::*; use crate::grid::block_test::script::RowScript::*;
use flowy_grid::entities::FieldType;
use flowy_grid_data_model::revision::RowMetaChangeset; use flowy_grid_data_model::revision::RowMetaChangeset;
#[tokio::test] #[tokio::test]
@ -67,15 +68,48 @@ async fn grid_row_add_cells_test() {
let mut test = GridRowTest::new().await; let mut test = GridRowTest::new().await;
let mut builder = test.row_builder(); let mut builder = test.row_builder();
builder.insert_text_cell("hello world"); let text_field_id = builder.insert_text_cell("hello world");
builder.insert_number_cell("18,443"); let number_field_id = builder.insert_number_cell("18,443");
builder.insert_date_cell("1647251762"); let date_field_id = builder.insert_date_cell("1647251762");
builder.insert_single_select_cell(|options| options.first().unwrap()); let single_select_field_id = builder.insert_single_select_cell(|options| options.first().unwrap());
builder.insert_multi_select_cell(|options| options); builder.insert_multi_select_cell(|options| options);
builder.insert_checkbox_cell("false"); builder.insert_checkbox_cell("false");
builder.insert_url_cell("1"); let url_field_id = builder.insert_url_cell("https://appflowy.io");
let row_rev = builder.build(); let row_rev = builder.build();
let scripts = vec![CreateRow { row_rev }]; let row_id = row_rev.id.clone();
let scripts = vec![
CreateRow { row_rev },
AssertCell {
row_id: row_id.clone(),
field_id: text_field_id,
field_type: FieldType::RichText,
expected: "hello world".to_owned(),
},
AssertCell {
row_id: row_id.clone(),
field_id: number_field_id,
field_type: FieldType::Number,
expected: "$18,443.00".to_owned(),
},
AssertCell {
row_id: row_id.clone(),
field_id: single_select_field_id,
field_type: FieldType::SingleSelect,
expected: "Completed".to_owned(),
},
AssertCell {
row_id: row_id.clone(),
field_id: date_field_id,
field_type: FieldType::DateTime,
expected: "2022/03/14".to_owned(),
},
AssertCell {
row_id: row_id.clone(),
field_id: url_field_id,
field_type: FieldType::URL,
expected: "https://appflowy.io/".to_owned(),
},
];
test.run_scripts(scripts).await; test.run_scripts(scripts).await;
} }

View File

@ -1,7 +1,11 @@
use crate::grid::block_test::util::GridRowTestBuilder; use crate::grid::block_test::util::GridRowTestBuilder;
use crate::grid::grid_editor::GridEditorTest; use crate::grid::grid_editor::GridEditorTest;
use flowy_grid::entities::{CellIdentifier, RowInfo}; use flowy_grid::entities::{CellIdentifier, FieldType, RowInfo};
use flowy_grid::services::field::{
DateCellDataParser, NumberCellDataParser, NumberFormat, NumberTypeOption, SelectOptionCellDataParser,
SelectOptionIdsParser, SelectOptionOperation, SingleSelectTypeOption, TextCellDataParser, URLCellDataParser,
};
use flowy_grid_data_model::revision::{ use flowy_grid_data_model::revision::{
GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowMetaChangeset, RowRevision, GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowMetaChangeset, RowRevision,
}; };
@ -24,7 +28,8 @@ pub enum RowScript {
AssertCell { AssertCell {
row_id: String, row_id: String,
field_id: String, field_id: String,
expected_display: Option<String>, field_type: FieldType,
expected: String,
}, },
AssertRowCount(usize), AssertRowCount(usize),
CreateBlock { CreateBlock {
@ -101,20 +106,15 @@ impl GridRowTest {
RowScript::AssertCell { RowScript::AssertCell {
row_id, row_id,
field_id, field_id,
expected_display, field_type,
expected,
} => { } => {
let id = CellIdentifier { let id = CellIdentifier {
grid_id: self.grid_id.clone(), grid_id: self.grid_id.clone(),
field_id, field_id,
row_id, row_id,
}; };
let display = self.editor.get_cell_display(&id).await; self.compare_cell_content(id, field_type, expected).await;
match expected_display {
None => {}
Some(expected_display) => {
assert_eq!(display.unwrap(), expected_display);
}
}
} }
RowScript::AssertRow { expected_row } => { RowScript::AssertRow { expected_row } => {
let row = &*self let row = &*self
@ -153,6 +153,72 @@ impl GridRowTest {
} }
} }
} }
async fn compare_cell_content(&self, cell_id: CellIdentifier, field_type: FieldType, expected: String) {
match field_type {
FieldType::RichText => {
let cell_data = self
.editor
.get_cell_bytes(&cell_id)
.await
.unwrap()
.with_parser(TextCellDataParser())
.unwrap();
assert_eq!(cell_data.as_ref(), &expected);
}
FieldType::Number => {
let field_rev = self.editor.get_field_rev(&cell_id.field_id).await.unwrap();
let number_type_option = field_rev
.get_type_option_entry::<NumberTypeOption>(FieldType::Number.into())
.unwrap();
let cell_data = self
.editor
.get_cell_bytes(&cell_id)
.await
.unwrap()
.with_parser(NumberCellDataParser(number_type_option.format.clone()))
.unwrap();
assert_eq!(cell_data.to_string(), expected);
}
FieldType::DateTime => {
let cell_data = self
.editor
.get_cell_bytes(&cell_id)
.await
.unwrap()
.with_parser(DateCellDataParser())
.unwrap();
assert_eq!(cell_data.date, expected);
}
FieldType::SingleSelect => {
let select_options = self
.editor
.get_cell_bytes(&cell_id)
.await
.unwrap()
.with_parser(SelectOptionCellDataParser())
.unwrap();
let select_option = select_options.select_options.first().unwrap();
assert_eq!(select_option.name, expected);
}
FieldType::MultiSelect => {}
FieldType::Checkbox => {}
FieldType::URL => {
let cell_data = self
.editor
.get_cell_bytes(&cell_id)
.await
.unwrap()
.with_parser(URLCellDataParser())
.unwrap();
assert_eq!(cell_data.content, expected);
assert_eq!(cell_data.url, expected);
}
}
}
} }
impl std::ops::Deref for GridRowTest { impl std::ops::Deref for GridRowTest {

View File

@ -23,21 +23,24 @@ impl<'a> GridRowTestBuilder<'a> {
} }
} }
pub fn insert_text_cell(&mut self, data: &str) { pub fn insert_text_cell(&mut self, data: &str) -> String {
let text_field = self.field_rev_with_type(&FieldType::RichText); let text_field = self.field_rev_with_type(&FieldType::RichText);
self.inner_builder self.inner_builder
.insert_cell(&text_field.id, data.to_string()) .insert_cell(&text_field.id, data.to_string())
.unwrap(); .unwrap();
text_field.id.clone()
} }
pub fn insert_number_cell(&mut self, data: &str) { pub fn insert_number_cell(&mut self, data: &str) -> String {
let number_field = self.field_rev_with_type(&FieldType::Number); let number_field = self.field_rev_with_type(&FieldType::Number);
self.inner_builder self.inner_builder
.insert_cell(&number_field.id, data.to_string()) .insert_cell(&number_field.id, data.to_string())
.unwrap(); .unwrap();
number_field.id.clone()
} }
pub fn insert_date_cell(&mut self, data: &str) { pub fn insert_date_cell(&mut self, data: &str) -> String {
let value = serde_json::to_string(&DateCellChangeset { let value = serde_json::to_string(&DateCellChangeset {
date: Some(data.to_string()), date: Some(data.to_string()),
time: None, time: None,
@ -45,6 +48,7 @@ impl<'a> GridRowTestBuilder<'a> {
.unwrap(); .unwrap();
let date_field = self.field_rev_with_type(&FieldType::DateTime); let date_field = self.field_rev_with_type(&FieldType::DateTime);
self.inner_builder.insert_cell(&date_field.id, value).unwrap(); self.inner_builder.insert_cell(&date_field.id, value).unwrap();
date_field.id.clone()
} }
pub fn insert_checkbox_cell(&mut self, data: &str) { pub fn insert_checkbox_cell(&mut self, data: &str) {
@ -54,14 +58,13 @@ impl<'a> GridRowTestBuilder<'a> {
.unwrap(); .unwrap();
} }
pub fn insert_url_cell(&mut self, data: &str) { pub fn insert_url_cell(&mut self, data: &str) -> String {
let number_field = self.field_rev_with_type(&FieldType::URL); let url_field = self.field_rev_with_type(&FieldType::URL);
self.inner_builder self.inner_builder.insert_cell(&url_field.id, data.to_string()).unwrap();
.insert_cell(&number_field.id, data.to_string()) url_field.id.clone()
.unwrap();
} }
pub fn insert_single_select_cell<F>(&mut self, f: F) pub fn insert_single_select_cell<F>(&mut self, f: F) -> String
where where
F: Fn(&Vec<SelectOption>) -> &SelectOption, F: Fn(&Vec<SelectOption>) -> &SelectOption,
{ {
@ -71,6 +74,8 @@ impl<'a> GridRowTestBuilder<'a> {
self.inner_builder self.inner_builder
.insert_select_option_cell(&single_select_field.id, option.id.clone()) .insert_select_option_cell(&single_select_field.id, option.id.clone())
.unwrap(); .unwrap();
single_select_field.id.clone()
} }
pub fn insert_multi_select_cell<F>(&mut self, f: F) pub fn insert_multi_select_cell<F>(&mut self, f: F)

View File

@ -1,12 +1,12 @@
use crate::grid::filter_test::script::FilterScript::*; use crate::grid::filter_test::script::FilterScript::*;
use crate::grid::filter_test::script::*; use crate::grid::filter_test::script::*;
use flowy_grid::entities::{CreateGridFilterPayload, TextFilterCondition}; use flowy_grid::entities::{CreateGridFilterPayload, FieldType, TextFilterCondition};
use flowy_grid_data_model::revision::FieldRevision; use flowy_grid_data_model::revision::FieldRevision;
#[tokio::test] #[tokio::test]
async fn grid_filter_create_test() { async fn grid_filter_create_test() {
let mut test = GridFilterTest::new().await; let mut test = GridFilterTest::new().await;
let field_rev = test.text_field(); let field_rev = test.get_field_rev(FieldType::RichText);
let payload = CreateGridFilterPayload::new(field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned())); let payload = CreateGridFilterPayload::new(field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned()));
let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }]; let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }];
test.run_scripts(scripts).await; test.run_scripts(scripts).await;
@ -16,7 +16,7 @@ async fn grid_filter_create_test() {
#[should_panic] #[should_panic]
async fn grid_filter_invalid_condition_panic_test() { async fn grid_filter_invalid_condition_panic_test() {
let mut test = GridFilterTest::new().await; let mut test = GridFilterTest::new().await;
let field_rev = test.text_field().clone(); let field_rev = test.get_field_rev(FieldType::RichText).clone();
// 100 is not a valid condition, so this test should be panic. // 100 is not a valid condition, so this test should be panic.
let payload = CreateGridFilterPayload::new(&field_rev, 100, Some("".to_owned())); let payload = CreateGridFilterPayload::new(&field_rev, 100, Some("".to_owned()));
@ -27,7 +27,7 @@ async fn grid_filter_invalid_condition_panic_test() {
#[tokio::test] #[tokio::test]
async fn grid_filter_delete_test() { async fn grid_filter_delete_test() {
let mut test = GridFilterTest::new().await; let mut test = GridFilterTest::new().await;
let field_rev = test.text_field().clone(); let field_rev = test.get_field_rev(FieldType::RichText).clone();
let payload = create_filter(&field_rev, TextFilterCondition::TextIsEmpty, "abc"); let payload = create_filter(&field_rev, TextFilterCondition::TextIsEmpty, "abc");
let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }]; let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }];
test.run_scripts(scripts).await; test.run_scripts(scripts).await;
@ -36,7 +36,7 @@ async fn grid_filter_delete_test() {
test.run_scripts(vec![ test.run_scripts(vec![
DeleteGridTableFilter { DeleteGridTableFilter {
filter_id: filter.id, filter_id: filter.id,
field_rev, field_rev: field_rev.as_ref().clone(),
}, },
AssertTableFilterCount { count: 0 }, AssertTableFilterCount { count: 0 },
]) ])

View File

@ -64,7 +64,7 @@ impl GridEditorTest {
} }
} }
pub(crate) async fn get_row_revs(&self) -> Vec<Arc<RowRevision>> { pub async fn get_row_revs(&self) -> Vec<Arc<RowRevision>> {
self.editor self.editor
.grid_block_snapshots(None) .grid_block_snapshots(None)
.await .await
@ -79,12 +79,12 @@ impl GridEditorTest {
self.editor.get_grid_filter(&layout_type).await.unwrap() self.editor.get_grid_filter(&layout_type).await.unwrap()
} }
pub fn text_field(&self) -> &FieldRevision { pub fn get_field_rev(&self, field_type: FieldType) -> &Arc<FieldRevision> {
self.field_revs self.field_revs
.iter() .iter()
.filter(|field_rev| { .filter(|field_rev| {
let t_field_type: FieldType = field_rev.field_type_rev.into(); let t_field_type: FieldType = field_rev.field_type_rev.into();
t_field_type == FieldType::RichText t_field_type == field_type
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
.pop() .pop()
@ -129,7 +129,6 @@ fn make_test_grid() -> BuildGridContext {
FieldType::SingleSelect => { FieldType::SingleSelect => {
// Single Select // Single Select
let single_select = SingleSelectTypeOptionBuilder::default() let single_select = SingleSelectTypeOptionBuilder::default()
.option(SelectOption::new("Live"))
.option(SelectOption::new("Completed")) .option(SelectOption::new("Completed"))
.option(SelectOption::new("Planned")) .option(SelectOption::new("Planned"))
.option(SelectOption::new("Paused")); .option(SelectOption::new("Paused"));