diff --git a/frontend/appflowy_flutter/assets/test/workspaces/markdowns/test1.md b/frontend/appflowy_flutter/assets/test/workspaces/markdowns/test1.md
new file mode 100644
index 0000000000..47d854f6ef
--- /dev/null
+++ b/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** writing `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.
diff --git a/frontend/appflowy_flutter/assets/test/workspaces/markdowns/test2.md b/frontend/appflowy_flutter/assets/test/workspaces/markdowns/test2.md
new file mode 100644
index 0000000000..83c831f0b0
--- /dev/null
+++ b/frontend/appflowy_flutter/assets/test/workspaces/markdowns/test2.md
@@ -0,0 +1 @@
+# test
diff --git a/frontend/appflowy_flutter/assets/translations/en.json b/frontend/appflowy_flutter/assets/translations/en.json
index de558f56a1..e408557310 100644
--- a/frontend/appflowy_flutter/assets/translations/en.json
+++ b/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",
diff --git a/frontend/appflowy_flutter/integration_test/import_files_test.dart b/frontend/appflowy_flutter/integration_test/import_files_test.dart
new file mode 100644
index 0000000000..5743e01f76
--- /dev/null
+++ b/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');
+ });
+ });
+}
diff --git a/frontend/appflowy_flutter/integration_test/runner.dart b/frontend/appflowy_flutter/integration_test/runner.dart
index 6547e795fa..6ee18f424d 100644
--- a/frontend/appflowy_flutter/integration_test/runner.dart
+++ b/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();
diff --git a/frontend/appflowy_flutter/integration_test/util/base.dart b/frontend/appflowy_flutter/integration_test/util/base.dart
index be426a61c3..2cc483138c 100644
--- a/frontend/appflowy_flutter/integration_test/util/base.dart
+++ b/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,
diff --git a/frontend/appflowy_flutter/integration_test/util/common_operations.dart b/frontend/appflowy_flutter/integration_test/util/common_operations.dart
index 585a40cd60..ba7055cc40 100644
--- a/frontend/appflowy_flutter/integration_test/util/common_operations.dart
+++ b/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 currentFileLocation() async {
+ return TestFolder.currentLocation();
+ }
+
Future 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 tapImportButton() async {
+ await tapButtonWithName(LocaleKeys.moreAction_import.tr());
+ }
+
+ Future tapTextAndMarkdownButton() async {
+ await tapButtonWithName(LocaleKeys.importPanel_textAndMarkdown.tr());
+ }
+
Finder findPageName(String name) {
return find.byWidgetPredicate(
(widget) => widget is ViewSectionItem && widget.view.name == name,
diff --git a/frontend/appflowy_flutter/integration_test/util/mock/mock_file_picker.dart b/frontend/appflowy_flutter/integration_test/util/mock/mock_file_picker.dart
index 4ebb2d66a0..390d77d194 100644
--- a/frontend/appflowy_flutter/integration_test/util/mock/mock_file_picker.dart
+++ b/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 mockPaths;
@override
Future 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 mockSaveFilePath(String? name, String fileName) async {
);
return path;
}
+
+Future> mockPickFilePaths(
+ List 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();
+ getIt.registerFactory(
+ () => MockFilePicker(
+ mockPaths: paths,
+ ),
+ );
+ return paths;
+}
diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/import/import_type.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/import/import_type.dart
index 086eee1c86..a51892dd0e 100644
--- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/import/import_type.dart
+++ b/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();
}
}
diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml
index 0f0f41ed5b..b05b57af95 100644
--- a/frontend/appflowy_flutter/pubspec.yaml
+++ b/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