mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add group unit test
This commit is contained in:
parent
af23e3e803
commit
0680b20579
@ -1,10 +1,8 @@
|
||||
import 'package:app_flowy/plugins/board/application/card/board_text_cell_bloc.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||
import 'package:flowy_infra/image.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class BoardTextCell extends StatefulWidget {
|
||||
final GridCellControllerBuilder cellControllerBuilder;
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub use crate::entities::view::ViewDataTypePB;
|
||||
use crate::entities::{ViewInfoPB, ViewLayoutTypePB};
|
||||
use crate::entities::ViewInfoPB;
|
||||
use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
|
||||
use crate::{
|
||||
dart_notification::{send_dart_notification, FolderNotification},
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::script::{invalid_workspace_name_test_case, FolderScript::*, FolderTest};
|
||||
use flowy_folder::entities::view::ViewDataTypePB;
|
||||
use flowy_folder::entities::workspace::CreateWorkspacePayloadPB;
|
||||
use flowy_folder::entities::ViewLayoutTypePB;
|
||||
|
||||
use flowy_revision::disk::RevisionState;
|
||||
use flowy_test::{event_builder::*, FlowySDKTest};
|
||||
@ -135,11 +136,13 @@ async fn app_create_with_view() {
|
||||
name: "View A".to_owned(),
|
||||
desc: "View A description".to_owned(),
|
||||
data_type: ViewDataTypePB::Text,
|
||||
layout: ViewLayoutTypePB::Document,
|
||||
},
|
||||
CreateView {
|
||||
name: "Grid".to_owned(),
|
||||
desc: "Grid description".to_owned(),
|
||||
data_type: ViewDataTypePB::Database,
|
||||
layout: ViewLayoutTypePB::Document,
|
||||
},
|
||||
ReadApp(app.id),
|
||||
])
|
||||
@ -199,11 +202,13 @@ async fn view_delete_all() {
|
||||
name: "View A".to_owned(),
|
||||
desc: "View A description".to_owned(),
|
||||
data_type: ViewDataTypePB::Text,
|
||||
layout: ViewLayoutTypePB::Document,
|
||||
},
|
||||
CreateView {
|
||||
name: "Grid".to_owned(),
|
||||
desc: "Grid description".to_owned(),
|
||||
data_type: ViewDataTypePB::Database,
|
||||
layout: ViewLayoutTypePB::Document,
|
||||
},
|
||||
ReadApp(app.id.clone()),
|
||||
])
|
||||
@ -232,6 +237,7 @@ async fn view_delete_all_permanent() {
|
||||
name: "View A".to_owned(),
|
||||
desc: "View A description".to_owned(),
|
||||
data_type: ViewDataTypePB::Text,
|
||||
layout: ViewLayoutTypePB::Document,
|
||||
},
|
||||
ReadApp(app.id.clone()),
|
||||
])
|
||||
@ -331,6 +337,7 @@ async fn folder_sync_revision_with_new_view() {
|
||||
name: view_name.clone(),
|
||||
desc: view_desc.clone(),
|
||||
data_type: ViewDataTypePB::Text,
|
||||
layout: ViewLayoutTypePB::Document,
|
||||
},
|
||||
AssertCurrentRevId(3),
|
||||
AssertNextSyncRevId(Some(3)),
|
||||
|
@ -28,7 +28,20 @@ impl std::convert::From<&GroupConfigurationRevision> for GridGroupConfigurationP
|
||||
#[derive(ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct RepeatedGridGroupPB {
|
||||
#[pb(index = 1)]
|
||||
pub(crate) items: Vec<GroupPB>,
|
||||
pub items: Vec<GroupPB>,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for RepeatedGridGroupPB {
|
||||
type Target = Vec<GroupPB>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.items
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for RepeatedGridGroupPB {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.items
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Debug, Default, Clone)]
|
||||
|
@ -9,9 +9,7 @@ use crate::services::field::{default_type_option_builder_from_type, type_option_
|
||||
use crate::services::filter::GridFilterService;
|
||||
use crate::services::grid_view_manager::GridViewManager;
|
||||
use crate::services::persistence::block_index::BlockIndexCache;
|
||||
use crate::services::row::{
|
||||
make_grid_blocks, make_row_from_row_rev, make_rows_from_row_revs, GridBlockSnapshot, RowRevisionBuilder,
|
||||
};
|
||||
use crate::services::row::{make_grid_blocks, make_rows_from_row_revs, GridBlockSnapshot, RowRevisionBuilder};
|
||||
use bytes::Bytes;
|
||||
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::revision::*;
|
||||
|
@ -13,6 +13,7 @@ use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad};
|
||||
use flowy_sync::entities::grid::GridSettingChangesetParams;
|
||||
use flowy_sync::entities::revision::Revision;
|
||||
use lib_infra::future::{wrap_future, AFFuture, FutureResult};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
@ -26,6 +27,7 @@ pub struct GridViewRevisionEditor {
|
||||
row_delegate: Arc<dyn GridViewRowDelegate>,
|
||||
group_service: Arc<RwLock<GroupService>>,
|
||||
scheduler: Arc<dyn GridServiceTaskScheduler>,
|
||||
did_load_group: AtomicBool,
|
||||
}
|
||||
|
||||
impl GridViewRevisionEditor {
|
||||
@ -46,6 +48,7 @@ impl GridViewRevisionEditor {
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let group_service = GroupService::new(Box::new(pad.clone())).await;
|
||||
let user_id = user_id.to_owned();
|
||||
let did_load_group = AtomicBool::new(false);
|
||||
Ok(Self {
|
||||
pad,
|
||||
user_id,
|
||||
@ -55,6 +58,7 @@ impl GridViewRevisionEditor {
|
||||
field_delegate,
|
||||
row_delegate,
|
||||
group_service: Arc::new(RwLock::new(group_service)),
|
||||
did_load_group,
|
||||
})
|
||||
}
|
||||
|
||||
@ -140,19 +144,25 @@ impl GridViewRevisionEditor {
|
||||
}
|
||||
|
||||
pub(crate) async fn load_groups(&self) -> FlowyResult<Vec<GroupPB>> {
|
||||
let field_revs = self.field_delegate.get_field_revs().await;
|
||||
let row_revs = self.row_delegate.gv_row_revs().await;
|
||||
let groups = if !self.did_load_group.load(Ordering::SeqCst) {
|
||||
self.did_load_group.store(true, Ordering::SeqCst);
|
||||
let field_revs = self.field_delegate.get_field_revs().await;
|
||||
let row_revs = self.row_delegate.gv_row_revs().await;
|
||||
match self
|
||||
.group_service
|
||||
.write()
|
||||
.await
|
||||
.load_groups(&field_revs, row_revs)
|
||||
.await
|
||||
{
|
||||
None => vec![],
|
||||
Some(groups) => groups,
|
||||
}
|
||||
} else {
|
||||
self.group_service.read().await.groups().await
|
||||
};
|
||||
|
||||
match self
|
||||
.group_service
|
||||
.write()
|
||||
.await
|
||||
.load_groups(&field_revs, row_revs)
|
||||
.await
|
||||
{
|
||||
None => Ok(vec![]),
|
||||
Some(groups) => Ok(groups.into_iter().map(GroupPB::from).collect()),
|
||||
}
|
||||
Ok(groups.into_iter().map(GroupPB::from).collect())
|
||||
}
|
||||
|
||||
pub(crate) async fn get_setting(&self) -> GridSettingPB {
|
||||
|
@ -37,9 +37,9 @@ impl Groupable for CheckboxGroupController {
|
||||
|
||||
fn move_row_if_match(
|
||||
&mut self,
|
||||
field_rev: &FieldRevision,
|
||||
_field_rev: &FieldRevision,
|
||||
_row_rev: &RowRevision,
|
||||
row_changeset: &mut RowChangeset,
|
||||
_row_changeset: &mut RowChangeset,
|
||||
_cell_data: &Self::CellDataType,
|
||||
_to_row_id: &str,
|
||||
) -> Vec<GroupRowsChangesetPB> {
|
||||
|
@ -47,7 +47,7 @@ pub trait GroupController: GroupControllerSharedAction + Send + Sync {
|
||||
pub trait GroupControllerSharedAction: Send + Sync {
|
||||
// The field that is used for grouping the rows
|
||||
fn field_id(&self) -> &str;
|
||||
fn build_groups(&self) -> Vec<Group>;
|
||||
fn groups(&self) -> Vec<Group>;
|
||||
fn group_rows(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()>;
|
||||
fn did_update_row(
|
||||
&mut self,
|
||||
@ -194,7 +194,7 @@ where
|
||||
&self.field_id
|
||||
}
|
||||
|
||||
fn build_groups(&self) -> Vec<Group> {
|
||||
fn groups(&self) -> Vec<Group> {
|
||||
let default_group = self.default_group.clone();
|
||||
let mut groups: Vec<Group> = self.groups_map.values().cloned().collect();
|
||||
if !default_group.rows.is_empty() {
|
||||
|
@ -249,11 +249,9 @@ fn move_row(
|
||||
) {
|
||||
cell_data.select_options.iter().for_each(|option| {
|
||||
// Remove the row in which group contains the row
|
||||
if option.id == group.id {
|
||||
if group.contains_row(&row_rev.id) {
|
||||
group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
|
||||
group.remove_row(&row_rev.id);
|
||||
}
|
||||
if option.id == group.id && group.contains_row(&row_rev.id) {
|
||||
group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
|
||||
group.remove_row(&row_rev.id);
|
||||
}
|
||||
|
||||
// Find the inserted group
|
||||
|
@ -7,7 +7,9 @@ use crate::services::group::{
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid_data_model::revision::{gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowRevision, RowChangeset};
|
||||
use flowy_grid_data_model::revision::{
|
||||
gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowChangeset, RowRevision,
|
||||
};
|
||||
use lib_infra::future::AFFuture;
|
||||
use std::future::Future;
|
||||
use std::sync::Arc;
|
||||
@ -18,7 +20,6 @@ pub trait GroupConfigurationDelegate: Send + Sync + 'static {
|
||||
}
|
||||
|
||||
pub(crate) struct GroupService {
|
||||
pub groups: Vec<Group>,
|
||||
delegate: Box<dyn GroupConfigurationDelegate>,
|
||||
group_controller: Option<Arc<RwLock<dyn GroupController>>>,
|
||||
}
|
||||
@ -26,12 +27,19 @@ pub(crate) struct GroupService {
|
||||
impl GroupService {
|
||||
pub(crate) async fn new(delegate: Box<dyn GroupConfigurationDelegate>) -> Self {
|
||||
Self {
|
||||
groups: vec![],
|
||||
delegate,
|
||||
group_controller: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn groups(&self) -> Vec<Group> {
|
||||
if let Some(group_action_handler) = self.group_controller.as_ref() {
|
||||
group_action_handler.read().await.groups()
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn load_groups(
|
||||
&mut self,
|
||||
field_revs: &[Arc<FieldRevision>],
|
||||
@ -44,10 +52,7 @@ impl GroupService {
|
||||
.build_groups(&field_type, &field_rev, row_revs, configuration)
|
||||
.await
|
||||
{
|
||||
Ok(groups) => {
|
||||
self.groups = groups.clone();
|
||||
Some(groups)
|
||||
}
|
||||
Ok(groups) => Some(groups),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
@ -183,7 +188,7 @@ impl GroupService {
|
||||
if let Some(group_action_handler) = self.group_controller.as_ref() {
|
||||
let mut write_guard = group_action_handler.write().await;
|
||||
let _ = write_guard.group_rows(&row_revs, field_rev)?;
|
||||
groups = write_guard.build_groups();
|
||||
groups = write_guard.groups();
|
||||
drop(write_guard);
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ pub struct GridRowTest {
|
||||
|
||||
impl GridRowTest {
|
||||
pub async fn new() -> Self {
|
||||
let editor_test = GridEditorTest::new().await;
|
||||
let editor_test = GridEditorTest::new_table().await;
|
||||
Self { inner: editor_test }
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ pub struct GridCellTest {
|
||||
|
||||
impl GridCellTest {
|
||||
pub async fn new() -> Self {
|
||||
let inner = GridEditorTest::new().await;
|
||||
let inner = GridEditorTest::new_table().await;
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ pub struct GridFieldTest {
|
||||
|
||||
impl GridFieldTest {
|
||||
pub async fn new() -> Self {
|
||||
let editor_test = GridEditorTest::new().await;
|
||||
let editor_test = GridEditorTest::new_table().await;
|
||||
Self { inner: editor_test }
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ pub struct GridFilterTest {
|
||||
|
||||
impl GridFilterTest {
|
||||
pub async fn new() -> Self {
|
||||
let editor_test = GridEditorTest::new().await;
|
||||
let editor_test = GridEditorTest::new_table().await;
|
||||
Self {
|
||||
inner: editor_test
|
||||
}
|
||||
|
@ -36,12 +36,25 @@ pub struct GridEditorTest {
|
||||
}
|
||||
|
||||
impl GridEditorTest {
|
||||
pub async fn new() -> Self {
|
||||
pub async fn new_table() -> Self {
|
||||
Self::new(GridLayout::Table).await
|
||||
}
|
||||
|
||||
pub async fn new_board() -> Self {
|
||||
Self::new(GridLayout::Board).await
|
||||
}
|
||||
|
||||
pub async fn new(layout: GridLayout) -> Self {
|
||||
let sdk = FlowySDKTest::default();
|
||||
let _ = sdk.init_user().await;
|
||||
let build_context = make_test_grid();
|
||||
let view_data: Bytes = build_context.into();
|
||||
let test = ViewTest::new_grid_view(&sdk, view_data.to_vec()).await;
|
||||
|
||||
let test = match layout {
|
||||
GridLayout::Table => ViewTest::new_grid_view(&sdk, view_data.to_vec()).await,
|
||||
GridLayout::Board => ViewTest::new_board_view(&sdk, view_data.to_vec()).await,
|
||||
};
|
||||
|
||||
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();
|
||||
|
@ -1 +1,2 @@
|
||||
mod script;
|
||||
mod test;
|
||||
|
@ -1,9 +1,23 @@
|
||||
use crate::grid::grid_editor::GridEditorTest;
|
||||
use flowy_grid::entities::MoveRowParams;
|
||||
use flowy_grid::entities::{GroupPB, MoveRowParams, RowPB};
|
||||
|
||||
pub enum GroupScript {
|
||||
MoveCard { from_row_id: String, to_row_id: String },
|
||||
AssertGroup {
|
||||
group_index: usize,
|
||||
row_count: usize,
|
||||
},
|
||||
AssertGroupCount(usize),
|
||||
AssertGroupRow {
|
||||
group_index: usize,
|
||||
row_index: usize,
|
||||
row: RowPB,
|
||||
},
|
||||
MoveRow {
|
||||
from_group_index: usize,
|
||||
from_row_index: usize,
|
||||
to_group_index: usize,
|
||||
to_row_index: usize,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct GridGroupTest {
|
||||
@ -12,7 +26,7 @@ pub struct GridGroupTest {
|
||||
|
||||
impl GridGroupTest {
|
||||
pub async fn new() -> Self {
|
||||
let editor_test = GridEditorTest::new().await;
|
||||
let editor_test = GridEditorTest::new_board().await;
|
||||
Self { inner: editor_test }
|
||||
}
|
||||
|
||||
@ -24,19 +38,48 @@ impl GridGroupTest {
|
||||
|
||||
pub async fn run_script(&mut self, script: GroupScript) {
|
||||
match script {
|
||||
GroupScript::MoveCard { from_row_id, to_row_id } => {
|
||||
let params = MoveRowParams {
|
||||
view_id: self.inner.grid_id.clone(),
|
||||
from_row_id,
|
||||
to_row_id,
|
||||
};
|
||||
let _ = self.editor.move_row(params).await.unwrap();
|
||||
GroupScript::AssertGroup { group_index, row_count } => {
|
||||
assert_eq!(row_count, self.group_at_index(group_index).await.rows.len());
|
||||
}
|
||||
GroupScript::AssertGroupCount(count) => {
|
||||
let groups = self.editor.load_groups().await.unwrap();
|
||||
assert_eq!(count, groups.len());
|
||||
}
|
||||
GroupScript::MoveRow {
|
||||
from_group_index,
|
||||
from_row_index,
|
||||
to_group_index,
|
||||
to_row_index,
|
||||
} => {
|
||||
let groups: Vec<GroupPB> = self.editor.load_groups().await.unwrap().items;
|
||||
let from_row = groups.get(from_group_index).unwrap().rows.get(from_row_index).unwrap();
|
||||
let to_row = groups.get(to_group_index).unwrap().rows.get(to_row_index).unwrap();
|
||||
let params = MoveRowParams {
|
||||
view_id: self.inner.grid_id.clone(),
|
||||
from_row_id: from_row.id.clone(),
|
||||
to_row_id: to_row.id.clone(),
|
||||
};
|
||||
|
||||
self.editor.move_row(params).await.unwrap();
|
||||
}
|
||||
GroupScript::AssertGroupRow {
|
||||
group_index,
|
||||
row_index,
|
||||
row,
|
||||
} => {
|
||||
//
|
||||
let group = self.group_at_index(group_index).await;
|
||||
let compare_row = group.rows.get(row_index).unwrap().clone();
|
||||
|
||||
assert_eq!(row.id, compare_row.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn group_at_index(&self, index: usize) -> GroupPB {
|
||||
let groups = self.editor.load_groups().await.unwrap().items;
|
||||
groups.get(index).unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for GridGroupTest {
|
||||
|
51
frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs
Normal file
51
frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use crate::grid::group_test::script::GridGroupTest;
|
||||
use crate::grid::group_test::script::GroupScript::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn board_init_test() {
|
||||
let mut test = GridGroupTest::new().await;
|
||||
let scripts = vec![
|
||||
AssertGroupCount(3),
|
||||
AssertGroup {
|
||||
group_index: 0,
|
||||
row_count: 2,
|
||||
},
|
||||
AssertGroup {
|
||||
group_index: 1,
|
||||
row_count: 2,
|
||||
},
|
||||
AssertGroup {
|
||||
group_index: 2,
|
||||
row_count: 1,
|
||||
},
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn board_move_row_test() {
|
||||
let mut test = GridGroupTest::new().await;
|
||||
let group = test.group_at_index(0).await;
|
||||
let scripts = vec![
|
||||
MoveRow {
|
||||
from_group_index: 0,
|
||||
from_row_index: 0,
|
||||
to_group_index: 1,
|
||||
to_row_index: 1,
|
||||
},
|
||||
AssertGroup {
|
||||
group_index: 0,
|
||||
row_count: 1,
|
||||
},
|
||||
AssertGroup {
|
||||
group_index: 1,
|
||||
row_count: 3,
|
||||
},
|
||||
AssertGroupRow {
|
||||
group_index: 1,
|
||||
row_index: 1,
|
||||
row: group.rows.get(0).unwrap().clone(),
|
||||
},
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
@ -184,7 +184,7 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
|
||||
&self,
|
||||
user_id: &str,
|
||||
view_id: &str,
|
||||
sub_data_type: ViewLayoutTypePB,
|
||||
_sub_data_type: ViewLayoutTypePB,
|
||||
) -> FutureResult<Bytes, FlowyError> {
|
||||
let user_id = user_id.to_string();
|
||||
let view_id = view_id.to_string();
|
||||
|
@ -275,7 +275,7 @@ impl std::default::Default for GridBlockRevisionPad {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::client_grid::GridBlockRevisionPad;
|
||||
use flowy_grid_data_model::revision::{RowMetaChangeset, RowRevision};
|
||||
use flowy_grid_data_model::revision::{RowChangeset, RowRevision};
|
||||
use lib_ot::core::TextDelta;
|
||||
use std::borrow::Cow;
|
||||
|
||||
@ -400,7 +400,7 @@ mod tests {
|
||||
visibility: false,
|
||||
};
|
||||
|
||||
let changeset = RowMetaChangeset {
|
||||
let changeset = RowChangeset {
|
||||
row_id: row.id.clone(),
|
||||
height: Some(100),
|
||||
visibility: Some(true),
|
||||
|
Loading…
Reference in New Issue
Block a user