feat: add new group (#3854)

* feat: implement backend logic

* fix: did_create_row not working properly

* fix: did_delete_group not working properly

* fix: test

* chore: fix clippy

* fix: new card not editable and in wrong position

* feat: imlement UI for add new stack

* test: add integration test

* chore: i18n

* chore: remove debug message

* chore: merge conflict

---------

Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
Richard Shiue
2023-11-06 16:17:05 +08:00
committed by GitHub
parent 4d82bb5322
commit c4fc60612f
28 changed files with 674 additions and 138 deletions

View File

@ -1,11 +1,14 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database_view/widgets/card/card.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
import 'package:appflowy_board/appflowy_board.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import '../util/util.dart';
import '../util/database_test_op.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
@ -46,5 +49,56 @@ void main() {
await tester.tapButtonWithName(LocaleKeys.button_duplicate.tr());
expect(find.textContaining(name, findRichText: true), findsNWidgets(2));
});
testWidgets('add new group', (tester) async {
await tester.initializeAppFlowy();
await tester.tapGoButton();
await tester.createNewPageWithName(layout: ViewLayoutPB.Board);
// assert number of groups
tester.assertNumberOfGroups(4);
// scroll the board horizontally to ensure add new group button appears
await tester.scrollBoardToEnd();
// assert and click on add new group button
tester.assertNewGroupTextField(false);
await tester.tapNewGroupButton();
tester.assertNewGroupTextField(true);
// enter new group name and submit
await tester.enterNewGroupName('needs design', submit: true);
// assert number of groups has increased
tester.assertNumberOfGroups(5);
// assert text field has disappeared
await tester.scrollBoardToEnd();
tester.assertNewGroupTextField(false);
// click on add new group button
await tester.tapNewGroupButton();
tester.assertNewGroupTextField(true);
// type some things
await tester.enterNewGroupName('needs planning', submit: false);
// click on clear button and assert empty contents
await tester.clearNewGroupTextField();
// press escape to cancel
await tester.sendKeyEvent(LogicalKeyboardKey.escape);
await tester.pumpAndSettle();
tester.assertNewGroupTextField(false);
// click on add new group button
await tester.tapNewGroupButton();
tester.assertNewGroupTextField(true);
// press elsewhere to cancel
await tester.tap(find.byType(AppFlowyBoard));
await tester.pumpAndSettle();
tester.assertNewGroupTextField(false);
});
});
}

View File

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database_view/board/presentation/board_page.dart';
import 'package:appflowy/plugins/database_view/board/presentation/widgets/board_column_header.dart';
import 'package:appflowy/plugins/database_view/calendar/application/calendar_bloc.dart';
import 'package:appflowy/plugins/database_view/calendar/presentation/calendar_day.dart';
import 'package:appflowy/plugins/database_view/calendar/presentation/calendar_event_card.dart';
@ -59,6 +60,7 @@ import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
import 'package:appflowy_board/appflowy_board.dart';
import 'package:calendar_view/calendar_view.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@ -1390,6 +1392,84 @@ extension AppFlowyDatabaseTest on WidgetTester {
await tapButton(findCreateButton);
}
void assertNumberOfGroups(int number) {
final groups = find.byType(BoardColumnHeader, skipOffstage: false);
expect(groups, findsNWidgets(number));
}
Future<void> scrollBoardToEnd() async {
final scrollable = find
.descendant(
of: find.byType(AppFlowyBoard),
matching: find.byWidgetPredicate(
(widget) => widget is Scrollable && widget.axis == Axis.horizontal,
),
)
.first;
await scrollUntilVisible(
find.byType(BoardTrailing),
300,
scrollable: scrollable,
);
}
Future<void> tapNewGroupButton() async {
final button = find.descendant(
of: find.byType(BoardTrailing),
matching: find.byWidgetPredicate(
(widget) => widget is FlowySvg && widget.svg == FlowySvgs.add_s,
),
);
expect(button, findsOneWidget);
await tapButton(button);
}
void assertNewGroupTextField(bool isVisible) {
final textField = find.descendant(
of: find.byType(BoardTrailing),
matching: find.byType(TextField),
);
if (isVisible) {
expect(textField, findsOneWidget);
} else {
expect(textField, findsNothing);
}
}
Future<void> enterNewGroupName(String name, {required bool submit}) async {
final textField = find.descendant(
of: find.byType(BoardTrailing),
matching: find.byType(TextField),
);
await enterText(textField, name);
await pumpAndSettle();
if (submit) {
await testTextInput.receiveAction(TextInputAction.done);
await pumpAndSettle();
}
}
Future<void> clearNewGroupTextField() async {
final textField = find.descendant(
of: find.byType(BoardTrailing),
matching: find.byType(TextField),
);
await tapButton(
find.descendant(
of: textField,
matching: find.byWidgetPredicate(
(widget) =>
widget is FlowySvg && widget.svg == FlowySvgs.close_filled_m,
),
),
);
final textFieldWidget = widget<TextField>(textField);
assert(
textFieldWidget.controller != null &&
textFieldWidget.controller!.text.isEmpty,
);
}
Future<void> tapTabBarLinkedViewByViewName(String name) async {
final viewButton = findTabBarLinkViewByViewName(name);
await tapButton(viewButton);