2023-06-05 13:10:14 +08:00
|
|
|
import 'dart:ui';
|
2023-06-14 06:14:41 -05:00
|
|
|
import 'package:appflowy_backend/log.dart';
|
2023-02-26 16:27:17 +08:00
|
|
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
2023-06-14 22:16:33 +08:00
|
|
|
|
2023-06-10 22:38:25 +08:00
|
|
|
import 'package:appflowy/plugins/document/presentation/share/share_button.dart';
|
2023-06-05 13:10:14 +08:00
|
|
|
import 'package:appflowy/user/presentation/skip_log_in_screen.dart';
|
|
|
|
import 'package:appflowy/workspace/presentation/home/menu/app/header/add_button.dart';
|
|
|
|
import 'package:appflowy/workspace/presentation/home/menu/app/section/item.dart';
|
2023-06-14 06:14:41 -05:00
|
|
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_language_view.dart';
|
2023-06-15 16:33:44 +08:00
|
|
|
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
2022-12-20 11:14:42 +08:00
|
|
|
import 'package:easy_localization/easy_localization.dart';
|
2023-06-12 14:29:09 +08:00
|
|
|
import 'package:flowy_infra_ui/widget/buttons/primary_button.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
2022-12-20 11:14:42 +08:00
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
import 'util.dart';
|
2023-06-05 13:10:14 +08:00
|
|
|
|
2023-06-11 14:19:44 +08:00
|
|
|
extension CommonOperations on WidgetTester {
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Get current file location of AppFlowy.
|
2023-06-12 14:36:55 +08:00
|
|
|
Future<String> currentFileLocation() async {
|
|
|
|
return TestFolder.currentLocation();
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the GetStart button on the launch page.
|
2022-12-20 11:14:42 +08:00
|
|
|
Future<void> tapGoButton() async {
|
2023-06-05 13:10:14 +08:00
|
|
|
final goButton = find.byType(GoButton);
|
|
|
|
await tapButton(goButton);
|
2022-12-20 11:14:42 +08:00
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the + button on the home page.
|
2023-06-05 13:10:14 +08:00
|
|
|
Future<void> tapAddButton() async {
|
|
|
|
final addButton = find.byType(AddButton);
|
|
|
|
await tapButton(addButton);
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the create document button.
|
|
|
|
///
|
|
|
|
/// Must call [tapAddButton] first.
|
2023-06-05 13:10:14 +08:00
|
|
|
Future<void> tapCreateDocumentButton() async {
|
|
|
|
await tapButtonWithName(LocaleKeys.document_menuName.tr());
|
|
|
|
}
|
|
|
|
|
2023-06-14 22:16:33 +08:00
|
|
|
/// Tap the create grid button.
|
|
|
|
///
|
|
|
|
/// Must call [tapAddButton] first.
|
|
|
|
Future<void> tapCreateGridButton() async {
|
|
|
|
await tapButtonWithName(LocaleKeys.grid_menuName.tr());
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the import button.
|
|
|
|
///
|
|
|
|
/// Must call [tapAddButton] first.
|
2023-06-12 14:36:55 +08:00
|
|
|
Future<void> tapImportButton() async {
|
|
|
|
await tapButtonWithName(LocaleKeys.moreAction_import.tr());
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the import from text & markdown button.
|
|
|
|
///
|
|
|
|
/// Must call [tapImportButton] first.
|
2023-06-12 14:36:55 +08:00
|
|
|
Future<void> tapTextAndMarkdownButton() async {
|
|
|
|
await tapButtonWithName(LocaleKeys.importPanel_textAndMarkdown.tr());
|
|
|
|
}
|
|
|
|
|
2023-06-14 06:14:41 -05:00
|
|
|
/// Tap the LanguageSelectorOnWelcomePage widget on the launch page.
|
|
|
|
Future<void> tapLanguageSelectorOnWelcomePage() async {
|
|
|
|
final languageSelector = find.byType(LanguageSelectorOnWelcomePage);
|
|
|
|
await tapButton(languageSelector);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Tap languageItem on LanguageItemsListView.
|
|
|
|
///
|
|
|
|
/// [scrollDelta] is the distance to scroll the ListView.
|
|
|
|
/// Default value is 100
|
|
|
|
///
|
|
|
|
/// If it is positive -> scroll down.
|
|
|
|
///
|
|
|
|
/// If it is negative -> scroll up.
|
|
|
|
Future<void> tapLanguageItem({
|
|
|
|
required String languageCode,
|
|
|
|
String? countryCode,
|
|
|
|
double? scrollDelta,
|
|
|
|
}) async {
|
|
|
|
final languageItemsListView = find.descendant(
|
|
|
|
of: find.byType(ListView),
|
|
|
|
matching: find.byType(Scrollable),
|
|
|
|
);
|
|
|
|
|
|
|
|
final languageItem = find.byWidgetPredicate(
|
|
|
|
(widget) =>
|
|
|
|
widget is LanguageItem &&
|
|
|
|
widget.locale.languageCode == languageCode &&
|
|
|
|
widget.locale.countryCode == countryCode,
|
|
|
|
);
|
|
|
|
|
|
|
|
// scroll the ListView until zHCNLanguageItem shows on the screen.
|
|
|
|
await scrollUntilVisible(
|
|
|
|
languageItem,
|
|
|
|
scrollDelta ?? 100,
|
|
|
|
scrollable: languageItemsListView,
|
|
|
|
// maxHeight of LanguageItemsListView
|
|
|
|
maxScrolls: 400,
|
|
|
|
);
|
|
|
|
|
|
|
|
try {
|
|
|
|
await tapButton(languageItem);
|
|
|
|
} on FlutterError catch (e) {
|
|
|
|
Log.warn('tapLanguageItem error: $e');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Hover on the widget.
|
|
|
|
Future<void> hoverOnWidget(
|
|
|
|
Finder finder, {
|
|
|
|
Offset? offset,
|
2023-06-15 16:33:44 +08:00
|
|
|
Future<void> Function()? onHover,
|
2023-06-12 20:32:55 +08:00
|
|
|
}) async {
|
2023-06-14 22:16:33 +08:00
|
|
|
try {
|
|
|
|
final gesture = await createGesture(kind: PointerDeviceKind.mouse);
|
|
|
|
await gesture.addPointer(location: Offset.zero);
|
|
|
|
await pump();
|
|
|
|
await gesture.moveTo(offset ?? getCenter(finder));
|
|
|
|
await pumpAndSettle();
|
2023-06-15 16:33:44 +08:00
|
|
|
await onHover?.call();
|
|
|
|
await gesture.removePointer();
|
|
|
|
} catch (err) {
|
|
|
|
Log.error('hoverOnWidget error: $err');
|
|
|
|
}
|
2023-06-05 13:10:14 +08:00
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Hover on the page name.
|
2023-06-15 16:33:44 +08:00
|
|
|
Future<void> hoverOnPageName(
|
|
|
|
String name, {
|
|
|
|
Future<void> Function()? onHover,
|
|
|
|
bool useLast = true,
|
|
|
|
}) async {
|
|
|
|
if (useLast) {
|
|
|
|
await hoverOnWidget(findPageName(name).last, onHover: onHover);
|
|
|
|
} else {
|
|
|
|
await hoverOnWidget(findPageName(name).first, onHover: onHover);
|
|
|
|
}
|
2023-06-12 20:32:55 +08:00
|
|
|
}
|
|
|
|
|
2023-06-15 22:43:07 +08:00
|
|
|
/// open the page with given name.
|
|
|
|
Future<void> openPage(String name) async {
|
|
|
|
await tapButton(findPageName(name));
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the ... button beside the page name.
|
|
|
|
///
|
|
|
|
/// Must call [hoverOnPageName] first.
|
2023-06-05 13:10:14 +08:00
|
|
|
Future<void> tapPageOptionButton() async {
|
|
|
|
final optionButton = find.byType(ViewDisclosureButton);
|
|
|
|
await tapButton(optionButton);
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the delete page button.
|
2023-06-05 13:10:14 +08:00
|
|
|
Future<void> tapDeletePageButton() async {
|
|
|
|
await tapPageOptionButton();
|
|
|
|
await tapButtonWithName(ViewDisclosureAction.delete.name);
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the rename page button.
|
2023-06-12 14:29:09 +08:00
|
|
|
Future<void> tapRenamePageButton() async {
|
|
|
|
await tapPageOptionButton();
|
|
|
|
await tapButtonWithName(ViewDisclosureAction.rename.name);
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Rename the page.
|
2023-06-12 14:29:09 +08:00
|
|
|
Future<void> renamePage(String name) async {
|
|
|
|
await tapRenamePageButton();
|
|
|
|
await enterText(find.byType(TextFormField), name);
|
|
|
|
await tapOKButton();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> tapOKButton() async {
|
|
|
|
final okButton = find.byWidgetPredicate(
|
|
|
|
(widget) =>
|
|
|
|
widget is PrimaryTextButton &&
|
|
|
|
widget.label == LocaleKeys.button_OK.tr(),
|
|
|
|
);
|
|
|
|
await tapButton(okButton);
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the restore button.
|
|
|
|
///
|
|
|
|
/// the restore button will show after the current page is deleted.
|
2023-06-05 13:10:14 +08:00
|
|
|
Future<void> tapRestoreButton() async {
|
|
|
|
final restoreButton = find.textContaining(
|
|
|
|
LocaleKeys.deletePagePrompt_restore.tr(),
|
|
|
|
);
|
|
|
|
await tapButton(restoreButton);
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the delete permanently button.
|
|
|
|
///
|
|
|
|
/// the restore button will show after the current page is deleted.
|
2023-06-05 13:10:14 +08:00
|
|
|
Future<void> tapDeletePermanentlyButton() async {
|
|
|
|
final restoreButton = find.textContaining(
|
|
|
|
LocaleKeys.deletePagePrompt_deletePermanent.tr(),
|
|
|
|
);
|
|
|
|
await tapButton(restoreButton);
|
|
|
|
}
|
2023-06-10 22:38:25 +08:00
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the share button above the document page.
|
2023-06-10 22:38:25 +08:00
|
|
|
Future<void> tapShareButton() async {
|
|
|
|
final shareButton = find.byWidgetPredicate(
|
|
|
|
(widget) => widget is DocumentShareButton,
|
|
|
|
);
|
|
|
|
await tapButton(shareButton);
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:32:55 +08:00
|
|
|
/// Tap the export markdown button
|
|
|
|
///
|
|
|
|
/// Must call [tapShareButton] first.
|
2023-06-10 22:38:25 +08:00
|
|
|
Future<void> tapMarkdownButton() async {
|
|
|
|
final markdownButton = find.textContaining(
|
|
|
|
LocaleKeys.shareAction_markdown.tr(),
|
|
|
|
);
|
|
|
|
await tapButton(markdownButton);
|
|
|
|
}
|
|
|
|
|
2023-06-15 16:33:44 +08:00
|
|
|
Future<void> createNewPageWithName(ViewLayoutPB layout, String name) async {
|
|
|
|
// create a new page
|
|
|
|
await tapAddButton();
|
|
|
|
await tapButtonWithName(layout.menuName);
|
|
|
|
await pumpAndSettle();
|
|
|
|
|
|
|
|
// hover on it and change it's name
|
|
|
|
await hoverOnPageName(
|
|
|
|
LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
|
|
|
onHover: () async {
|
|
|
|
await renamePage(name);
|
|
|
|
await pumpAndSettle();
|
|
|
|
},
|
2023-06-11 14:19:44 +08:00
|
|
|
);
|
2023-06-15 16:33:44 +08:00
|
|
|
await pumpAndSettle();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension ViewLayoutPBTest on ViewLayoutPB {
|
|
|
|
String get menuName {
|
|
|
|
switch (this) {
|
|
|
|
case ViewLayoutPB.Grid:
|
|
|
|
return LocaleKeys.grid_menuName.tr();
|
|
|
|
case ViewLayoutPB.Board:
|
|
|
|
return LocaleKeys.board_menuName.tr();
|
|
|
|
case ViewLayoutPB.Document:
|
|
|
|
return LocaleKeys.document_menuName.tr();
|
|
|
|
case ViewLayoutPB.Calendar:
|
|
|
|
return LocaleKeys.calendar_menuName.tr();
|
|
|
|
default:
|
|
|
|
throw UnsupportedError('Unsupported layout: $this');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
String get referencedMenuName {
|
|
|
|
switch (this) {
|
|
|
|
case ViewLayoutPB.Grid:
|
|
|
|
return LocaleKeys.document_plugins_referencedGrid.tr();
|
|
|
|
case ViewLayoutPB.Board:
|
|
|
|
return LocaleKeys.document_plugins_referencedBoard.tr();
|
|
|
|
case ViewLayoutPB.Calendar:
|
|
|
|
return LocaleKeys.document_plugins_referencedCalendar.tr();
|
|
|
|
default:
|
|
|
|
throw UnsupportedError('Unsupported layout: $this');
|
|
|
|
}
|
2023-06-11 14:19:44 +08:00
|
|
|
}
|
2022-12-20 11:14:42 +08:00
|
|
|
}
|