Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support editor to show workspace view overview #4629

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
dd65f58
feat: adds workspace overview block component to display folder struc…
Jayaprakash-dev Feb 7, 2024
2af2948
feat: adds workspace overview bloc to manage the state of workspace o…
Jayaprakash-dev Feb 7, 2024
f048cde
feat: adds workspace overview listener
Jayaprakash-dev Feb 7, 2024
1e5b1c9
feat: adds events and notification events related to overview block i…
Jayaprakash-dev Feb 7, 2024
c1c2942
feat: adds placeholder in the locale translation
Jayaprakash-dev Feb 7, 2024
4e57891
feat: Update backend code for overview block event and notification e…
Jayaprakash-dev Feb 7, 2024
5b2c3c9
feat: support retrieving the entire hierarchical view of view child v…
Jayaprakash-dev Feb 7, 2024
8b6bc61
feat: adds custom style and configuration for overview block component
Jayaprakash-dev Feb 7, 2024
a38c08c
test: adds test for workspace overview block component
Jayaprakash-dev Feb 7, 2024
09084cb
refactor: fix syntax error by adding missing semicolon
Jayaprakash-dev Feb 7, 2024
3924fdf
feat: adds expansion functionality to the overview block
Jayaprakash-dev Feb 7, 2024
9174705
test: adds test for overview block expansion view and navigation
Jayaprakash-dev Feb 7, 2024
a9906e1
fix: updates workspace overview parent view item
Jayaprakash-dev Feb 7, 2024
ddb2685
fix: workspace overview parent view item update bug
Jayaprakash-dev Feb 7, 2024
6363ac1
test: add test for updating overview block parent view
Jayaprakash-dev Feb 7, 2024
165df67
refactor: proper error propagation
Jayaprakash-dev Feb 7, 2024
5756c36
refactor: removed redundant code lines
Jayaprakash-dev Feb 7, 2024
aa672c4
refactor: removes unwanted white spaces
Jayaprakash-dev Feb 7, 2024
5e85e06
fix: adds target arch condition for `BoxFuture` type
Jayaprakash-dev Feb 7, 2024
01bdfa2
refactor: formatted rust code using clippy
Jayaprakash-dev Feb 7, 2024
2de9236
ci: trigger github workflow actions
Jayaprakash-dev Feb 8, 2024
bbce138
fix: resolves merge conflicts with base branch
Jayaprakash-dev Feb 8, 2024
da15edf
chore: update error message
Jayaprakash-dev Feb 9, 2024
efd1379
chore: update test description
Jayaprakash-dev Feb 9, 2024
ca99acd
ci: trigger github workflow actions
Jayaprakash-dev Feb 9, 2024
9338729
ci: trigger github actions
Jayaprakash-dev Feb 10, 2024
a224372
fix: cargo fmt
Jayaprakash-dev Feb 10, 2024
d95c908
fix: update `WorkspaceOverviewListenerIdManager` drop method
Jayaprakash-dev Feb 10, 2024
4657f36
fix: update `WorkspaceOverviewListenerIdManager` drop method
Jayaprakash-dev Feb 11, 2024
703b10a
ci: trigger github actions
Jayaprakash-dev Feb 19, 2024
eba4c8f
chore: refactor code
Jayaprakash-dev Feb 22, 2024
e7ac57a
chore: refactor code
Jayaprakash-dev Feb 22, 2024
28d1f18
chore: refactor code
Jayaprakash-dev Feb 23, 2024
58234b9
refactor: refactor `Either` to `FlowyResult`
Jayaprakash-dev Feb 27, 2024
e358aea
fix: resolves merge conflicts with base branch
Jayaprakash-dev Mar 5, 2024
a09cfd0
fix: resolves merge conflicts with base branch
Jayaprakash-dev Mar 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import 'document_with_inline_page_test.dart' as document_with_inline_page_test;
import 'document_with_outline_block_test.dart' as document_with_outline_block;
import 'document_with_toggle_list_test.dart' as document_with_toggle_list_test;
import 'edit_document_test.dart' as document_edit_test;
import 'document_with_overview_block_test.dart' as document_with_overview_block_test;
import 'document_inline_page_reference_test.dart'
as document_inline_page_reference_test;

Expand All @@ -38,4 +39,5 @@ void startTesting() {
document_option_action_test.main();
document_with_image_block_test.main();
document_inline_page_reference_test.main();
document_with_overview_block_test.main();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
import 'dart:core';

import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/overview/workspace_overview_block_component.dart';
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

import '../../shared/util.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
const String firstLevelParentViewName = 'Overview Test';
const emoji = '😁';

group("Doc workspace overview block test: ", () {
testWidgets('insert an overview block widget', (tester) async {
await initializeEditorAndInsertOverviewBlock(tester);

/// validate the [WorkspaceOverviewBlockWidget] component is inserted
expect(find.byType(WorkspaceOverviewBlockWidget), findsOneWidget);

// expect to find "Workspace Overview" title placeholder under the [WorkspaceOverviewBlockWidget] component
expect(
find.descendant(
of: find.byType(WorkspaceOverviewBlockWidget),
matching: find
.text(LocaleKeys.document_selectionMenu_workspaceOverview.tr()),
),
findsOneWidget,
);

/// expect to find `Getting Started` view name under the [WorkspaceOverviewBlockWidget] component
expect(
find.descendant(
of: find.byType(WorkspaceOverviewBlockWidget),
matching: find.text(gettingStarted),
),
findsOneWidget,
);
});

testWidgets('update parent view',
(tester) async {
const String viewName = '$gettingStarted View';
await initializeEditorAndInsertOverviewBlock(tester);

await tester.hoverOnPageName(gettingStarted);
await tester.renamePage(viewName);
await tester.pumpAndSettle();

// expect parent view name to be updated
expect(
find.descendant(
of: find.byType(WorkspaceOverviewBlockWidget),
matching: find.text(viewName),
),
findsOne,
);

await tester.updatePageIconInSidebarByName(
name: viewName,
parentName: viewName,
layout: ViewLayoutPB.Document,
icon: emoji,
);
await tester.pumpAndSettle();

// expect parent view icon to be updated
expect(
find.descendant(
of: find.byType(WorkspaceOverviewBlockWidget),
matching: find.text(emoji, findRichText: true),
),
findsOne,
);
});

testWidgets(
'update child views',
(tester) async {
await initializeEditorAndInsertOverviewBlock(tester);
// validate the overview is inserted
expect(find.byType(WorkspaceOverviewBlockWidget), findsOneWidget);

await tester.createNewPageWithNameUnderParent(
name: firstLevelParentViewName,
);

/// inserting nested view pages under the [firstLevelParentView] of `Getting Started` doc page
final viewsUnderFirstLvlParent =
[1, 2].map((e) => 'Document View $e').toList();
await buildViewItems(
tester,
viewsUnderFirstLvlParent,
parentName: firstLevelParentViewName,
);

/// inserting views under the `Getting Started` doc page
final firstLevelViewNames =
[2, 3].map((e) => 'Sub-Doc View $e').toList();
await buildViewItems(tester, firstLevelViewNames);

// navigating to `Getting Started` doc page
await tester.openPage(gettingStarted);

/// expect all views to be present under the first-level parent view of `Getting Started` doc page
checkOverviewBlockComponentChildItems(tester, viewsUnderFirstLvlParent);

/// expect all views to be present under the `Getting Started` doc page
checkOverviewBlockComponentChildItems(tester, firstLevelViewNames);

/// deletes the first-level child of the `Getting Started` page
await tester.hoverOnPageName(
firstLevelViewNames[firstLevelViewNames.length - 1],
);
await tester.tapDeletePageButton();

/// deletes the first-level child of the `Getting Started` page's child view
await tester.hoverOnPageName(
viewsUnderFirstLvlParent[viewsUnderFirstLvlParent.length - 1],
);
await tester.tapDeletePageButton();

// checks whether the deleted views were not visible in the overview block
expect(
find.descendant(
of: find.byType(WorkspaceOverviewBlockWidget),
matching:
find.text(firstLevelViewNames[firstLevelViewNames.length - 1]),
),
findsNothing,
);
expect(
find.descendant(
of: find.byType(WorkspaceOverviewBlockWidget),
matching: find.text(
viewsUnderFirstLvlParent[viewsUnderFirstLvlParent.length - 1],
),
),
findsNothing,
);

await tester.hoverOnPageName(firstLevelParentViewName);
await tester.renamePage('View 1');

// expect the name of the first-level view to be changed
expect(
find.descendant(
of: find.byType(WorkspaceOverviewBlockWidget),
matching: find.text('View 1'),
),
findsOneWidget,
);

await tester.updatePageIconInSidebarByName(
name: gettingStarted,
parentName: gettingStarted,
layout: ViewLayoutPB.Document,
icon: emoji,
);

expect(
find.descendant(
of: find.byType(WorkspaceOverviewBlockWidget),
matching: find.text(emoji, findRichText: true),
),
findsOne,
);
},
);

testWidgets('expansion test', (tester) async {
await initializeEditorAndInsertOverviewBlock(tester);

/// validate the [WorkspaceOverviewBlockWidget] component is inserted
expect(find.byType(WorkspaceOverviewBlockWidget), findsOneWidget);

// expect to find [WorkspaceOverviewBlockWidget] expanded
expect(find.byType(OverviewItemWidget).hitTestable(), findsOneWidget);

await tester.tapButton(
find.byKey(
const Key("OverviewBlockExpansionIcon"),
),
);
await tester.pumpAndSettle();

// expect to find [WorkspaceOverviewBlockWidget] collapsed
expect(find.byType(OverviewItemWidget).hitTestable(), findsNothing);
});

testWidgets('navigating to the selected page view item from overview block',
(tester) async {
await initializeEditorAndInsertOverviewBlock(tester);

/// validate the [WorkspaceOverviewBlockWidget] component is inserted
expect(find.byType(WorkspaceOverviewBlockWidget), findsOneWidget);

/// inserting views under the `Getting Started` doc page
final views = [1, 2].map((e) => 'Document View $e').toList();
await buildViewItems(tester, views);

// navigating to `Getting Started` doc page
await tester.openPage(gettingStarted);

// navigating to `Document View 1` doc page
await tester.tap(
find.descendant(
of: find.byType(WorkspaceOverviewBlockWidget),
matching: find.text(views[0]),
),
);
await tester.pumpAndSettle();

// expected to be at `Document View 1` doc page
expect(
find.descendant(
of: find.byType(HomeTopBar),
matching: find.text(views[0]),
),
findsOne,
);

// navigating to `Getting Started` doc page
await tester.openPage(gettingStarted);

// navigating to `Document View 2` doc page
await tester.tap(
find.descendant(
of: find.byType(WorkspaceOverviewBlockWidget),
matching: find.text(views[1]),
),
);
await tester.pumpAndSettle();

// navigating to `Document View 2` doc page
expect(
find.descendant(
of: find.byType(HomeTopBar),
matching: find.text(views[1]),
),
findsOne,
);
});
});
}

/// Inserts an [WorkspaceOverviewBlockWidget] component in the document page
Future<void> insertWorkspaceOverviewInDocument(WidgetTester tester) async {
// open the actions menu and insert the overview block component
await tester.editor.showSlashMenu();
await tester.editor.tapSlashMenuItemWithName(
LocaleKeys.document_selectionMenu_workspaceOverview.tr(),
);
await tester.pumpAndSettle();
}

Future<void> buildViewItems(
WidgetTester tester,
List<String> views, {
String parentName = gettingStarted,
}) async {
for (final String view in views) {
await tester.createNewPageWithNameUnderParent(
name: view,
parentName: parentName,
);
}
}

void checkOverviewBlockComponentChildItems(
WidgetTester tester,
List<String> views,
) {
for (final view in views) {
expect(
find.descendant(
of: find.byType(WorkspaceOverviewBlockWidget),
matching: find.text(view),
),
findsOneWidget,
);
}
}

Future<void> initializeEditorAndInsertOverviewBlock(WidgetTester tester) async {
await tester.initializeAppFlowy();
await tester.tapGoButton();

await tester.editor.tapLineOfEditorAt(0);
await insertWorkspaceOverviewInDocument(tester);

await tester.pumpAndSettle();
}
Loading
Loading