mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-07-09 01:56:08 +00:00

* chore: create orphan view handler * feat: save icon url and cover url in view * feat: implement emoji picker UI * chore: config ui * chore: config ui again * chore: replace RowPB with RowMetaPB to exposing more row information * fix: compile error * feat: show emoji in row * chore: update * test: insert emoji test * test: add update emoji test * test: add remove emoji test * test: add create field tests * test: add create row and delete row integration tests * test: add create row from row menu * test: document in row detail page * test: delete, duplicate row in row detail page * test: check the row count displayed in grid page * test: rename existing field in grid page * test: update field type of exisiting field in grid page * test: delete field test * test: add duplicate field test * test: add hide field test * test: add edit text cell test * test: add insert text to text cell test * test: add edit number cell test * test: add edit multiple number cells * test: add edit checkbox cell test * feat: integrate editor into database row * test: add edit create time and last edit time cell test * test: add edit date cell by selecting a date test * chore: remove unused code * chore: update checklist bg color * test: add update database layout test --------- Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
222 lines
6.5 KiB
Dart
222 lines
6.5 KiB
Dart
import 'dart:ui';
|
|
import 'package:appflowy_backend/log.dart';
|
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
|
|
|
import 'package:appflowy/plugins/document/presentation/share/share_button.dart';
|
|
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';
|
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_language_view.dart';
|
|
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flowy_infra_ui/widget/buttons/primary_button.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'util.dart';
|
|
|
|
extension CommonOperations on WidgetTester {
|
|
/// Get current file location of AppFlowy.
|
|
Future<String> currentFileLocation() async {
|
|
return TestFolder.currentLocation();
|
|
}
|
|
|
|
/// Tap the GetStart button on the launch page.
|
|
Future<void> tapGoButton() async {
|
|
final goButton = find.byType(GoButton);
|
|
await tapButton(goButton);
|
|
}
|
|
|
|
/// Tap the + button on the home page.
|
|
Future<void> tapAddButton() async {
|
|
final addButton = find.byType(AddButton);
|
|
await tapButton(addButton);
|
|
}
|
|
|
|
/// Tap the create document button.
|
|
///
|
|
/// Must call [tapAddButton] first.
|
|
Future<void> tapCreateDocumentButton() async {
|
|
await tapButtonWithName(LocaleKeys.document_menuName.tr());
|
|
}
|
|
|
|
/// Tap the create grid button.
|
|
///
|
|
/// Must call [tapAddButton] first.
|
|
Future<void> tapCreateGridButton() async {
|
|
await tapButtonWithName(LocaleKeys.grid_menuName.tr());
|
|
}
|
|
|
|
/// Tap the import button.
|
|
///
|
|
/// Must call [tapAddButton] first.
|
|
Future<void> tapImportButton() async {
|
|
await tapButtonWithName(LocaleKeys.moreAction_import.tr());
|
|
}
|
|
|
|
/// Tap the import from text & markdown button.
|
|
///
|
|
/// Must call [tapImportButton] first.
|
|
Future<void> tapTextAndMarkdownButton() async {
|
|
await tapButtonWithName(LocaleKeys.importPanel_textAndMarkdown.tr());
|
|
}
|
|
|
|
/// 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');
|
|
}
|
|
}
|
|
|
|
/// Hover on the widget.
|
|
Future<void> hoverOnWidget(
|
|
Finder finder, {
|
|
Offset? offset,
|
|
}) async {
|
|
try {
|
|
final gesture = await createGesture(kind: PointerDeviceKind.mouse);
|
|
await gesture.addPointer(location: Offset.zero);
|
|
addTearDown(gesture.removePointer);
|
|
await pump();
|
|
await gesture.moveTo(offset ?? getCenter(finder));
|
|
await pumpAndSettle();
|
|
} catch (_) {}
|
|
}
|
|
|
|
/// Hover on the page name.
|
|
Future<void> hoverOnPageName(String name) async {
|
|
await hoverOnWidget(findPageName(name));
|
|
}
|
|
|
|
/// Tap the ... button beside the page name.
|
|
///
|
|
/// Must call [hoverOnPageName] first.
|
|
Future<void> tapPageOptionButton() async {
|
|
final optionButton = find.byType(ViewDisclosureButton);
|
|
await tapButton(optionButton);
|
|
}
|
|
|
|
/// Tap the delete page button.
|
|
///
|
|
/// Must call [tapPageOptionButton] first.
|
|
Future<void> tapDeletePageButton() async {
|
|
await tapPageOptionButton();
|
|
await tapButtonWithName(ViewDisclosureAction.delete.name);
|
|
}
|
|
|
|
/// Tap the rename page button.
|
|
///
|
|
/// Must call [tapPageOptionButton] first.
|
|
Future<void> tapRenamePageButton() async {
|
|
await tapPageOptionButton();
|
|
await tapButtonWithName(ViewDisclosureAction.rename.name);
|
|
}
|
|
|
|
/// Rename the page.
|
|
///
|
|
/// Must call [tapPageOptionButton] first.
|
|
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);
|
|
}
|
|
|
|
/// Tap the restore button.
|
|
///
|
|
/// the restore button will show after the current page is deleted.
|
|
Future<void> tapRestoreButton() async {
|
|
final restoreButton = find.textContaining(
|
|
LocaleKeys.deletePagePrompt_restore.tr(),
|
|
);
|
|
await tapButton(restoreButton);
|
|
}
|
|
|
|
/// Tap the delete permanently button.
|
|
///
|
|
/// the restore button will show after the current page is deleted.
|
|
Future<void> tapDeletePermanentlyButton() async {
|
|
final restoreButton = find.textContaining(
|
|
LocaleKeys.deletePagePrompt_deletePermanent.tr(),
|
|
);
|
|
await tapButton(restoreButton);
|
|
}
|
|
|
|
/// Tap the share button above the document page.
|
|
Future<void> tapShareButton() async {
|
|
final shareButton = find.byWidgetPredicate(
|
|
(widget) => widget is DocumentShareButton,
|
|
);
|
|
await tapButton(shareButton);
|
|
}
|
|
|
|
/// Tap the export markdown button
|
|
///
|
|
/// Must call [tapShareButton] first.
|
|
Future<void> tapMarkdownButton() async {
|
|
final markdownButton = find.textContaining(
|
|
LocaleKeys.shareAction_markdown.tr(),
|
|
);
|
|
await tapButton(markdownButton);
|
|
}
|
|
|
|
/// Hover on cover plugin button above the document
|
|
Future<void> hoverOnCoverPluginAddButton() async {
|
|
final editor = find.byWidgetPredicate(
|
|
(widget) => widget is AppFlowyEditor,
|
|
);
|
|
await hoverOnWidget(
|
|
editor,
|
|
offset: getTopLeft(editor).translate(20, 20),
|
|
);
|
|
}
|
|
}
|