test: add database event tests (#2744)

* chore: add tests

* test: add tests

* test: add tests
This commit is contained in:
Nathan.fooo 2023-06-09 18:57:29 +08:00 committed by GitHub
parent 0f9f5251f2
commit e9be37a961
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 834 additions and 104 deletions

View File

@ -47,7 +47,7 @@ class DateCellDataPersistence implements CellDataPersistence<DateCellData> {
@override
Future<Option<FlowyError>> save(DateCellData data) {
final payload = DateChangesetPB.create()
..cellPath = _makeCellPath(cellContext);
..cellId = _makeCellPath(cellContext);
if (data.dateTime != null) {
final date = (data.dateTime!.millisecondsSinceEpoch ~/ 1000).toString();
payload.date = date;

View File

@ -1,5 +1,4 @@
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/group.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:dartz/dartz.dart';
@ -10,12 +9,10 @@ class GroupBackendService {
Future<Either<Unit, FlowyError>> groupByField({
required String fieldId,
required FieldType fieldType,
}) {
final payload = GroupByFieldPayloadPB.create()
..viewId = viewId
..fieldId = fieldId
..fieldType = fieldType;
..fieldId = fieldId;
return DatabaseEventSetGroupByField(payload).send();
}

View File

@ -32,7 +32,6 @@ class DatabaseGroupBloc extends Bloc<DatabaseGroupEvent, DatabaseGroupState> {
setGroupByField: (String fieldId, FieldType fieldType) async {
final result = await _groupBackendSvc.groupByField(
fieldId: fieldId,
fieldType: fieldType,
);
result.fold((l) => null, (err) => Log.error(err));
},

View File

@ -230,7 +230,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
for (final group in updatedGroups) {
final columnController =
boardController.getGroupController(group.groupId);
columnController?.updateGroupName(group.desc);
columnController?.updateGroupName(group.groupName);
}
},
);
@ -285,7 +285,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
AppFlowyGroupData initializeGroupData(GroupPB group) {
return AppFlowyGroupData(
id: group.groupId,
name: group.desc,
name: group.groupName,
items: _buildGroupItems(group),
customData: GroupData(
group: group,

View File

@ -285,10 +285,10 @@ packages:
dependency: transitive
description:
name: csslib
sha256: "831883fb353c8bdc1d71979e5b342c7d88acfbc643113c14ae51e2442ea0f20f"
sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb"
url: "https://pub.dev"
source: hosted
version: "0.17.3"
version: "1.0.0"
dart_style:
dependency: transitive
description:
@ -648,10 +648,10 @@ packages:
dependency: transitive
description:
name: html
sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8"
sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
url: "https://pub.dev"
source: hosted
version: "0.15.3"
version: "0.15.4"
http:
dependency: "direct main"
description:

View File

@ -48,8 +48,9 @@ void main() {
);
final expectedGroupName = "No ${multiSelectField.name}";
assert(
boardBloc.groupControllers.values.first.group.desc == expectedGroupName,
"Expected $expectedGroupName, but receive ${boardBloc.groupControllers.values.first.group.desc}",
boardBloc.groupControllers.values.first.group.groupName ==
expectedGroupName,
"Expected $expectedGroupName, but receive ${boardBloc.groupControllers.values.first.group.groupName}",
);
});
@ -101,8 +102,8 @@ void main() {
final groups =
boardBloc.groupControllers.values.map((e) => e.group).toList();
assert(groups[0].desc == "No ${multiSelectField.name}");
assert(groups[1].desc == "B");
assert(groups[2].desc == "A");
assert(groups[0].groupName == "No ${multiSelectField.name}");
assert(groups[1].groupName == "B");
assert(groups[2].groupName == "A");
});
}

View File

@ -99,7 +99,7 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "appflowy-integrate"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"collab",
@ -1024,7 +1024,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"bytes",
@ -1042,7 +1042,7 @@ dependencies = [
[[package]]
name = "collab-client-ws"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"bytes",
"collab-sync",
@ -1060,7 +1060,7 @@ dependencies = [
[[package]]
name = "collab-database"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"async-trait",
@ -1086,7 +1086,7 @@ dependencies = [
[[package]]
name = "collab-derive"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"proc-macro2",
"quote",
@ -1098,7 +1098,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"collab",
@ -1115,7 +1115,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"chrono",
@ -1135,7 +1135,7 @@ dependencies = [
[[package]]
name = "collab-persistence"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"bincode",
"chrono",
@ -1155,7 +1155,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"async-trait",
@ -1186,7 +1186,7 @@ dependencies = [
[[package]]
name = "collab-sync"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"bytes",
"collab",

View File

@ -34,12 +34,12 @@ default = ["custom-protocol"]
custom-protocol = ["tauri/custom-protocol"]
[patch.crates-io]
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "87f534" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "87f534" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "87f534" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "87f534" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "87f534" }
appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "87f534" }
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c382b1" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c382b1" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c382b1" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c382b1" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c382b1" }
appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c382b1" }
#collab = { path = "../../AppFlowy-Collab/collab" }
#collab-folder = { path = "../../AppFlowy-Collab/collab-folder" }

View File

@ -24,7 +24,7 @@ export class DateCellDataPersistence extends CellDataPersistence<CalendarData> {
}
save(data: CalendarData): Promise<Result<void, FlowyError>> {
const payload = DateChangesetPB.fromObject({ cell_path: _makeCellPath(this.cellIdentifier) });
const payload = DateChangesetPB.fromObject({ cell_id: _makeCellId(this.cellIdentifier) });
payload.date = ((data.date.getTime() / 1000) | 0).toString();
if (data.time !== undefined) {
payload.time = data.time;
@ -34,7 +34,7 @@ export class DateCellDataPersistence extends CellDataPersistence<CalendarData> {
}
}
function _makeCellPath(cellIdentifier: CellIdentifier): CellIdPB {
function _makeCellId(cellIdentifier: CellIdentifier): CellIdPB {
return CellIdPB.fromObject({
view_id: cellIdentifier.viewId,
field_id: cellIdentifier.fieldId,

View File

@ -1,9 +1,9 @@
import { DatabaseNotification, FlowyError, GroupPB, GroupRowsNotificationPB, RowPB } from "@/services/backend";
import { ChangeNotifier } from "$app/utils/change_notifier";
import { None, Ok, Option, Result, Some } from "ts-results";
import { DatabaseNotificationObserver } from "../notifications/observer";
import { Log } from "$app/utils/log";
import { DatabaseBackendService } from "../database_bd_svc";
import { DatabaseNotification, FlowyError, GroupPB, GroupRowsNotificationPB, RowPB } from '@/services/backend';
import { ChangeNotifier } from '$app/utils/change_notifier';
import { None, Ok, Option, Result, Some } from 'ts-results';
import { DatabaseNotificationObserver } from '../notifications/observer';
import { Log } from '$app/utils/log';
import { DatabaseBackendService } from '../database_bd_svc';
export type GroupDataCallbacks = {
onRemoveRow: (groupId: string, rowId: string) => void;
@ -30,7 +30,7 @@ export class DatabaseGroupController {
}
get name() {
return this.group.desc;
return this.group.group_name;
}
updateGroup = (group: GroupPB) => {
@ -83,7 +83,7 @@ export class DatabaseGroupController {
} else {
Log.error(result.val);
}
}
},
});
};
@ -111,8 +111,7 @@ class GroupDataObserver {
private notifier?: ChangeNotifier<Result<GroupRowsNotificationPB, FlowyError>>;
private listener?: DatabaseNotificationObserver;
constructor(public readonly groupId: string) {
}
constructor(public readonly groupId: string) {}
subscribe = async (callbacks: { onRowsChanged: GroupRowsSubscribeCallback }) => {
this.notifier = new ChangeNotifier();
@ -132,7 +131,7 @@ class GroupDataObserver {
default:
break;
}
}
},
});
await this.listener.start();
};

View File

@ -85,7 +85,7 @@ checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
[[package]]
name = "appflowy-integrate"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"collab",
@ -887,7 +887,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"bytes",
@ -905,7 +905,7 @@ dependencies = [
[[package]]
name = "collab-client-ws"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"bytes",
"collab-sync",
@ -923,7 +923,7 @@ dependencies = [
[[package]]
name = "collab-database"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"async-trait",
@ -949,7 +949,7 @@ dependencies = [
[[package]]
name = "collab-derive"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"proc-macro2",
"quote",
@ -961,7 +961,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"collab",
@ -978,7 +978,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"chrono",
@ -998,7 +998,7 @@ dependencies = [
[[package]]
name = "collab-persistence"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"bincode",
"chrono",
@ -1018,7 +1018,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"anyhow",
"async-trait",
@ -1049,7 +1049,7 @@ dependencies = [
[[package]]
name = "collab-sync"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=87f534#87f53452241a65275f5b2878ba57dff2a0e2b838"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=c382b1#c382b1ceb44e5615175e3b01f2bf0d49f6c669e3"
dependencies = [
"bytes",
"collab",

View File

@ -33,11 +33,11 @@ opt-level = 3
incremental = false
[patch.crates-io]
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "87f534" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "87f534" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "87f534" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "87f534" }
appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "87f534" }
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c382b1" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c382b1" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c382b1" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c382b1" }
appflowy-integrate = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c382b1" }
#collab = { path = "../AppFlowy-Collab/collab" }
#collab-folder = { path = "../AppFlowy-Collab/collab-folder" }

View File

@ -80,17 +80,11 @@ impl std::convert::From<CalendarLayout> for CalendarLayoutPB {
pub struct CalendarEventRequestPB {
#[pb(index = 1)]
pub view_id: String,
// Currently, requesting the events within the specified month
// is not supported
#[pb(index = 2)]
pub month: String,
}
#[derive(Debug, Clone, Default)]
pub struct CalendarEventRequestParams {
pub view_id: String,
pub month: String,
}
impl TryInto<CalendarEventRequestParams> for CalendarEventRequestPB {
@ -98,10 +92,7 @@ impl TryInto<CalendarEventRequestParams> for CalendarEventRequestPB {
fn try_into(self) -> Result<CalendarEventRequestParams, Self::Error> {
let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::ViewIdIsInvalid)?;
Ok(CalendarEventRequestParams {
view_id: view_id.0,
month: self.month,
})
Ok(CalendarEventRequestParams { view_id: view_id.0 })
}
}

View File

@ -135,11 +135,13 @@ impl TryInto<MoveRowParams> for MoveRowPayloadPB {
fn try_into(self) -> Result<MoveRowParams, Self::Error> {
let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::DatabaseViewIdIsEmpty)?;
let from_row_id = NotEmptyStr::parse(self.from_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
let to_row_id = NotEmptyStr::parse(self.to_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
Ok(MoveRowParams {
view_id: view_id.0,
from_row_id: RowId::from(self.from_row_id),
to_row_id: RowId::from(self.to_row_id),
from_row_id: RowId::from(from_row_id.0),
to_row_id: RowId::from(to_row_id.0),
})
}
}

View File

@ -76,7 +76,7 @@ pub struct GroupPB {
pub group_id: String,
#[pb(index = 3)]
pub desc: String,
pub group_name: String,
#[pb(index = 4)]
pub rows: Vec<RowPB>,
@ -93,7 +93,7 @@ impl std::convert::From<GroupData> for GroupPB {
Self {
field_id: group_data.field_id,
group_id: group_data.id,
desc: group_data.name,
group_name: group_data.name,
rows: group_data.rows.into_iter().map(RowPB::from).collect(),
is_default: group_data.is_default,
is_visible: group_data.is_visible,
@ -108,9 +108,6 @@ pub struct GroupByFieldPayloadPB {
#[pb(index = 2)]
pub view_id: String,
#[pb(index = 3)]
pub field_type: FieldType,
}
impl TryInto<GroupByFieldParams> for GroupByFieldPayloadPB {
@ -124,18 +121,13 @@ impl TryInto<GroupByFieldParams> for GroupByFieldPayloadPB {
.map_err(|_| ErrorCode::ViewIdIsInvalid)?
.0;
Ok(GroupByFieldParams {
field_id,
view_id,
field_type: self.field_type,
})
Ok(GroupByFieldParams { field_id, view_id })
}
}
pub struct GroupByFieldParams {
pub field_id: String,
pub view_id: String,
pub field_type: FieldType,
}
pub struct DeleteGroupParams {

View File

@ -158,6 +158,7 @@ impl TryInto<RowIdParams> for RowIdPB {
fn try_into(self) -> Result<RowIdParams, Self::Error> {
let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::DatabaseIdIsEmpty)?;
let row_id = NotEmptyStr::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
let group_id = match self.group_id {
Some(group_id) => Some(
NotEmptyStr::parse(group_id)
@ -169,7 +170,7 @@ impl TryInto<RowIdParams> for RowIdPB {
Ok(RowIdParams {
view_id: view_id.0,
row_id: RowId::from(self.row_id),
row_id: RowId::from(row_id.0),
group_id,
})
}

View File

@ -1,11 +1,12 @@
use collab_database::rows::RowId;
use flowy_derive::ProtoBuf;
use flowy_error::{ErrorCode, FlowyError};
use crate::entities::parser::NotEmptyStr;
use crate::entities::SelectOptionPB;
use crate::services::field::checklist_type_option::ChecklistCellData;
use crate::services::field::SelectOption;
use collab_database::rows::RowId;
use flowy_derive::ProtoBuf;
use flowy_error::{ErrorCode, FlowyError};
#[derive(Debug, Clone, Default, ProtoBuf)]
pub struct ChecklistCellDataPB {
@ -16,7 +17,7 @@ pub struct ChecklistCellDataPB {
pub selected_options: Vec<SelectOptionPB>,
#[pb(index = 3)]
pub(crate) percentage: f64,
pub percentage: f64,
}
impl From<ChecklistCellData> for ChecklistCellDataPB {

View File

@ -25,7 +25,7 @@ pub struct DateCellDataPB {
#[derive(Clone, Debug, Default, ProtoBuf)]
pub struct DateChangesetPB {
#[pb(index = 1)]
pub cell_path: CellIdPB,
pub cell_id: CellIdPB,
#[pb(index = 2, one_of)]
pub date: Option<String>,

View File

@ -294,7 +294,9 @@ pub(crate) async fn get_row_handler(
) -> DataResult<OptionalRowPB, FlowyError> {
let params: RowIdParams = data.into_inner().try_into()?;
let database_editor = manager.get_database_with_view_id(&params.view_id).await?;
let row = database_editor.get_row(&params.row_id).map(RowPB::from);
let row = database_editor
.get_row(&params.view_id, &params.row_id)
.map(RowPB::from);
data_result_ok(OptionalRowPB { row })
}
@ -525,7 +527,7 @@ pub(crate) async fn update_date_cell_handler(
manager: AFPluginState<Arc<DatabaseManager2>>,
) -> Result<(), FlowyError> {
let data = data.into_inner();
let cell_id: CellIdParams = data.cell_path.try_into()?;
let cell_id: CellIdParams = data.cell_id.try_into()?;
let cell_changeset = DateCellChangeset {
date: data.date,
time: data.time,

View File

@ -496,8 +496,12 @@ impl DatabaseEditor {
Ok(view_editor.v_get_rows().await)
}
pub fn get_row(&self, row_id: &RowId) -> Option<Row> {
self.database.lock().get_row(row_id)
pub fn get_row(&self, view_id: &str, row_id: &RowId) -> Option<Row> {
if self.database.lock().views.is_row_exist(view_id, row_id) {
return None;
} else {
self.database.lock().get_row(row_id)
}
}
pub async fn delete_row(&self, row_id: &RowId) {
@ -832,6 +836,11 @@ impl DatabaseEditor {
from_group: &str,
to_group: &str,
) -> FlowyResult<()> {
// Do nothing if the group is the same
if from_group == to_group {
return Ok(());
}
let view = self.database_views.get_view_editor(view_id).await?;
view.v_move_group(from_group, to_group).await?;
Ok(())

View File

@ -375,6 +375,7 @@ impl DatabaseViewEditor {
.as_ref()?
.groups()
.into_iter()
.filter(|group| group.is_visible)
.map(|group_data| GroupPB::from(group_data.clone()))
.collect::<Vec<_>>();
tracing::trace!("Number of groups: {}", groups.len());

View File

@ -351,15 +351,21 @@ where
}
pub(crate) fn update_group(&mut self, group_changeset: GroupChangeset) -> FlowyResult<()> {
self.mut_group(&group_changeset.group_id, |group| {
let update_group = self.mut_group(&group_changeset.group_id, |group| {
if let Some(visible) = group_changeset.visible {
group.visible = visible;
}
if let Some(name) = &group_changeset.name {
group.name = name.clone();
}
})?;
if let Some(group) = update_group {
self.group_by_id.get_mut(&group.id).map(|group_data| {
group_data.name = group.name.clone();
group_data.is_visible = group.visible;
});
}
Ok(())
}
@ -370,6 +376,11 @@ where
.await
}
/// # Arguments
///
/// * `mut_configuration_fn`: mutate the [GroupSetting] and return whether the [GroupSetting] is
/// changed. If the [GroupSetting] is changed, the [GroupSetting] will be saved to the storage.
///
fn mut_configuration(
&mut self,
mut_configuration_fn: impl FnOnce(&mut GroupSetting) -> bool,
@ -392,7 +403,12 @@ where
Ok(())
}
fn mut_group(&mut self, group_id: &str, mut_groups_fn: impl Fn(&mut Group)) -> FlowyResult<()> {
fn mut_group(
&mut self,
group_id: &str,
mut_groups_fn: impl Fn(&mut Group),
) -> FlowyResult<Option<Group>> {
let mut updated_group = None;
self.mut_configuration(|configuration| {
match configuration
.groups
@ -402,10 +418,12 @@ where
None => false,
Some(group) => {
mut_groups_fn(group);
updated_group = Some(group.clone());
true
},
}
})
})?;
Ok(updated_group)
}
}

View File

@ -1,6 +1,7 @@
use collab_database::database::gen_row_id;
use collab_database::fields::Field;
use collab_database::rows::{CreateRowParams, RowId};
use flowy_database2::entities::{FieldType, GroupPB, RowPB};
use flowy_database2::services::cell::{
delete_select_option_cell, insert_select_option_cell, insert_url_cell,
@ -233,7 +234,7 @@ impl DatabaseGroupTest {
} => {
let group = self.group_at_index(group_index).await;
assert_eq!(group.group_id, group_pb.group_id);
assert_eq!(group.desc, group_pb.desc);
assert_eq!(group.group_name, group_pb.group_name);
},
GroupScript::UpdateSingleSelectSelectOption { inserted_options } => {
self

View File

@ -463,7 +463,7 @@ async fn group_insert_single_select_option_test() {
];
test.run_scripts(scripts).await;
let new_group = test.group_at_index(1).await;
assert_eq!(new_group.desc, new_option_name);
assert_eq!(new_group.group_name, new_option_name);
}
#[tokio::test]

View File

@ -1,3 +1,5 @@
use bytes::Bytes;
use std::convert::TryFrom;
use std::env::temp_dir;
use std::sync::Arc;
@ -132,6 +134,49 @@ impl FlowyCoreTest {
.parse::<flowy_folder2::entities::ViewPB>()
}
pub async fn create_board(&self, parent_id: &str, name: String, initial_data: Vec<u8>) -> ViewPB {
let payload = CreateViewPayloadPB {
parent_view_id: parent_id.to_string(),
name,
desc: "".to_string(),
thumbnail: None,
layout: ViewLayoutPB::Board,
initial_data,
meta: Default::default(),
set_as_current: true,
};
EventBuilder::new(self.clone())
.event(flowy_folder2::event_map::FolderEvent::CreateView)
.payload(payload)
.async_send()
.await
.parse::<flowy_folder2::entities::ViewPB>()
}
pub async fn create_calendar(
&self,
parent_id: &str,
name: String,
initial_data: Vec<u8>,
) -> ViewPB {
let payload = CreateViewPayloadPB {
parent_view_id: parent_id.to_string(),
name,
desc: "".to_string(),
thumbnail: None,
layout: ViewLayoutPB::Calendar,
initial_data,
meta: Default::default(),
set_as_current: true,
};
EventBuilder::new(self.clone())
.event(flowy_folder2::event_map::FolderEvent::CreateView)
.payload(payload)
.async_send()
.await
.parse::<flowy_folder2::entities::ViewPB>()
}
pub async fn get_database(&self, view_id: &str) -> DatabasePB {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::GetDatabase)
@ -238,7 +283,20 @@ impl FlowyCoreTest {
.parse::<RowPB>()
}
pub async fn get_row(&self, view_id: &str, row_id: &str) -> RowPB {
pub async fn delete_row(&self, view_id: &str, row_id: &str) -> Option<FlowyError> {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::DeleteRow)
.payload(RowIdPB {
view_id: view_id.to_string(),
row_id: row_id.to_string(),
group_id: None,
})
.async_send()
.await
.error()
}
pub async fn get_row(&self, view_id: &str, row_id: &str) -> OptionalRowPB {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::GetRow)
.payload(RowIdPB {
@ -248,7 +306,7 @@ impl FlowyCoreTest {
})
.async_send()
.await
.parse::<RowPB>()
.parse::<OptionalRowPB>()
}
pub async fn duplicate_row(&self, view_id: &str, row_id: &str) -> Option<FlowyError> {
@ -264,6 +322,19 @@ impl FlowyCoreTest {
.error()
}
pub async fn move_row(&self, view_id: &str, row_id: &str, to_row_id: &str) -> Option<FlowyError> {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::MoveRow)
.payload(MoveRowPayloadPB {
view_id: view_id.to_string(),
from_row_id: row_id.to_string(),
to_row_id: to_row_id.to_string(),
})
.async_send()
.await
.error()
}
pub async fn update_cell(&self, changeset: CellChangesetPB) -> Option<FlowyError> {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::UpdateCell)
@ -273,6 +344,15 @@ impl FlowyCoreTest {
.error()
}
pub async fn update_date_cell(&self, changeset: DateChangesetPB) -> Option<FlowyError> {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::UpdateDateCell)
.payload(changeset)
.async_send()
.await
.error()
}
pub async fn get_cell(&self, view_id: &str, row_id: &str, field_id: &str) -> CellPB {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::GetCell)
@ -286,6 +366,41 @@ impl FlowyCoreTest {
.parse::<CellPB>()
}
pub async fn get_date_cell(&self, view_id: &str, row_id: &str, field_id: &str) -> DateCellDataPB {
let cell = self.get_cell(view_id, row_id, field_id).await;
DateCellDataPB::try_from(Bytes::from(cell.data)).unwrap()
}
pub async fn get_checklist_cell(
&self,
view_id: &str,
field_id: &str,
row_id: &str,
) -> ChecklistCellDataPB {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::GetChecklistCellData)
.payload(CellIdPB {
view_id: view_id.to_string(),
row_id: row_id.to_string(),
field_id: field_id.to_string(),
})
.async_send()
.await
.parse::<ChecklistCellDataPB>()
}
pub async fn update_checklist_cell(
&self,
changeset: ChecklistCellDataChangesetPB,
) -> Option<FlowyError> {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::UpdateChecklistCell)
.payload(changeset)
.async_send()
.await
.error()
}
pub async fn insert_option(
&self,
view_id: &str,
@ -317,6 +432,84 @@ impl FlowyCoreTest {
.error()
}
pub async fn get_groups(&self, view_id: &str) -> Vec<GroupPB> {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::GetGroups)
.payload(DatabaseViewIdPB {
value: view_id.to_string(),
})
.async_send()
.await
.parse::<RepeatedGroupPB>()
.items
}
pub async fn move_group(&self, view_id: &str, from_id: &str, to_id: &str) -> Option<FlowyError> {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::MoveGroup)
.payload(MoveGroupPayloadPB {
view_id: view_id.to_string(),
from_group_id: from_id.to_string(),
to_group_id: to_id.to_string(),
})
.async_send()
.await
.error()
}
pub async fn set_group_by_field(&self, view_id: &str, field_id: &str) -> Option<FlowyError> {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::SetGroupByField)
.payload(GroupByFieldPayloadPB {
field_id: field_id.to_string(),
view_id: view_id.to_string(),
})
.async_send()
.await
.error()
}
pub async fn update_group(
&self,
view_id: &str,
group_id: &str,
name: Option<String>,
visible: Option<bool>,
) -> Option<FlowyError> {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::UpdateGroup)
.payload(UpdateGroupPB {
view_id: view_id.to_string(),
group_id: group_id.to_string(),
name,
visible,
})
.async_send()
.await
.error()
}
pub async fn update_setting(&self, changeset: DatabaseSettingChangesetPB) -> Option<FlowyError> {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::UpdateDatabaseSetting)
.payload(changeset)
.async_send()
.await
.error()
}
pub async fn get_all_calendar_events(&self, view_id: &str) -> Vec<CalendarEventPB> {
EventBuilder::new(self.clone())
.event(flowy_database2::event_map::DatabaseEvent::GetAllCalendarEvents)
.payload(CalendarEventRequestPB {
view_id: view_id.to_string(),
})
.async_send()
.await
.parse::<RepeatedCalendarEventPB>()
.items
}
pub async fn get_view(&self, view_id: &str) -> ViewPB {
EventBuilder::new(self.clone())
.event(flowy_folder2::event_map::FolderEvent::ReadView)

View File

@ -1,9 +1,11 @@
use std::convert::TryFrom;
use bytes::Bytes;
use lib_infra::util::timestamp;
use flowy_database2::entities::{
CellChangesetPB, DatabaseLayoutPB, DatabaseViewIdPB, FieldType, SelectOptionCellDataPB,
CellChangesetPB, CellIdPB, ChecklistCellDataChangesetPB, DatabaseLayoutPB,
DatabaseSettingChangesetPB, DatabaseViewIdPB, DateChangesetPB, FieldType, SelectOptionCellDataPB,
};
use flowy_test::event_builder::EventBuilder;
use flowy_test::FlowyCoreTest;
@ -93,6 +95,7 @@ async fn delete_field_event_test() {
assert_eq!(fields.len(), 2);
}
// The primary field is not allowed to be deleted.
#[tokio::test]
async fn delete_primary_field_event_test() {
let test = FlowyCoreTest::new_with_user().await;
@ -162,6 +165,7 @@ async fn duplicate_field_event_test() {
assert_eq!(fields.len(), 4);
}
// The primary field is not allowed to be duplicated. So this test should return an error.
#[tokio::test]
async fn duplicate_primary_field_test() {
let test = FlowyCoreTest::new_with_user().await;
@ -189,6 +193,40 @@ async fn create_row_event_test() {
assert_eq!(database.rows.len(), 4);
}
#[tokio::test]
async fn delete_row_event_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
// delete the row
let database = test.get_database(&grid_view.id).await;
let error = test.delete_row(&grid_view.id, &database.rows[0].id).await;
assert!(error.is_none());
let database = test.get_database(&grid_view.id).await;
assert_eq!(database.rows.len(), 2);
// get the row again and check if it is deleted.
let optional_row = test.get_row(&grid_view.id, &database.rows[0].id).await;
assert!(optional_row.row.is_none());
}
#[tokio::test]
async fn delete_row_event_with_invalid_row_id_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
// delete the row with empty row_id. It should return an error.
let error = test.delete_row(&grid_view.id, "").await;
assert!(error.is_some());
}
#[tokio::test]
async fn duplicate_row_event_test() {
let test = FlowyCoreTest::new_with_user().await;
@ -206,6 +244,90 @@ async fn duplicate_row_event_test() {
assert_eq!(database.rows.len(), 4);
}
#[tokio::test]
async fn duplicate_row_event_with_invalid_row_id_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
let database = test.get_database(&grid_view.id).await;
assert_eq!(database.rows.len(), 3);
let error = test.duplicate_row(&grid_view.id, "").await;
assert!(error.is_some());
let database = test.get_database(&grid_view.id).await;
assert_eq!(database.rows.len(), 3);
}
#[tokio::test]
async fn move_row_event_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
let database = test.get_database(&grid_view.id).await;
let row_1 = database.rows[0].id.clone();
let row_2 = database.rows[1].id.clone();
let row_3 = database.rows[2].id.clone();
let error = test.move_row(&grid_view.id, &row_1, &row_3).await;
assert!(error.is_none());
let database = test.get_database(&grid_view.id).await;
assert_eq!(database.rows[0].id, row_2);
assert_eq!(database.rows[1].id, row_3);
assert_eq!(database.rows[2].id, row_1);
}
#[tokio::test]
async fn move_row_event_test2() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
let database = test.get_database(&grid_view.id).await;
let row_1 = database.rows[0].id.clone();
let row_2 = database.rows[1].id.clone();
let row_3 = database.rows[2].id.clone();
let error = test.move_row(&grid_view.id, &row_2, &row_1).await;
assert!(error.is_none());
let database = test.get_database(&grid_view.id).await;
assert_eq!(database.rows[0].id, row_2);
assert_eq!(database.rows[1].id, row_1);
assert_eq!(database.rows[2].id, row_3);
}
#[tokio::test]
async fn move_row_event_with_invalid_row_id_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
let database = test.get_database(&grid_view.id).await;
let row_1 = database.rows[0].id.clone();
let row_2 = database.rows[1].id.clone();
let row_3 = database.rows[2].id.clone();
for i in 0..2 {
if i == 0 {
let error = test.move_row(&grid_view.id, &row_1, "").await;
assert!(error.is_some());
} else {
let error = test.move_row(&grid_view.id, "", &row_1).await;
assert!(error.is_some());
}
let database = test.get_database(&grid_view.id).await;
assert_eq!(database.rows[0].id, row_1);
assert_eq!(database.rows[1].id, row_2);
assert_eq!(database.rows[2].id, row_3);
}
}
#[tokio::test]
async fn update_text_cell_event_test() {
let test = FlowyCoreTest::new_with_user().await;
@ -280,14 +402,415 @@ async fn update_single_select_cell_event_test() {
let field_id = fields[1].id.clone();
assert_eq!(fields[1].field_type, FieldType::SingleSelect);
// Insert a new option. This should update the cell with the new option.
let error = test
.insert_option(&grid_view.id, &field_id, &row_id, "task 1")
.await;
assert!(error.is_none());
// Check that the cell data is updated.
let cell = test.get_cell(&grid_view.id, &row_id, &field_id).await;
let select_option_cell = SelectOptionCellDataPB::try_from(Bytes::from(cell.data)).unwrap();
assert_eq!(select_option_cell.options.len(), 1);
assert_eq!(select_option_cell.select_options.len(), 1);
}
#[tokio::test]
async fn update_date_cell_event_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
let database = test.get_database(&grid_view.id).await;
// Create a date field
let date_field = test.create_field(&grid_view.id, FieldType::DateTime).await;
let cell_path = CellIdPB {
view_id: grid_view.id.clone(),
field_id: date_field.id.clone(),
row_id: database.rows[0].id.clone(),
};
// Insert data into the date cell of the first row.
let timestamp = 1686300557;
let timestamp_str = 1686300557.to_string();
let error = test
.update_date_cell(DateChangesetPB {
cell_id: cell_path,
date: Some(timestamp_str.clone()),
time: None,
include_time: None,
})
.await;
assert!(error.is_none());
// Check that the cell data is updated.
let cell = test
.get_date_cell(&grid_view.id, &database.rows[0].id, &date_field.id)
.await;
assert_eq!(cell.date, "Jun 09, 2023");
assert_eq!(cell.timestamp, timestamp);
}
#[tokio::test]
async fn update_date_cell_event_with_empty_time_str_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
let database = test.get_database(&grid_view.id).await;
let row_id = database.rows[0].id.clone();
// Create a date field
let date_field = test.create_field(&grid_view.id, FieldType::DateTime).await;
let cell_path = CellIdPB {
view_id: grid_view.id.clone(),
field_id: date_field.id.clone(),
row_id: row_id.clone(),
};
// Insert empty timestamp string
let error = test
.update_date_cell(DateChangesetPB {
cell_id: cell_path,
date: Some("".to_string()),
..Default::default()
})
.await;
assert!(error.is_none());
// Check that the cell data is updated.
let cell = test
.get_date_cell(&grid_view.id, &row_id, &date_field.id)
.await;
assert_eq!(cell.date, "");
assert_eq!(cell.timestamp, 0);
}
#[tokio::test]
async fn create_checklist_field_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
// create checklist field
let checklist_field = test.create_field(&grid_view.id, FieldType::Checklist).await;
let database = test.get_database(&grid_view.id).await;
// Get the checklist cell
let cell = test
.get_checklist_cell(&grid_view.id, &checklist_field.id, &database.rows[0].id)
.await;
assert_eq!(cell.options.len(), 0);
assert_eq!(cell.selected_options.len(), 0);
assert_eq!(cell.percentage, 0.0);
}
#[tokio::test]
async fn update_checklist_cell_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
// create checklist field
let checklist_field = test.create_field(&grid_view.id, FieldType::Checklist).await;
let database = test.get_database(&grid_view.id).await;
// update the checklist cell
let changeset = ChecklistCellDataChangesetPB {
view_id: grid_view.id.clone(),
row_id: database.rows[0].id.clone(),
field_id: checklist_field.id.clone(),
insert_options: vec![
"task 1".to_string(),
"task 2".to_string(),
"task 3".to_string(),
],
selected_option_ids: vec![],
delete_option_ids: vec![],
update_options: vec![],
};
test.update_checklist_cell(changeset).await;
// get the cell
let cell = test
.get_checklist_cell(&grid_view.id, &checklist_field.id, &database.rows[0].id)
.await;
assert_eq!(cell.options.len(), 3);
assert_eq!(cell.selected_options.len(), 0);
// select some options
let changeset = ChecklistCellDataChangesetPB {
view_id: grid_view.id.clone(),
row_id: database.rows[0].id.clone(),
field_id: checklist_field.id.clone(),
selected_option_ids: vec![cell.options[0].id.clone(), cell.options[1].id.clone()],
..Default::default()
};
test.update_checklist_cell(changeset).await;
// get the cell
let cell = test
.get_checklist_cell(&grid_view.id, &checklist_field.id, &database.rows[0].id)
.await;
assert_eq!(cell.options.len(), 3);
assert_eq!(cell.selected_options.len(), 2);
assert_eq!(cell.percentage, 0.6666666666666666);
}
// The number of groups should be 0 if there is no group by field in grid
#[tokio::test]
async fn get_groups_event_with_grid_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
let groups = test.get_groups(&grid_view.id).await;
assert_eq!(groups.len(), 0);
}
#[tokio::test]
async fn get_groups_event_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
let groups = test.get_groups(&board_view.id).await;
assert_eq!(groups.len(), 4);
}
#[tokio::test]
async fn move_group_event_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
let groups = test.get_groups(&board_view.id).await;
assert_eq!(groups.len(), 4);
let group_1 = groups[0].group_id.clone();
let group_2 = groups[1].group_id.clone();
let group_3 = groups[2].group_id.clone();
let group_4 = groups[3].group_id.clone();
let error = test.move_group(&board_view.id, &group_2, &group_3).await;
assert!(error.is_none());
let groups = test.get_groups(&board_view.id).await;
assert_eq!(groups[0].group_id, group_1);
assert_eq!(groups[1].group_id, group_3);
assert_eq!(groups[2].group_id, group_2);
assert_eq!(groups[3].group_id, group_4);
let error = test.move_group(&board_view.id, &group_1, &group_4).await;
assert!(error.is_none());
let groups = test.get_groups(&board_view.id).await;
assert_eq!(groups[0].group_id, group_3);
assert_eq!(groups[1].group_id, group_2);
assert_eq!(groups[2].group_id, group_4);
assert_eq!(groups[3].group_id, group_1);
}
#[tokio::test]
async fn move_group_event_with_invalid_id_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
// Empty to group id
let groups = test.get_groups(&board_view.id).await;
let error = test
.move_group(&board_view.id, &groups[0].group_id, "")
.await;
assert!(error.is_some());
// empty from group id
let error = test
.move_group(&board_view.id, "", &groups[1].group_id)
.await;
assert!(error.is_some());
}
#[tokio::test]
async fn rename_group_event_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
// Empty to group id
let groups = test.get_groups(&board_view.id).await;
let error = test
.update_group(
&board_view.id,
&groups[0].group_id,
Some("new name".to_owned()),
None,
)
.await;
assert!(error.is_none());
let groups = test.get_groups(&board_view.id).await;
assert_eq!(groups[0].group_name, "new name".to_owned());
}
#[tokio::test]
async fn hide_group_event_test2() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
// Empty to group id
let groups = test.get_groups(&board_view.id).await;
assert_eq!(groups.len(), 4);
let error = test
.update_group(&board_view.id, &groups[0].group_id, None, Some(false))
.await;
assert!(error.is_none());
let groups = test.get_groups(&board_view.id).await;
assert_eq!(groups.len(), 3);
}
// Update the database layout type from grid to board
#[tokio::test]
async fn update_database_layout_event_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
let error = test
.update_setting(DatabaseSettingChangesetPB {
view_id: grid_view.id.clone(),
layout_type: Some(DatabaseLayoutPB::Board),
..Default::default()
})
.await;
assert!(error.is_none());
let database = test.get_database(&grid_view.id).await;
assert_eq!(database.layout_type, DatabaseLayoutPB::Board);
}
// Update the database layout type from grid to board. Set the checkbox field as the grouping field
#[tokio::test]
async fn update_database_layout_event_test2() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
let fields = test.get_all_database_fields(&grid_view.id).await.items;
let checkbox_field = fields
.iter()
.find(|field| field.field_type == FieldType::Checkbox)
.unwrap();
test
.set_group_by_field(&grid_view.id, &checkbox_field.id)
.await;
let error = test
.update_setting(DatabaseSettingChangesetPB {
view_id: grid_view.id.clone(),
layout_type: Some(DatabaseLayoutPB::Board),
..Default::default()
})
.await;
assert!(error.is_none());
// Empty to group id
let groups = test.get_groups(&grid_view.id).await;
assert_eq!(groups.len(), 2);
}
// Create a checkbox field in the default board and then set it as the grouping field.
#[tokio::test]
async fn set_group_by_checkbox_field_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
let checkbox_field = test.create_field(&board_view.id, FieldType::Checkbox).await;
test
.set_group_by_field(&board_view.id, &checkbox_field.id)
.await;
let groups = test.get_groups(&board_view.id).await;
assert_eq!(groups.len(), 2);
}
#[tokio::test]
async fn get_all_calendar_event_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let calendar_view = test
.create_calendar(&current_workspace.id, "my calendar view".to_owned(), vec![])
.await;
// By default, there should be no events
let events = test.get_all_calendar_events(&calendar_view.id).await;
assert!(events.is_empty());
}
#[tokio::test]
async fn create_calendar_event_test() {
let test = FlowyCoreTest::new_with_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let calendar_view = test
.create_calendar(&current_workspace.id, "my calendar view".to_owned(), vec![])
.await;
let fields = test.get_all_database_fields(&calendar_view.id).await.items;
let date_field = fields
.iter()
.find(|field| field.field_type == FieldType::DateTime)
.unwrap();
// create a new row
let row = test.create_row(&calendar_view.id, None, None).await;
// Insert data into the date cell of the first row.
let timestamp_str = timestamp().to_string();
let error = test
.update_date_cell(DateChangesetPB {
cell_id: CellIdPB {
view_id: calendar_view.id.clone(),
field_id: date_field.id.clone(),
row_id: row.id,
},
date: Some(timestamp_str.clone()),
time: None,
include_time: None,
})
.await;
assert!(error.is_none());
let events = test.get_all_calendar_events(&calendar_view.id).await;
assert_eq!(events.len(), 1);
}