瀏覽代碼

test: add integration test

Lucas.Xu 1 年之前
父節點
當前提交
8b4d1868e5

+ 22 - 0
frontend/appflowy_flutter/assets/test/workspaces/markdowns/test1.md

@@ -0,0 +1,22 @@
+# Welcome to AppFlowy!
+
+## Here are the basics
+
+- [ ] Click anywhere and just start typing.
+- [ ] Highlight any text, and use the editing menu to _style_ **your** <u>writing</u> `however` you ~~like.~~
+- [ ] As soon as you type /a menu will pop up. Select different types of content blocks you can add.
+- [ ] Type `/` followed by `/bullet` or `/num` to create a list.
+- [x] Click `+ New Page `button at the bottom of your sidebar to add a new page.
+- [ ] Click `+` next to any page title in the sidebar to quickly add a new subpage, `Document`, `Grid`, or `Kanban Board`.
+
+---
+
+## Keyboard shortcuts, markdown, and code block
+
+1. Keyboard shortcuts [guide](https://appflowy.gitbook.io/docs/essential-documentation/shortcuts)
+1. Markdown [reference](https://appflowy.gitbook.io/docs/essential-documentation/markdown)
+1. Type `/code` to insert a code block
+
+## Have a question❓
+
+> Click `?` at the bottom right for help and support.

+ 1 - 0
frontend/appflowy_flutter/assets/test/workspaces/markdowns/test2.md

@@ -0,0 +1 @@
+# test

+ 6 - 0
frontend/appflowy_flutter/assets/translations/en.json

@@ -51,6 +51,12 @@
     "import": "Import",
     "moreOptions": "More options"
   },
+  "importPanel": {
+    "textAndMarkdown": "Text & Markdown",
+    "documentFromV010": "Document from v0.1.0",
+    "databaseFromV010": "Database from v0.1.0",
+    "csv": "CSV"
+  },
   "disclosureAction": {
     "rename": "Rename",
     "delete": "Delete",

+ 60 - 0
frontend/appflowy_flutter/integration_test/import_files_test.dart

@@ -0,0 +1,60 @@
+import 'dart:io';
+
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+
+import 'util/mock/mock_file_picker.dart';
+import 'util/util.dart';
+import 'package:path/path.dart' as p;
+
+void main() {
+  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+  group('import files', () {
+    const location = 'import_files';
+
+    setUp(() async {
+      await TestFolder.cleanTestLocation(location);
+      await TestFolder.setTestLocation(location);
+    });
+
+    tearDown(() async {
+      await TestFolder.cleanTestLocation(location);
+    });
+
+    tearDownAll(() async {
+      await TestFolder.cleanTestLocation(null);
+    });
+
+    testWidgets('import multiple markdown files', (tester) async {
+      await tester.initializeAppFlowy();
+      await tester.tapGoButton();
+
+      // expect to see a readme page
+      tester.expectToSeePageName(readme);
+
+      await tester.tapAddButton();
+      await tester.tapImportButton();
+
+      final testFileNames = ['test1.md', 'test2.md'];
+      final fileLocation = await tester.currentFileLocation();
+      for (final fileName in testFileNames) {
+        final str = await rootBundle.loadString(
+          p.join(
+            'assets/test/workspaces/markdowns',
+            fileName,
+          ),
+        );
+        File(p.join(fileLocation, fileName)).writeAsStringSync(str);
+      }
+      // mock get files
+      await mockPickFilePaths(testFileNames, name: location);
+
+      await tester.tapTextAndMarkdownButton();
+
+      tester.expectToSeePageName('test1');
+      tester.expectToSeePageName('test2');
+    });
+  });
+}

+ 4 - 0
frontend/appflowy_flutter/integration_test/runner.dart

@@ -3,6 +3,8 @@ import 'package:integration_test/integration_test.dart';
 import 'switch_folder_test.dart' as switch_folder_test;
 import 'document_test.dart' as document_test;
 import 'cover_image_test.dart' as cover_image_test;
+import 'share_markdown_test.dart' as share_markdown_test;
+import 'import_files_test.dart' as import_files_test;
 
 /// The main task runner for all integration tests in AppFlowy.
 ///
@@ -16,6 +18,8 @@ void main() {
   switch_folder_test.main();
   cover_image_test.main();
   document_test.main();
+  share_markdown_test.main();
+  import_files_test.main();
   // board_test.main();
   // empty_document_test.main();
   // smart_menu_test.main();

+ 11 - 1
frontend/appflowy_flutter/integration_test/util/base.dart

@@ -3,6 +3,7 @@ import 'dart:io';
 import 'package:appflowy/core/config/kv_keys.dart';
 import 'package:appflowy/main.dart' as app;
 import 'package:appflowy/startup/tasks/prelude.dart';
+import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flutter/gestures.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
@@ -91,7 +92,16 @@ extension AppFlowyTestBase on WidgetTester {
     String tr, {
     int milliseconds = 500,
   }) async {
-    final button = find.text(tr, findRichText: true);
+    Finder button = find.text(
+      tr,
+      findRichText: true,
+      skipOffstage: false,
+    );
+    if (button.evaluate().isEmpty) {
+      button = find.byWidgetPredicate(
+        (widget) => widget is FlowyText && widget.title == tr,
+      );
+    }
     await tapButton(
       button,
       milliseconds: milliseconds,

+ 12 - 0
frontend/appflowy_flutter/integration_test/util/common_operations.dart

@@ -19,6 +19,10 @@ import 'base.dart';
 const String readme = 'Read me';
 
 extension CommonOperations on WidgetTester {
+  Future<String> currentFileLocation() async {
+    return TestFolder.currentLocation();
+  }
+
   Future<void> tapGoButton() async {
     final goButton = find.byType(GoButton);
     await tapButton(goButton);
@@ -42,6 +46,14 @@ extension CommonOperations on WidgetTester {
     await tapButtonWithName(LocaleKeys.document_menuName.tr());
   }
 
+  Future<void> tapImportButton() async {
+    await tapButtonWithName(LocaleKeys.moreAction_import.tr());
+  }
+
+  Future<void> tapTextAndMarkdownButton() async {
+    await tapButtonWithName(LocaleKeys.importPanel_textAndMarkdown.tr());
+  }
+
   Finder findPageName(String name) {
     return find.byWidgetPredicate(
       (widget) => widget is ViewSectionItem && widget.view.name == name,

+ 35 - 3
frontend/appflowy_flutter/integration_test/util/mock/mock_file_picker.dart

@@ -1,15 +1,19 @@
+import 'dart:io';
+
 import 'package:appflowy/startup/startup.dart';
 import 'package:appflowy/util/file_picker/file_picker_service.dart';
-import 'package:file_picker/src/file_picker.dart' as fp;
+import 'package:file_picker/file_picker.dart' as fp;
 import 'package:path/path.dart' as p;
 import '../util.dart';
 
 class MockFilePicker implements FilePickerService {
   MockFilePicker({
-    required this.mockPath,
+    this.mockPath = '',
+    this.mockPaths = const [],
   });
 
   final String mockPath;
+  final List<String> mockPaths;
 
   @override
   Future<String?> getDirectoryPath({String? title}) {
@@ -41,7 +45,14 @@ class MockFilePicker implements FilePickerService {
     bool withReadStream = false,
     bool lockParentWindow = false,
   }) {
-    throw UnimplementedError();
+    final platformFiles = mockPaths
+        .map((e) => fp.PlatformFile(path: e, name: '', size: 0))
+        .toList();
+    return Future.value(
+      FilePickerResult(
+        platformFiles,
+      ),
+    );
   }
 }
 
@@ -67,3 +78,24 @@ Future<String> mockSaveFilePath(String? name, String fileName) async {
   );
   return path;
 }
+
+Future<List<String>> mockPickFilePaths(
+  List<String> fileNames, {
+  String? name,
+  String? customPath,
+}) async {
+  late final Directory dir;
+  if (customPath != null) {
+    dir = Directory(customPath);
+  } else {
+    dir = await TestFolder.testLocation(name);
+  }
+  final paths = fileNames.map((e) => p.join(dir.path, e)).toList();
+  getIt.unregister<FilePickerService>();
+  getIt.registerFactory<FilePickerService>(
+    () => MockFilePicker(
+      mockPaths: paths,
+    ),
+  );
+  return paths;
+}

+ 6 - 4
frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/import/import_type.dart

@@ -1,3 +1,5 @@
+import 'package:appflowy/generated/locale_keys.g.dart';
+import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flutter/material.dart';
 
@@ -11,13 +13,13 @@ enum ImportType {
   String toString() {
     switch (this) {
       case ImportType.historyDocument:
-        return 'Document from v0.1';
+        return LocaleKeys.importPanel_documentFromV010.tr();
       case ImportType.historyDatabase:
-        return 'Database from v0.1';
+        return LocaleKeys.importPanel_databaseFromV010.tr();
       case ImportType.markdownOrText:
-        return 'Text & Markdown';
+        return LocaleKeys.importPanel_textAndMarkdown.tr();
       case ImportType.databaseCSV:
-        return 'CSV';
+        return LocaleKeys.importPanel_csv.tr();
     }
   }
 

+ 1 - 0
frontend/appflowy_flutter/pubspec.yaml

@@ -181,4 +181,5 @@ flutter:
     # BEGIN: EXCLUDE_IN_RELEASE
     - assets/test/workspaces/
     - assets/template/
+    - assets/test/workspaces/markdowns/
     # END: EXCLUDE_IN_RELEASE