mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: config grid filter in backend & add tests
* chore: add search crate * chore: add task order test * chore: enable timeout * add task crate * chore: run filter task * chore: run filter task * chore: filter rows * chore: cache filter result * chore: filter rows when open a grid * chore: add tests * test: add number filter test * test: add checkbox fitler test * chore: fix test Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
@ -0,0 +1,27 @@
|
||||
use crate::grid::filter_test::script::FilterScript::*;
|
||||
use crate::grid::filter_test::script::GridFilterTest;
|
||||
use flowy_grid::entities::CheckboxFilterCondition;
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_filter_checkbox_is_check_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateCheckboxFilter {
|
||||
condition: CheckboxFilterCondition::IsChecked,
|
||||
},
|
||||
AssertNumberOfRows { expected: 2 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_filter_checkbox_is_uncheck_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateCheckboxFilter {
|
||||
condition: CheckboxFilterCondition::IsUnChecked,
|
||||
},
|
||||
AssertNumberOfRows { expected: 3 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
use crate::grid::filter_test::script::FilterScript::*;
|
||||
use crate::grid::filter_test::script::GridFilterTest;
|
||||
use flowy_grid::entities::DateFilterCondition;
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic]
|
||||
async fn grid_filter_date_is_check_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateDateFilter {
|
||||
condition: DateFilterCondition::DateIs,
|
||||
content: "1647251762".to_string(),
|
||||
},
|
||||
AssertNumberOfRows { expected: 2 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
@ -1,2 +1,5 @@
|
||||
mod checkbox_filter_test;
|
||||
mod date_filter_test;
|
||||
mod number_filter_test;
|
||||
mod script;
|
||||
mod text_filter_test;
|
||||
|
@ -0,0 +1,82 @@
|
||||
use crate::grid::filter_test::script::FilterScript::*;
|
||||
use crate::grid::filter_test::script::GridFilterTest;
|
||||
use flowy_grid::entities::NumberFilterCondition;
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_filter_number_is_equal_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateNumberFilter {
|
||||
condition: NumberFilterCondition::Equal,
|
||||
content: "1".to_string(),
|
||||
},
|
||||
AssertNumberOfRows { expected: 1 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_filter_number_is_less_than_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateNumberFilter {
|
||||
condition: NumberFilterCondition::LessThan,
|
||||
content: "3".to_string(),
|
||||
},
|
||||
AssertNumberOfRows { expected: 2 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic]
|
||||
async fn grid_filter_number_is_less_than_test2() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateNumberFilter {
|
||||
condition: NumberFilterCondition::LessThan,
|
||||
content: "$3".to_string(),
|
||||
},
|
||||
AssertNumberOfRows { expected: 2 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_filter_number_is_less_than_or_equal_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateNumberFilter {
|
||||
condition: NumberFilterCondition::LessThanOrEqualTo,
|
||||
content: "3".to_string(),
|
||||
},
|
||||
AssertNumberOfRows { expected: 3 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_filter_number_is_empty_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateNumberFilter {
|
||||
condition: NumberFilterCondition::NumberIsEmpty,
|
||||
content: "".to_string(),
|
||||
},
|
||||
AssertNumberOfRows { expected: 1 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_filter_number_is_not_empty_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateNumberFilter {
|
||||
condition: NumberFilterCondition::NumberIsNotEmpty,
|
||||
content: "".to_string(),
|
||||
},
|
||||
AssertNumberOfRows { expected: 4 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
@ -3,21 +3,46 @@
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use flowy_grid::entities::{InsertFilterParams, InsertFilterPayloadPB, DeleteFilterParams, GridLayout, GridSettingChangesetParams, GridSettingPB};
|
||||
use futures::TryFutureExt;
|
||||
use flowy_grid::entities::{CreateFilterParams, CreateFilterPayloadPB, DeleteFilterParams, GridLayout, GridSettingChangesetParams, GridSettingPB, RowPB, TextFilterCondition, FieldType, NumberFilterCondition, CheckboxFilterCondition, DateFilterCondition};
|
||||
use flowy_grid::services::setting::GridSettingChangesetBuilder;
|
||||
use grid_rev_model::{FieldRevision, FieldTypeRevision};
|
||||
use flowy_grid::services::filter::FilterType;
|
||||
use crate::grid::grid_editor::GridEditorTest;
|
||||
|
||||
pub enum FilterScript {
|
||||
InsertGridTableFilter {
|
||||
payload: InsertFilterPayloadPB,
|
||||
InsertFilter {
|
||||
payload: CreateFilterPayloadPB,
|
||||
},
|
||||
AssertTableFilterCount {
|
||||
CreateTextFilter {
|
||||
condition: TextFilterCondition,
|
||||
content: String,
|
||||
},
|
||||
CreateNumberFilter {
|
||||
condition: NumberFilterCondition,
|
||||
content: String,
|
||||
},
|
||||
CreateCheckboxFilter {
|
||||
condition: CheckboxFilterCondition,
|
||||
},
|
||||
CreateDateFilter{
|
||||
condition: DateFilterCondition,
|
||||
content: String,
|
||||
},
|
||||
AssertFilterCount {
|
||||
count: i32,
|
||||
},
|
||||
DeleteGridTableFilter {
|
||||
DeleteFilter {
|
||||
filter_id: String,
|
||||
field_rev: FieldRevision,
|
||||
filter_type: FilterType,
|
||||
},
|
||||
AssertFilterContent {
|
||||
filter_type: FilterType,
|
||||
condition: u32,
|
||||
content: String
|
||||
},
|
||||
AssertNumberOfRows{
|
||||
expected: usize,
|
||||
},
|
||||
#[allow(dead_code)]
|
||||
AssertGridSetting {
|
||||
@ -45,25 +70,65 @@ impl GridFilterTest {
|
||||
|
||||
pub async fn run_script(&mut self, script: FilterScript) {
|
||||
match script {
|
||||
|
||||
FilterScript::InsertGridTableFilter { payload } => {
|
||||
let params: InsertFilterParams = payload.try_into().unwrap();
|
||||
let _ = self.editor.create_filter(params).await.unwrap();
|
||||
FilterScript::InsertFilter { payload } => {
|
||||
self.insert_filter(payload).await;
|
||||
}
|
||||
FilterScript::AssertTableFilterCount { count } => {
|
||||
let filters = self.editor.get_grid_filter().await.unwrap();
|
||||
FilterScript::CreateTextFilter { condition, content} => {
|
||||
let field_rev = self.get_field_rev(FieldType::RichText);
|
||||
let payload =
|
||||
CreateFilterPayloadPB::new(field_rev, condition, content);
|
||||
self.insert_filter(payload).await;
|
||||
}
|
||||
FilterScript::CreateNumberFilter {condition, content} => {
|
||||
let field_rev = self.get_field_rev(FieldType::Number);
|
||||
let payload =
|
||||
CreateFilterPayloadPB::new(field_rev, condition, content);
|
||||
self.insert_filter(payload).await;
|
||||
}
|
||||
FilterScript::CreateCheckboxFilter {condition} => {
|
||||
let field_rev = self.get_field_rev(FieldType::Checkbox);
|
||||
let payload =
|
||||
CreateFilterPayloadPB::new(field_rev, condition, "".to_string());
|
||||
self.insert_filter(payload).await;
|
||||
}
|
||||
FilterScript::CreateDateFilter { condition, content} => {
|
||||
let field_rev = self.get_field_rev(FieldType::DateTime);
|
||||
let payload =
|
||||
CreateFilterPayloadPB::new(field_rev, condition, content);
|
||||
self.insert_filter(payload).await;
|
||||
}
|
||||
FilterScript::AssertFilterCount { count } => {
|
||||
let filters = self.editor.get_all_filters().await.unwrap();
|
||||
assert_eq!(count as usize, filters.len());
|
||||
}
|
||||
FilterScript::DeleteGridTableFilter { filter_id, field_rev} => {
|
||||
let params = DeleteFilterParams { field_id: field_rev.id, filter_id, field_type_rev: field_rev.ty };
|
||||
FilterScript::AssertFilterContent { filter_type: filter_id, condition, content} => {
|
||||
let filter = self.editor.get_filters(filter_id).await.unwrap().pop().unwrap();
|
||||
assert_eq!(&filter.content, &content);
|
||||
assert_eq!(filter.condition as u32, condition);
|
||||
|
||||
}
|
||||
FilterScript::DeleteFilter { filter_id, filter_type } => {
|
||||
let params = DeleteFilterParams { filter_type, filter_id };
|
||||
let _ = self.editor.delete_filter(params).await.unwrap();
|
||||
}
|
||||
FilterScript::AssertGridSetting { expected_setting } => {
|
||||
let setting = self.editor.get_grid_setting().await.unwrap();
|
||||
let setting = self.editor.get_setting().await.unwrap();
|
||||
assert_eq!(expected_setting, setting);
|
||||
}
|
||||
FilterScript::AssertNumberOfRows { expected } => {
|
||||
//
|
||||
let grid = self.editor.get_grid().await.unwrap();
|
||||
let rows = grid.blocks.into_iter().map(|block| block.rows).flatten().collect::<Vec<RowPB>>();
|
||||
assert_eq!(rows.len(), expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn insert_filter(&self, payload: CreateFilterPayloadPB) {
|
||||
|
||||
let params: CreateFilterParams = payload.try_into().unwrap();
|
||||
let _ = self.editor.create_filter(params).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,26 +1,71 @@
|
||||
use crate::grid::filter_test::script::FilterScript::*;
|
||||
use crate::grid::filter_test::script::*;
|
||||
use flowy_grid::entities::{FieldType, InsertFilterPayloadPB, TextFilterCondition};
|
||||
use grid_rev_model::FieldRevision;
|
||||
use flowy_grid::entities::{CreateFilterPayloadPB, FieldType, TextFilterCondition};
|
||||
use flowy_grid::services::filter::FilterType;
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_filter_create_test() {
|
||||
async fn grid_filter_text_is_empty_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let field_rev = test.get_field_rev(FieldType::RichText);
|
||||
let payload = InsertFilterPayloadPB::new(field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned()));
|
||||
let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }];
|
||||
let scripts = vec![
|
||||
CreateTextFilter {
|
||||
condition: TextFilterCondition::TextIsEmpty,
|
||||
content: "".to_string(),
|
||||
},
|
||||
AssertFilterCount { count: 1 },
|
||||
AssertNumberOfRows { expected: 0 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic]
|
||||
async fn grid_filter_invalid_condition_panic_test() {
|
||||
async fn grid_filter_is_text_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let field_rev = test.get_field_rev(FieldType::RichText).clone();
|
||||
let scripts = vec![
|
||||
CreateTextFilter {
|
||||
condition: TextFilterCondition::Is,
|
||||
content: "A".to_string(),
|
||||
},
|
||||
AssertNumberOfRows { expected: 1 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
// 100 is not a valid condition, so this test should be panic.
|
||||
let payload = InsertFilterPayloadPB::new(&field_rev, 100, Some("".to_owned()));
|
||||
let scripts = vec![InsertGridTableFilter { payload }];
|
||||
#[tokio::test]
|
||||
async fn grid_filter_contain_text_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateTextFilter {
|
||||
condition: TextFilterCondition::Contains,
|
||||
content: "A".to_string(),
|
||||
},
|
||||
AssertNumberOfRows { expected: 3 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_filter_start_with_text_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateTextFilter {
|
||||
condition: TextFilterCondition::StartsWith,
|
||||
content: "A".to_string(),
|
||||
},
|
||||
AssertNumberOfRows { expected: 2 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_filter_ends_with_text_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateTextFilter {
|
||||
condition: TextFilterCondition::EndsWith,
|
||||
content: "A".to_string(),
|
||||
},
|
||||
AssertNumberOfRows { expected: 2 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
@ -28,24 +73,22 @@ async fn grid_filter_invalid_condition_panic_test() {
|
||||
async fn grid_filter_delete_test() {
|
||||
let mut test = GridFilterTest::new().await;
|
||||
let field_rev = test.get_field_rev(FieldType::RichText).clone();
|
||||
let payload = create_filter(&field_rev, TextFilterCondition::TextIsEmpty, "abc");
|
||||
let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }];
|
||||
let payload = CreateFilterPayloadPB::new(&field_rev, TextFilterCondition::TextIsEmpty, "".to_string());
|
||||
let scripts = vec![
|
||||
InsertFilter { payload },
|
||||
AssertFilterCount { count: 1 },
|
||||
AssertNumberOfRows { expected: 0 },
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
|
||||
let filter = test.grid_filters().await.pop().unwrap();
|
||||
test.run_scripts(vec![
|
||||
DeleteGridTableFilter {
|
||||
DeleteFilter {
|
||||
filter_id: filter.id,
|
||||
field_rev: field_rev.as_ref().clone(),
|
||||
filter_type: FilterType::from(&field_rev),
|
||||
},
|
||||
AssertTableFilterCount { count: 0 },
|
||||
AssertFilterCount { count: 0 },
|
||||
AssertNumberOfRows { expected: 5 },
|
||||
])
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_filter_get_rows_test() {}
|
||||
|
||||
fn create_filter(field_rev: &FieldRevision, condition: TextFilterCondition, s: &str) -> InsertFilterPayloadPB {
|
||||
InsertFilterPayloadPB::new(field_rev, condition, Some(s.to_owned()))
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#![allow(unused_imports)]
|
||||
use crate::grid::block_test::util::GridRowTestBuilder;
|
||||
use bytes::Bytes;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid::entities::*;
|
||||
use flowy_grid::services::field::SelectOptionPB;
|
||||
use flowy_grid::services::field::*;
|
||||
@ -55,7 +56,7 @@ impl GridEditorTest {
|
||||
let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap();
|
||||
let field_revs = editor.get_field_revs(None).await.unwrap();
|
||||
let block_meta_revs = editor.get_block_meta_revs().await.unwrap();
|
||||
let row_revs = editor.grid_block_snapshots(None).await.unwrap().pop().unwrap().row_revs;
|
||||
let row_revs = editor.get_blocks(None).await.unwrap().pop().unwrap().row_revs;
|
||||
assert_eq!(block_meta_revs.len(), 1);
|
||||
|
||||
// It seems like you should add the field in the make_test_grid() function.
|
||||
@ -76,17 +77,11 @@ impl GridEditorTest {
|
||||
}
|
||||
|
||||
pub async fn get_row_revs(&self) -> Vec<Arc<RowRevision>> {
|
||||
self.editor
|
||||
.grid_block_snapshots(None)
|
||||
.await
|
||||
.unwrap()
|
||||
.pop()
|
||||
.unwrap()
|
||||
.row_revs
|
||||
self.editor.get_blocks(None).await.unwrap().pop().unwrap().row_revs
|
||||
}
|
||||
|
||||
pub async fn grid_filters(&self) -> Vec<GridFilterConfigurationPB> {
|
||||
self.editor.get_grid_filter().await.unwrap()
|
||||
pub async fn grid_filters(&self) -> Vec<FilterPB> {
|
||||
self.editor.get_all_filters().await.unwrap()
|
||||
}
|
||||
|
||||
pub fn get_field_rev(&self, field_type: FieldType) -> &Arc<FieldRevision> {
|
||||
@ -239,7 +234,7 @@ fn make_test_grid() -> BuildGridContext {
|
||||
3 => {
|
||||
for field_type in FieldType::iter() {
|
||||
match field_type {
|
||||
FieldType::RichText => row_builder.insert_text_cell("D"),
|
||||
FieldType::RichText => row_builder.insert_text_cell("DA"),
|
||||
FieldType::Number => row_builder.insert_number_cell("4"),
|
||||
FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
|
||||
FieldType::SingleSelect => {
|
||||
@ -253,8 +248,8 @@ fn make_test_grid() -> BuildGridContext {
|
||||
4 => {
|
||||
for field_type in FieldType::iter() {
|
||||
match field_type {
|
||||
FieldType::RichText => row_builder.insert_text_cell("E"),
|
||||
FieldType::Number => row_builder.insert_number_cell("5"),
|
||||
FieldType::RichText => row_builder.insert_text_cell("AE"),
|
||||
FieldType::Number => row_builder.insert_number_cell(""),
|
||||
FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
|
||||
FieldType::SingleSelect => {
|
||||
row_builder.insert_single_select_cell(|mut options| options.remove(2))
|
||||
|
Reference in New Issue
Block a user