You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by pa...@apache.org on 2022/10/18 16:31:05 UTC
[beam] branch master updated: [Playground][Frontend] Tags filter for Examples Catalog (#22074) (#23532)
This is an automated email from the ASF dual-hosted git repository.
pabloem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git
The following commit(s) were added to refs/heads/master by this push:
new 2e2bb66f82a [Playground][Frontend] Tags filter for Examples Catalog (#22074) (#23532)
2e2bb66f82a is described below
commit 2e2bb66f82a0d9013283b838fae8b118a1e2c652
Author: Darkhan Nausharipov <31...@users.noreply.github.com>
AuthorDate: Tue Oct 18 22:30:54 2022 +0600
[Playground][Frontend] Tags filter for Examples Catalog (#22074) (#23532)
* [Playground] Tags filter for Examples Catalog (#22074)
* addressing review comments (1)(#22074)
Co-authored-by: darkhan.nausharipov <da...@kzn.akvelon.com>
Co-authored-by: Alexey Inkin <le...@inkin.ru>
---
.../examples/components/examples_components.dart | 5 +-
.../modules/examples/components/filter/filter.dart | 97 ++++++++++++++++++++
.../{category_bubble.dart => tag_bubble.dart} | 16 ++--
.../{category_bubble.dart => type_bubble.dart} | 6 +-
.../examples/components/filter/type_filter.dart | 59 ------------
.../components/search_field/search_field.dart | 6 +-
.../lib/modules/examples/example_selector.dart | 2 +-
.../playground/states/example_selector_state.dart | 101 ++++++++++++++-------
.../lib/src/cache/example_cache.dart | 1 +
.../example_loaders/content_example_loader.dart | 11 ++-
.../example_loaders/empty_example_loader.dart | 1 +
.../lib/src/models/example.dart | 2 +
.../lib/src/models/example_base.dart | 2 +
.../example_client/grpc_example_client.dart | 1 +
.../test/src/common/categories.dart | 20 ++--
.../test/src/common/examples.dart | 7 +-
.../states/example_selector_state_test.dart | 56 +++++++++---
17 files changed, 255 insertions(+), 138 deletions(-)
diff --git a/playground/frontend/lib/modules/examples/components/examples_components.dart b/playground/frontend/lib/modules/examples/components/examples_components.dart
index cd7ac4ad4f7..c25c30a63e0 100644
--- a/playground/frontend/lib/modules/examples/components/examples_components.dart
+++ b/playground/frontend/lib/modules/examples/components/examples_components.dart
@@ -18,6 +18,7 @@
export 'package:playground/modules/examples/components/example_list/category_expansion_panel.dart';
export 'package:playground/modules/examples/components/example_list/example_list.dart';
-export 'package:playground/modules/examples/components/filter/category_bubble.dart';
-export 'package:playground/modules/examples/components/filter/type_filter.dart';
+export 'package:playground/modules/examples/components/filter/tag_bubble.dart';
+export 'package:playground/modules/examples/components/filter/type_bubble.dart';
+export 'package:playground/modules/examples/components/filter/filter.dart';
export 'package:playground/modules/examples/components/search_field/search_field.dart';
diff --git a/playground/frontend/lib/modules/examples/components/filter/filter.dart b/playground/frontend/lib/modules/examples/components/filter/filter.dart
new file mode 100644
index 00000000000..56fa6956abe
--- /dev/null
+++ b/playground/frontend/lib/modules/examples/components/filter/filter.dart
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:flutter/material.dart';
+import 'package:playground/constants/sizes.dart';
+import 'package:playground/modules/examples/components/examples_components.dart';
+import 'package:playground/pages/playground/states/example_selector_state.dart';
+import 'package:playground_components/playground_components.dart';
+import 'package:provider/provider.dart';
+
+class ExamplesFilter extends StatelessWidget {
+ const ExamplesFilter({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.symmetric(
+ horizontal: kLgSpacing,
+ vertical: kMdSpacing,
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: const [
+ _Types(),
+ _Tags(),
+ ],
+ ),
+ );
+ }
+}
+
+class _Types extends StatelessWidget {
+ const _Types();
+
+ @override
+ Widget build(BuildContext context) {
+ AppLocalizations appLocale = AppLocalizations.of(context)!;
+
+ return Row(
+ children: [
+ TypeBubble(
+ type: ExampleType.all,
+ name: appLocale.all,
+ ),
+ TypeBubble(
+ type: ExampleType.example,
+ name: appLocale.examples,
+ ),
+ TypeBubble(
+ type: ExampleType.kata,
+ name: appLocale.katas,
+ ),
+ TypeBubble(
+ type: ExampleType.test,
+ name: appLocale.unitTests,
+ ),
+ ],
+ );
+ }
+}
+
+class _Tags extends StatelessWidget {
+ const _Tags();
+
+ @override
+ Widget build(BuildContext context) {
+ return Consumer<ExampleSelectorState>(
+ builder: (context, state, child) => Padding(
+ padding: const EdgeInsets.symmetric(vertical: kMdSpacing),
+ child: SingleChildScrollView(
+ scrollDirection: Axis.horizontal,
+ child: Row(
+ children: state.tags
+ .map((tag) => TagBubble(name: tag))
+ .toList(growable: false),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/playground/frontend/lib/modules/examples/components/filter/category_bubble.dart b/playground/frontend/lib/modules/examples/components/filter/tag_bubble.dart
similarity index 82%
copy from playground/frontend/lib/modules/examples/components/filter/category_bubble.dart
copy to playground/frontend/lib/modules/examples/components/filter/tag_bubble.dart
index 849f19db877..f4768e0c533 100644
--- a/playground/frontend/lib/modules/examples/components/filter/category_bubble.dart
+++ b/playground/frontend/lib/modules/examples/components/filter/tag_bubble.dart
@@ -21,13 +21,11 @@ import 'package:playground/pages/playground/states/example_selector_state.dart';
import 'package:playground_components/playground_components.dart';
import 'package:provider/provider.dart';
-class CategoryBubble extends StatelessWidget {
- final ExampleType type;
+class TagBubble extends StatelessWidget {
final String name;
- const CategoryBubble({
+ const TagBubble({
Key? key,
- required this.type,
required this.name,
}) : super(key: key);
@@ -35,16 +33,18 @@ class CategoryBubble extends StatelessWidget {
Widget build(BuildContext context) {
return Consumer<ExampleSelectorState>(
builder: (context, state, child) {
- final isSelected = type == state.selectedFilterType;
+ final isSelected = state.selectedTags.contains(name);
return BubbleWidget(
isSelected: isSelected,
title: name,
onTap: () {
- if (!isSelected) {
- state.setSelectedFilterType(type);
- state.sortCategories();
+ if (isSelected) {
+ state.removeSelectedTag(name);
+ } else {
+ state.addSelectedTag(name);
}
+ state.filterCategoriesWithExamples();
},
);
},
diff --git a/playground/frontend/lib/modules/examples/components/filter/category_bubble.dart b/playground/frontend/lib/modules/examples/components/filter/type_bubble.dart
similarity index 93%
rename from playground/frontend/lib/modules/examples/components/filter/category_bubble.dart
rename to playground/frontend/lib/modules/examples/components/filter/type_bubble.dart
index 849f19db877..2925d54f336 100644
--- a/playground/frontend/lib/modules/examples/components/filter/category_bubble.dart
+++ b/playground/frontend/lib/modules/examples/components/filter/type_bubble.dart
@@ -21,11 +21,11 @@ import 'package:playground/pages/playground/states/example_selector_state.dart';
import 'package:playground_components/playground_components.dart';
import 'package:provider/provider.dart';
-class CategoryBubble extends StatelessWidget {
+class TypeBubble extends StatelessWidget {
final ExampleType type;
final String name;
- const CategoryBubble({
+ const TypeBubble({
Key? key,
required this.type,
required this.name,
@@ -43,7 +43,7 @@ class CategoryBubble extends StatelessWidget {
onTap: () {
if (!isSelected) {
state.setSelectedFilterType(type);
- state.sortCategories();
+ state.filterCategoriesWithExamples();
}
},
);
diff --git a/playground/frontend/lib/modules/examples/components/filter/type_filter.dart b/playground/frontend/lib/modules/examples/components/filter/type_filter.dart
deleted file mode 100644
index a221999f3ce..00000000000
--- a/playground/frontend/lib/modules/examples/components/filter/type_filter.dart
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import 'package:flutter/material.dart';
-import 'package:flutter_gen/gen_l10n/app_localizations.dart';
-import 'package:playground/constants/sizes.dart';
-import 'package:playground/modules/examples/components/examples_components.dart';
-import 'package:playground_components/playground_components.dart';
-
-class TypeFilter extends StatelessWidget {
- const TypeFilter({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- AppLocalizations appLocale = AppLocalizations.of(context)!;
-
- return Padding(
- padding: const EdgeInsets.symmetric(
- horizontal: kLgSpacing,
- vertical: kMdSpacing,
- ),
- child: Row(
- children: <CategoryBubble>[
- CategoryBubble(
- type: ExampleType.all,
- name: appLocale.all,
- ),
- CategoryBubble(
- type: ExampleType.example,
- name: appLocale.examples,
- ),
- CategoryBubble(
- type: ExampleType.kata,
- name: appLocale.katas,
- ),
- CategoryBubble(
- type: ExampleType.test,
- name: appLocale.unitTests,
- ),
- ],
- ),
- );
- }
-}
diff --git a/playground/frontend/lib/modules/examples/components/search_field/search_field.dart b/playground/frontend/lib/modules/examples/components/search_field/search_field.dart
index 2095dfac1d2..2ca7a354c3f 100644
--- a/playground/frontend/lib/modules/examples/components/search_field/search_field.dart
+++ b/playground/frontend/lib/modules/examples/components/search_field/search_field.dart
@@ -89,8 +89,8 @@ class SearchField extends StatelessWidget {
);
}
- _onChange(ExampleSelectorState state, String filterText) {
- state.setFilterText(filterText);
- state.sortCategories();
+ _onChange(ExampleSelectorState state, String searchText) {
+ state.setSearchText(searchText);
+ state.filterCategoriesWithExamples();
}
}
diff --git a/playground/frontend/lib/modules/examples/example_selector.dart b/playground/frontend/lib/modules/examples/example_selector.dart
index c08fdb3cea2..45b936fb9a1 100644
--- a/playground/frontend/lib/modules/examples/example_selector.dart
+++ b/playground/frontend/lib/modules/examples/example_selector.dart
@@ -190,7 +190,7 @@ class _ExampleSelectorState extends State<ExampleSelector>
return Column(
children: [
SearchField(controller: textController),
- const TypeFilter(),
+ const ExamplesFilter(),
ExampleList(
controller: scrollController,
selectedExample: playgroundController.selectedExample!,
diff --git a/playground/frontend/lib/pages/playground/states/example_selector_state.dart b/playground/frontend/lib/pages/playground/states/example_selector_state.dart
index f62a1773012..7ce9064e1b9 100644
--- a/playground/frontend/lib/pages/playground/states/example_selector_state.dart
+++ b/playground/frontend/lib/pages/playground/states/example_selector_state.dart
@@ -22,27 +22,57 @@ import 'package:playground_components/playground_components.dart';
class ExampleSelectorState with ChangeNotifier {
final PlaygroundController _playgroundController;
ExampleType _selectedFilterType;
- String _filterText;
+ String _searchText;
List<CategoryWithExamples> categories;
+ List<String> tags = [];
+ List<String> selectedTags = [];
ExampleSelectorState(
this._playgroundController,
this.categories, [
this._selectedFilterType = ExampleType.all,
- this._filterText = '',
- ]);
+ this._searchText = '',
+ ]) {
+ tags = _getTagsSortedByExampleCount(categories);
+ }
ExampleType get selectedFilterType => _selectedFilterType;
- String get filterText => _filterText;
+ String get searchText => _searchText;
void setSelectedFilterType(ExampleType type) {
_selectedFilterType = type;
notifyListeners();
}
- void setFilterText(String text) {
- _filterText = text;
+ void addSelectedTag(String tag) {
+ selectedTags.add(tag);
+ notifyListeners();
+ }
+
+ void removeSelectedTag(String tag) {
+ selectedTags.remove(tag);
+ notifyListeners();
+ }
+
+ List<String> _getTagsSortedByExampleCount(
+ List<CategoryWithExamples> categories,
+ ) {
+ Map<String, int> exampleCountByTag = {};
+ for (final category in categories) {
+ for (final example in category.examples) {
+ for (final tag in example.tags) {
+ exampleCountByTag[tag] = (exampleCountByTag[tag] ?? 0) + 1;
+ }
+ }
+ }
+ final tagEntries = exampleCountByTag.entries.toList()
+ ..sort((entry1, entry2) => entry2.value.compareTo(entry1.value));
+ return tagEntries.map((entry) => entry.key).toList();
+ }
+
+ void setSearchText(String text) {
+ _searchText = text;
notifyListeners();
}
@@ -51,56 +81,59 @@ class ExampleSelectorState with ChangeNotifier {
notifyListeners();
}
- void sortCategories() {
+ void filterCategoriesWithExamples() {
final categories = _playgroundController.exampleCache.getCategories(
_playgroundController.sdk,
);
-
- final sortedCategories = categories
+ final filteredCategories = categories
.map((category) => CategoryWithExamples(
title: category.title,
- examples: _sortCategoryExamples(category.examples)))
+ examples: _filterExamples(category.examples)))
.where((category) => category.examples.isNotEmpty)
.toList();
- setCategories(sortedCategories);
+ setCategories(filteredCategories);
+ }
+
+ List<ExampleBase> _filterExamples(List<ExampleBase> examples) {
+ final byType = filterExamplesByType(examples, selectedFilterType);
+ final byTags = filterExamplesByTags(byType);
+ final byName = filterExamplesByName(byTags);
+ return byName;
}
- List<ExampleBase> _sortCategoryExamples(List<ExampleBase> examples) {
- final isAllFilterType = selectedFilterType == ExampleType.all;
- final isFilterTextEmpty = filterText.isEmpty;
- if (isAllFilterType && isFilterTextEmpty) {
+ @visibleForTesting
+ List<ExampleBase> filterExamplesByTags(List<ExampleBase> examples) {
+ if (selectedTags.isEmpty) {
return examples;
}
- if (!isAllFilterType && isFilterTextEmpty) {
- return sortExamplesByType(
- examples,
- selectedFilterType,
- );
+ List<ExampleBase> sorted = [];
+ for (var example in examples) {
+ if (example.tags.toSet().containsAll(selectedTags)) {
+ sorted.add(example);
+ }
}
- if (isAllFilterType && !isFilterTextEmpty) {
- return sortExamplesByName(examples, filterText);
- }
- final sorted = sortExamplesByType(
- examples,
- selectedFilterType,
- );
- return sortExamplesByName(sorted, filterText);
+ return sorted;
}
- List<ExampleBase> sortExamplesByType(
+ @visibleForTesting
+ List<ExampleBase> filterExamplesByType(
List<ExampleBase> examples,
ExampleType type,
) {
+ if (type == ExampleType.all) {
+ return examples;
+ }
return examples.where((element) => element.type == type).toList();
}
- List<ExampleBase> sortExamplesByName(
- List<ExampleBase> examples,
- String name,
- ) {
+ @visibleForTesting
+ List<ExampleBase> filterExamplesByName(List<ExampleBase> examples) {
+ if (_searchText.isEmpty) {
+ return examples;
+ }
return examples
.where((example) =>
- example.name.toLowerCase().contains(name.toLowerCase()))
+ example.name.toLowerCase().contains(_searchText.toLowerCase()))
.toList();
}
}
diff --git a/playground/frontend/playground_components/lib/src/cache/example_cache.dart b/playground/frontend/playground_components/lib/src/cache/example_cache.dart
index 5e600591fe9..032d4fcbce9 100644
--- a/playground/frontend/playground_components/lib/src/cache/example_cache.dart
+++ b/playground/frontend/playground_components/lib/src/cache/example_cache.dart
@@ -114,6 +114,7 @@ class ExampleCache extends ChangeNotifier {
name: result.files.first.name,
path: id,
description: '',
+ tags: [],
type: ExampleType.example,
source: result.files.first.code,
pipelineOptions: result.pipelineOptions,
diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/content_example_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/content_example_loader.dart
index a66e9fa69ad..8196ff10b8b 100644
--- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/content_example_loader.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/content_example_loader.dart
@@ -33,13 +33,14 @@ class ContentExampleLoader extends ExampleLoader {
@override
Future<Example> get future async => Example(
- sdk: descriptor.sdk,
+ complexity: descriptor.complexity,
+ description: '',
name: descriptor.name ?? 'Embedded_Example',
path: '',
- description: '',
- type: ExampleType.example,
- source: descriptor.content,
pipelineOptions: '',
- complexity: descriptor.complexity,
+ sdk: descriptor.sdk,
+ source: descriptor.content,
+ tags: [],
+ type: ExampleType.example,
);
}
diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/empty_example_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/empty_example_loader.dart
index 0303444c76a..faef4c0098f 100644
--- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/empty_example_loader.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/empty_example_loader.dart
@@ -38,6 +38,7 @@ class EmptyExampleLoader extends ExampleLoader {
name: 'Embedded_Example',
path: '',
description: '',
+ tags: [],
type: ExampleType.example,
source: '',
pipelineOptions: '',
diff --git a/playground/frontend/playground_components/lib/src/models/example.dart b/playground/frontend/playground_components/lib/src/models/example.dart
index 2c072d100b2..2654ecb6461 100644
--- a/playground/frontend/playground_components/lib/src/models/example.dart
+++ b/playground/frontend/playground_components/lib/src/models/example.dart
@@ -27,6 +27,7 @@ class Example extends ExampleBase {
const Example({
required super.sdk,
+ required super.tags,
required super.type,
required super.name,
required super.path,
@@ -53,6 +54,7 @@ class Example extends ExampleBase {
name: example.name,
path: example.path,
description: example.description,
+ tags: example.tags,
type: example.type,
contextLine: example.contextLine,
isMultiFile: example.isMultiFile,
diff --git a/playground/frontend/playground_components/lib/src/models/example_base.dart b/playground/frontend/playground_components/lib/src/models/example_base.dart
index 10a55e1be0b..62968579b27 100644
--- a/playground/frontend/playground_components/lib/src/models/example_base.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_base.dart
@@ -49,6 +49,7 @@ extension ExampleTypeToString on ExampleType {
/// These objects are fetched as lists from [ExampleRepository].
class ExampleBase with Comparable<ExampleBase>, EquatableMixin {
final Sdk sdk;
+ final List<String> tags;
final ExampleType type;
final String name;
final String path;
@@ -64,6 +65,7 @@ class ExampleBase with Comparable<ExampleBase>, EquatableMixin {
required this.name,
required this.path,
required this.description,
+ required this.tags,
required this.type,
this.contextLine = 1,
this.isMultiFile = false,
diff --git a/playground/frontend/playground_components/lib/src/repositories/example_client/grpc_example_client.dart b/playground/frontend/playground_components/lib/src/repositories/example_client/grpc_example_client.dart
index 6292fcb77c5..db286d31593 100644
--- a/playground/frontend/playground_components/lib/src/repositories/example_client/grpc_example_client.dart
+++ b/playground/frontend/playground_components/lib/src/repositories/example_client/grpc_example_client.dart
@@ -334,6 +334,7 @@ class GrpcExampleClient implements ExampleClient {
sdk: sdk,
name: example.name,
description: example.description,
+ tags: example.tags,
type: _exampleTypeFromString(example.type),
path: example.cloudPath,
contextLine: example.contextLine,
diff --git a/playground/frontend/playground_components/test/src/common/categories.dart b/playground/frontend/playground_components/test/src/common/categories.dart
index 39c0f4c38bc..2bba911d19c 100644
--- a/playground/frontend/playground_components/test/src/common/categories.dart
+++ b/playground/frontend/playground_components/test/src/common/categories.dart
@@ -24,19 +24,25 @@ import 'package:playground_components/src/models/sdk.dart';
import 'examples.dart';
final categoriesMock = [
- CategoryWithExamples(title: 'Sorted', examples: [exampleMock1]),
- CategoryWithExamples(title: 'Unsorted', examples: [exampleMock2]),
+ CategoryWithExamples(title: 'Filtered', examples: [exampleMock1]),
+ CategoryWithExamples(
+ title: 'Unfiltered',
+ // exampleMock2 is repeated to test that 'tag2' is more frequent than 'tag1'
+ examples: [exampleMock1, exampleMock2, exampleMock2, exampleMock2],
+ ),
];
-final sortedCategories = [
- CategoryWithExamples(title: 'Sorted', examples: [exampleMock1]),
+final filteredCategories = [
+ CategoryWithExamples(title: 'Filtered', examples: [exampleMock1]),
];
-const unsortedExamples = [exampleMock1, exampleMock2];
+const filteredExamples = [exampleMock1, exampleMock2];
-const examplesSortedByTypeMock = [exampleMock2];
+const examplesFilteredByTypeMock = [exampleMock2];
-const examplesSortedByNameMock = [exampleMock1];
+const examplesFilteredByTagsMock = [exampleMock2];
+
+const examplesFilteredByNameMock = [exampleMock1];
final sdkCategoriesFromServerMock = UnmodifiableMapView({
Sdk.java: categoriesMock,
diff --git a/playground/frontend/playground_components/test/src/common/examples.dart b/playground/frontend/playground_components/test/src/common/examples.dart
index e8590e87b36..ec2e82fd24d 100644
--- a/playground/frontend/playground_components/test/src/common/examples.dart
+++ b/playground/frontend/playground_components/test/src/common/examples.dart
@@ -24,7 +24,8 @@ import 'package:playground_components/src/models/sdk.dart';
const exampleMock1 = Example(
sdk: Sdk.python,
source: 'ex1',
- name: 'Example',
+ name: 'Example X1',
+ tags: ['tag1'],
type: ExampleType.example,
description: 'description',
path: 'SDK_PYTHON/Category/Name',
@@ -36,6 +37,7 @@ const exampleMock2 = Example(
sdk: Sdk.python,
source: 'ex2',
name: 'Kata',
+ tags: ['tag2'],
type: ExampleType.kata,
description: 'description',
path: 'SDK_PYTHON/Category/Name',
@@ -46,6 +48,7 @@ const exampleMock2 = Example(
const exampleWithoutSourceMock = ExampleBase(
sdk: Sdk.python,
name: 'Test example',
+ tags: [],
type: ExampleType.example,
description: 'description',
path: 'SDK_PYTHON/Category/Name',
@@ -56,6 +59,7 @@ const exampleWithoutSourceMock = ExampleBase(
const exampleWithAllAdditionsMock = Example(
sdk: Sdk.python,
name: 'Test example',
+ tags: [],
type: ExampleType.example,
description: 'description',
path: 'SDK_PYTHON/Category/Name',
@@ -71,6 +75,7 @@ const exampleMockGo = Example(
sdk: Sdk.go,
source: 'ex1',
name: 'Example',
+ tags: [],
type: ExampleType.example,
description: 'description',
path: 'SDK_GO/Category/Name',
diff --git a/playground/frontend/test/pages/playground/states/example_selector_state_test.dart b/playground/frontend/test/pages/playground/states/example_selector_state_test.dart
index 1d1c37d4d95..e31dee00cab 100644
--- a/playground/frontend/test/pages/playground/states/example_selector_state_test.dart
+++ b/playground/frontend/test/pages/playground/states/example_selector_state_test.dart
@@ -58,7 +58,7 @@ void main() {
test(
'ExampleSelector state filterText should be empty string by default',
() {
- expect(state.filterText, '');
+ expect(state.searchText, '');
},
);
@@ -76,9 +76,9 @@ void main() {
'ExampleSelector state should notify all listeners about filterText change',
() {
state.addListener(() {
- expect(state.filterText, 'test');
+ expect(state.searchText, 'test');
});
- state.setFilterText('test');
+ state.setSearchText('test');
},
);
@@ -93,7 +93,7 @@ void main() {
);
test(
- 'ExampleSelector state sortCategories should:'
+ 'ExampleSelector state filterCategories should:'
'- update categories and notify all listeners,'
'but should NOT:'
'- affect Example state categories', () {
@@ -101,11 +101,11 @@ void main() {
expect(state.categories, []);
expect(exampleCache.categoryListsBySdk, exampleCache.categoryListsBySdk);
});
- state.sortCategories();
+ state.filterCategoriesWithExamples();
});
test(
- 'ExampleSelector state sortExamplesByType should:'
+ 'ExampleSelector state filterExamplesByType should:'
'- update categories,'
'- notify all listeners,'
'but should NOT:'
@@ -115,15 +115,32 @@ void main() {
categoriesMock,
);
state.addListener(() {
- expect(state.categories, examplesSortedByTypeMock);
+ expect(state.categories, examplesFilteredByTypeMock);
expect(exampleCache.categoryListsBySdk, exampleCache.categoryListsBySdk);
});
- state.sortExamplesByType(unsortedExamples, ExampleType.kata);
+ state.filterExamplesByType(filteredExamples, ExampleType.kata);
});
test(
- 'ExampleSelector state sortExamplesByName should:'
- '- update categories'
+ 'ExampleSelector state filterExamplesByTags should:'
+ '- return examples which contain all selected tags'
+ '- notify all listeners,'
+ 'but should NOT:'
+ '- affect Example state categories', () {
+ final state = ExampleSelectorState(
+ playgroundController,
+ categoriesMock,
+ );
+ state.addSelectedTag('tag2');
+ expect(
+ state.filterExamplesByTags(filteredExamples),
+ examplesFilteredByTagsMock,
+ );
+ });
+
+ test(
+ 'ExampleSelector state filterExamplesByName should:'
+ '- return examples with matching names'
'- notify all listeners,'
'but should NOT:'
'- wait for full name of example,'
@@ -133,10 +150,19 @@ void main() {
playgroundController,
categoriesMock,
);
- state.addListener(() {
- expect(state.categories, examplesSortedByNameMock);
- expect(exampleCache.categoryListsBySdk, exampleCache.categoryListsBySdk);
- });
- state.sortExamplesByName(unsortedExamples, 'X1');
+ state.setSearchText('Example X1');
+ expect(
+ state.filterExamplesByName(filteredExamples),
+ examplesFilteredByNameMock,
+ );
+ });
+
+ test('ExampleSelectorState sorts tags by example count', () {
+ final state = ExampleSelectorState(
+ playgroundController,
+ categoriesMock,
+ );
+ const popularTag = 'tag2';
+ expect(state.tags.first == popularTag, true);
});
}