From e1b45bec55e8113af64c2cc305d8ef92159965a1 Mon Sep 17 00:00:00 2001 From: Istvan Soos Date: Fri, 9 May 2025 16:59:21 +0200 Subject: [PATCH 1/3] Promote name matches to top position + add name match badge after the title. --- app/lib/frontend/templates/admin.dart | 1 + app/lib/frontend/templates/listing.dart | 28 +------------------ app/lib/frontend/templates/package_misc.dart | 3 ++ .../frontend/templates/views/pkg/index.dart | 6 ---- .../templates/views/pkg/package_list.dart | 15 +++++++++- app/lib/search/mem_index.dart | 16 +++++++++-- app/test/search/mem_index_test.dart | 13 +++++---- pkg/web_css/lib/src/_list.scss | 6 ---- pkg/web_css/lib/src/_pkg.scss | 2 +- 9 files changed, 40 insertions(+), 50 deletions(-) diff --git a/app/lib/frontend/templates/admin.dart b/app/lib/frontend/templates/admin.dart index b14098030a..8c7d81e1ac 100644 --- a/app/lib/frontend/templates/admin.dart +++ b/app/lib/frontend/templates/admin.dart @@ -58,6 +58,7 @@ String renderAccountPackagesPage({ searchForm: null, sdkLibraryHits: [], packageHits: packageHits, + nameMatches: null, ), if (nextPackage != null) d.div( diff --git a/app/lib/frontend/templates/listing.dart b/app/lib/frontend/templates/listing.dart index 62b92cf416..4f3f124897 100644 --- a/app/lib/frontend/templates/listing.dart +++ b/app/lib/frontend/templates/listing.dart @@ -5,11 +5,9 @@ import 'dart:math'; import 'package:_pub_shared/search/search_form.dart'; -import 'package:collection/collection.dart'; import '../../package/search_adapter.dart'; import '../../search/search_service.dart'; -import '../../shared/urls.dart' as urls; import '../dom/dom.dart' as d; import '_consts.dart'; @@ -29,6 +27,7 @@ d.Node packageList(SearchResultPage searchResultPage) { searchForm: searchResultPage.form, sdkLibraryHits: searchResultPage.sdkLibraryHits, packageHits: searchResultPage.packageHits, + nameMatches: searchResultPage.nameMatches, ); } @@ -50,7 +49,6 @@ String renderPkgIndexPage( title: topPackages, messageFromBackend: searchResultPage.errorMessage, ), - nameMatches: _nameMatches(searchForm, searchResultPage.nameMatches), packageList: packageList(searchResultPage), pagination: searchResultPage.hasHit ? paginationNode(links) : null, openSections: openSections, @@ -123,27 +121,3 @@ class PageLinks { return min(fromSymmetry, max(currentPage!, fromCount)); } } - -d.Node? _nameMatches(SearchForm form, List? matches) { - if (matches == null || matches.isEmpty) { - return null; - } - final singular = matches.length == 1; - final isExactNameMatch = singular && form.parsedQuery.text == matches.single; - final nameMatchLabel = isExactNameMatch - ? 'Exact package name match: ' - : 'Matching package ${singular ? 'name' : 'names'}: '; - - return d.p(children: [ - d.text(nameMatchLabel), - ...matches.expandIndexed((i, name) { - return [ - if (i > 0) d.text(', '), - d.a( - href: urls.pkgPageUrl(name), - child: d.b(text: name), - ), - ]; - }), - ]); -} diff --git a/app/lib/frontend/templates/package_misc.dart b/app/lib/frontend/templates/package_misc.dart index e63856fe1f..a1162bf6da 100644 --- a/app/lib/frontend/templates/package_misc.dart +++ b/app/lib/frontend/templates/package_misc.dart @@ -29,6 +29,9 @@ final flutterFavoriteBadgeNode = packageBadgeNode( ), ); +/// Renders the name match badge node, used for exact package name hits. +final nameMatchBadgeNode = packageBadgeNode(label: 'Name match'); + /// Renders the null-safe badge used by package listing and package page. d.Node nullSafeBadgeNode({String? title}) { return packageBadgeNode( diff --git a/app/lib/frontend/templates/views/pkg/index.dart b/app/lib/frontend/templates/views/pkg/index.dart index cc5bc889af..f74fae78b6 100644 --- a/app/lib/frontend/templates/views/pkg/index.dart +++ b/app/lib/frontend/templates/views/pkg/index.dart @@ -13,18 +13,12 @@ import '../../../static_files.dart'; d.Node packageListingNode({ required SearchForm searchForm, required d.Node listingInfo, - required d.Node? nameMatches, required d.Node packageList, required d.Node? pagination, required Set? openSections, }) { final innerContent = d.fragment([ listingInfo, - if (nameMatches != null) - d.div( - classes: ['listing-highlight-block'], - child: nameMatches, - ), packageList, if (pagination != null) pagination, d.markdown('Check our help page for details on ' diff --git a/app/lib/frontend/templates/views/pkg/package_list.dart b/app/lib/frontend/templates/views/pkg/package_list.dart index 5063932a54..95b97754e9 100644 --- a/app/lib/frontend/templates/views/pkg/package_list.dart +++ b/app/lib/frontend/templates/views/pkg/package_list.dart @@ -27,12 +27,19 @@ d.Node listOfPackagesNode({ required SearchForm? searchForm, required List sdkLibraryHits, required List packageHits, + required List? nameMatches, }) { + final bestNameMatch = + (nameMatches == null || nameMatches.isEmpty) ? null : nameMatches.first; return d.div( classes: ['packages'], children: [ ...sdkLibraryHits.map(_sdkLibraryItem), - ...packageHits.map((hit) => _packageItem(hit, searchForm: searchForm)), + ...packageHits.map((hit) => _packageItem( + hit, + searchForm: searchForm, + isNameMatch: hit.name == bestNameMatch, + )), imageCarousel(), ], ); @@ -48,6 +55,7 @@ d.Node _sdkLibraryItem(SdkLibraryHit hit) { return _item( url: hit.url!, name: hit.library!, + isNameMatch: false, newTimestamp: null, labeledScoresNode: null, description: hit.description ?? '', @@ -71,6 +79,7 @@ d.Node _sdkLibraryItem(SdkLibraryHit hit) { d.Node _packageItem( PackageView view, { required SearchForm? searchForm, + required bool isNameMatch, }) { final isFlutterFavorite = view.tags.contains(PackageTags.isFlutterFavorite); final isNullSafe = view.tags.contains(PackageVersionTags.isNullSafe); @@ -177,6 +186,7 @@ d.Node _packageItem( screenshotDescriptions: screenshotDescriptions, url: urls.pkgPageUrl(view.name), name: view.name, + isNameMatch: isNameMatch, newTimestamp: view.created, labeledScoresNode: labeledScoresNodeFromPackageView(view), description: view.ellipsizedDescription ?? '', @@ -207,6 +217,7 @@ d.Node _item({ List topics = const [], required String url, required String name, + required bool isNameMatch, required DateTime? newTimestamp, required d.Node? labeledScoresNode, required String description, @@ -230,6 +241,8 @@ d.Node _item({ ], children: [ d.a(href: url, text: name), if (copyIcon != null) copyIcon, + d.text(' '), + if (isNameMatch) nameMatchBadgeNode, ]), if (age != null && age.inDays <= 30) d.div( diff --git a/app/lib/search/mem_index.dart b/app/lib/search/mem_index.dart index c604bcde9d..ef4d197571 100644 --- a/app/lib/search/mem_index.dart +++ b/app/lib/search/mem_index.dart @@ -23,6 +23,7 @@ final _textSearchTimeout = Duration(milliseconds: 500); class InMemoryPackageIndex { final List _documents; final _documentsByName = {}; + final _nameToIndex = {}; late final PackageNameIndex _packageNameIndex; late final TokenIndex _descrIndex; late final TokenIndex _readmeIndex; @@ -62,6 +63,7 @@ class InMemoryPackageIndex { for (var i = 0; i < _documents.length; i++) { final doc = _documents[i]; _documentsByName[doc.package] = doc; + _nameToIndex[doc.package] = i; // transform tags into numberical IDs final tagIds = []; @@ -268,8 +270,11 @@ class InMemoryPackageIndex { /// it linearly into the [0.4-1.0] range, to allow better /// multiplication outcomes. packageScores.multiplyAllFromValues(_adjustedOverallScores); - indexedHits = _rankWithValues(packageScores, - requiredLengthThreshold: query.offset); + indexedHits = _rankWithValues( + packageScores, + requiredLengthThreshold: query.offset, + bestNameMatch: bestNameMatch, + ); break; case SearchOrder.text: indexedHits = _rankWithValues(packageScores, @@ -471,11 +476,14 @@ class InMemoryPackageIndex { IndexedScore score, { // if the item count is fewer than this threshold, an empty list will be returned int? requiredLengthThreshold, + String? bestNameMatch, }) { final list = []; + final bestNameIndex = + bestNameMatch == null ? null : _nameToIndex[bestNameMatch]; for (var i = 0; i < score.length; i++) { final value = score.getValue(i); - if (value <= 0.0) continue; + if (value <= 0.0 && i != bestNameIndex) continue; list.add(IndexedPackageHit( i, PackageHit(package: score.keys[i], score: value))); } @@ -484,6 +492,8 @@ class InMemoryPackageIndex { return []; } list.sort((a, b) { + if (a.index == bestNameIndex) return -1; + if (b.index == bestNameIndex) return 1; final scoreCompare = -a.hit.score!.compareTo(b.hit.score!); if (scoreCompare != 0) return scoreCompare; // if two packages got the same score, order by last updated diff --git a/app/test/search/mem_index_test.dart b/app/test/search/mem_index_test.dart index de358dff21..f928fe516b 100644 --- a/app/test/search/mem_index_test.dart +++ b/app/test/search/mem_index_test.dart @@ -636,9 +636,9 @@ server.dart adds a small, prescriptive server (PicoServer) that can be configure 'nameMatches': ['abc'], 'sdkLibraryHits': [], 'packageHits': [ - // `abc` is at its natural place - {'package': 'def', 'score': closeTo(0.85, 0.01)}, + // `abc` is at the first position, score is kept {'package': 'abc', 'score': closeTo(0.70, 0.01)}, + {'package': 'def', 'score': closeTo(0.85, 0.01)}, ] }); // exact name match with tags @@ -651,9 +651,9 @@ server.dart adds a small, prescriptive server (PicoServer) that can be configure 'nameMatches': ['abc'], 'sdkLibraryHits': [], 'packageHits': [ - // `abc` is at its natural place - {'package': 'def', 'score': closeTo(0.85, 0.01)}, + // `abc` is at the first position, score is kept {'package': 'abc', 'score': closeTo(0.70, 0.01)}, + {'package': 'def', 'score': closeTo(0.85, 0.01)}, ] }); // absent exact name match with tags @@ -662,11 +662,12 @@ server.dart adds a small, prescriptive server (PicoServer) that can be configure .toJson(), { 'timestamp': isNotEmpty, - 'totalCount': 1, + 'totalCount': 2, 'nameMatches': ['abc'], 'sdkLibraryHits': [], 'packageHits': [ - // `abc` is not present in the package list + // `abc` is at the first position, score is zero + {'package': 'abc', 'score': 0.0}, {'package': 'def', 'score': closeTo(0.85, 0.01)}, ] }); diff --git a/pkg/web_css/lib/src/_list.scss b/pkg/web_css/lib/src/_list.scss index 816e36c23e..7b9cde7f0d 100644 --- a/pkg/web_css/lib/src/_list.scss +++ b/pkg/web_css/lib/src/_list.scss @@ -46,12 +46,6 @@ } } -.listing-highlight-block { - border-left: 0.25em solid var(--pub-markdown-alert-note); - padding: .5rem 1rem; - margin: 4px 0px; -} - .sort-control { position: relative; cursor: pointer; diff --git a/pkg/web_css/lib/src/_pkg.scss b/pkg/web_css/lib/src/_pkg.scss index 27fd0245c1..0837d38576 100644 --- a/pkg/web_css/lib/src/_pkg.scss +++ b/pkg/web_css/lib/src/_pkg.scss @@ -511,7 +511,7 @@ display: inline-block; height: 20px; width: 20px; - margin-left: 12px; + margin: 0px 12px; .pkg-page-title-copy-icon { display: block; From c1e34d9664fc7ea8be1181f388ceef402b354ac4 Mon Sep 17 00:00:00 2001 From: Istvan Soos Date: Tue, 13 May 2025 16:56:39 +0200 Subject: [PATCH 2/3] Better positioning. --- app/lib/frontend/templates/package_misc.dart | 5 ++++- pkg/web_css/lib/src/_pkg.scss | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/lib/frontend/templates/package_misc.dart b/app/lib/frontend/templates/package_misc.dart index a1162bf6da..9412b7f397 100644 --- a/app/lib/frontend/templates/package_misc.dart +++ b/app/lib/frontend/templates/package_misc.dart @@ -30,7 +30,10 @@ final flutterFavoriteBadgeNode = packageBadgeNode( ); /// Renders the name match badge node, used for exact package name hits. -final nameMatchBadgeNode = packageBadgeNode(label: 'Name match'); +final nameMatchBadgeNode = packageBadgeNode( + label: 'Name match', + color: 'name-match', +); /// Renders the null-safe badge used by package listing and package page. d.Node nullSafeBadgeNode({String? title}) { diff --git a/pkg/web_css/lib/src/_pkg.scss b/pkg/web_css/lib/src/_pkg.scss index 0837d38576..ca2cba9a2e 100644 --- a/pkg/web_css/lib/src/_pkg.scss +++ b/pkg/web_css/lib/src/_pkg.scss @@ -20,6 +20,11 @@ color: var(--pub-badge-red-color); } + &.package-badge-name-match { + position: relative; + top: -5px; + } + .package-badge-icon { max-width: 13px; max-height: 13px; From 5348995103bf5aaa01ddc32aa9dceefdef4b57ae Mon Sep 17 00:00:00 2001 From: Istvan Soos Date: Tue, 13 May 2025 16:56:39 +0200 Subject: [PATCH 3/3] Don't promote name match when other filters are present. --- app/lib/search/mem_index.dart | 17 ++++++++++++---- app/lib/search/search_service.dart | 4 ++-- app/test/search/api_doc_page_test.dart | 1 - app/test/search/flutter_iap_test.dart | 1 - app/test/search/handlers_test.dart | 1 - app/test/search/haversine_test.dart | 1 - app/test/search/json_tool_test.dart | 3 +-- app/test/search/maps_test.dart | 3 +-- app/test/search/mem_index_test.dart | 28 ++++++++++++++++---------- app/test/search/stack_trace_test.dart | 1 - app/test/search/travis_test.dart | 1 - 11 files changed, 34 insertions(+), 27 deletions(-) diff --git a/app/lib/search/mem_index.dart b/app/lib/search/mem_index.dart index ef4d197571..f06b4a80f6 100644 --- a/app/lib/search/mem_index.dart +++ b/app/lib/search/mem_index.dart @@ -234,7 +234,9 @@ class InMemoryPackageIndex { ); String? bestNameMatch; - if (parsedQueryText != null) { + if (parsedQueryText != null && + query.parsedQuery.hasOnlyFreeText && + query.isNaturalOrder) { // exact package name if (_documentsByName.containsKey(parsedQueryText)) { bestNameMatch = parsedQueryText; @@ -277,8 +279,11 @@ class InMemoryPackageIndex { ); break; case SearchOrder.text: - indexedHits = _rankWithValues(packageScores, - requiredLengthThreshold: query.offset); + indexedHits = _rankWithValues( + packageScores, + requiredLengthThreshold: query.offset, + bestNameMatch: bestNameMatch, + ); break; case SearchOrder.created: indexedHits = _createdOrderedHits.whereInScores(packageScores); @@ -322,10 +327,14 @@ class InMemoryPackageIndex { packageHits = indexedHits.map((h) => h.hit).toList(); } + // Only indicate name match when the first item's score is lower than the second's score. + final indicateNameMatch = bestNameMatch != null && + packageHits.length > 1 && + ((packageHits[0].score ?? 0) <= (packageHits[1].score ?? 0)); return PackageSearchResult( timestamp: clock.now().toUtc(), totalCount: totalCount, - nameMatches: bestNameMatch == null ? null : [bestNameMatch], + nameMatches: indicateNameMatch ? [bestNameMatch] : null, packageHits: packageHits, errorMessage: textResults?.errorMessage, ); diff --git a/app/lib/search/search_service.dart b/app/lib/search/search_service.dart index 3ca8ddf9b9..0eb5000808 100644 --- a/app/lib/search/search_service.dart +++ b/app/lib/search/search_service.dart @@ -283,7 +283,7 @@ class ServiceSearchQuery { late final effectiveOrder = parsedQuery.order ?? order; bool get _hasQuery => query != null && query!.isNotEmpty; bool get _hasOnlyFreeText => _hasQuery && parsedQuery.hasOnlyFreeText; - bool get _isNaturalOrder => + bool get isNaturalOrder => effectiveOrder == null || effectiveOrder == SearchOrder.top || effectiveOrder == SearchOrder.text; @@ -294,7 +294,7 @@ class ServiceSearchQuery { bool get includeSdkResults => offset == 0 && _hasOnlyFreeText && - _isNaturalOrder && + isNaturalOrder && _hasNoOwnershipScope && !_isFlutterFavorite && (textMatchExtent ?? TextMatchExtent.api).shouldMatchApi(); diff --git a/app/test/search/api_doc_page_test.dart b/app/test/search/api_doc_page_test.dart index 5631515163..c10e596fcf 100644 --- a/app/test/search/api_doc_page_test.dart +++ b/app/test/search/api_doc_page_test.dart @@ -53,7 +53,6 @@ void main() { expect(json.decode(json.encode(result)), { 'timestamp': isNotNull, 'totalCount': 2, - 'nameMatches': ['foo'], 'sdkLibraryHits': [], 'packageHits': [ {'package': 'foo', 'score': 1.0}, // finds package name diff --git a/app/test/search/flutter_iap_test.dart b/app/test/search/flutter_iap_test.dart index 65949287c3..7199b228a8 100644 --- a/app/test/search/flutter_iap_test.dart +++ b/app/test/search/flutter_iap_test.dart @@ -69,7 +69,6 @@ void main() { expect(json.decode(json.encode(result)), { 'timestamp': isNotNull, 'totalCount': 1, - 'nameMatches': ['flutter_iap'], 'sdkLibraryHits': [], 'packageHits': [ {'package': 'flutter_iap', 'score': 1.0}, diff --git a/app/test/search/handlers_test.dart b/app/test/search/handlers_test.dart index de09e5f87d..29986d85a4 100644 --- a/app/test/search/handlers_test.dart +++ b/app/test/search/handlers_test.dart @@ -33,7 +33,6 @@ void main() { await expectJsonResponse(await issueGet('/search?q=oxygen'), body: { 'timestamp': isNotNull, 'totalCount': 1, - 'nameMatches': ['oxygen'], 'sdkLibraryHits': [], 'packageHits': [ {'package': 'oxygen', 'score': isPositive}, diff --git a/app/test/search/haversine_test.dart b/app/test/search/haversine_test.dart index 9d893de26d..d788a1f44f 100644 --- a/app/test/search/haversine_test.dart +++ b/app/test/search/haversine_test.dart @@ -380,7 +380,6 @@ MIT'''), expect(json.decode(json.encode(result)), { 'timestamp': isNotNull, 'totalCount': 3, - 'nameMatches': ['haversine'], 'sdkLibraryHits': [], 'packageHits': [ {'package': 'haversine', 'score': 1.0}, diff --git a/app/test/search/json_tool_test.dart b/app/test/search/json_tool_test.dart index fe69f113c3..b315927460 100644 --- a/app/test/search/json_tool_test.dart +++ b/app/test/search/json_tool_test.dart @@ -27,7 +27,6 @@ void main() { expect(json.decode(json.encode(result)), { 'timestamp': isNotNull, 'totalCount': 1, - 'nameMatches': ['jsontool'], 'sdkLibraryHits': [], 'packageHits': [ {'package': 'jsontool', 'score': 1.0}, @@ -70,8 +69,8 @@ void main() { 'nameMatches': ['jsontool'], 'sdkLibraryHits': [], 'packageHits': [ - {'package': 'json2entity', 'score': 1.0}, {'package': 'jsontool', 'score': 1.0}, + {'package': 'json2entity', 'score': 1.0}, {'package': 'json_to_model', 'score': closeTo(0.73, 0.01)}, ], }); diff --git a/app/test/search/maps_test.dart b/app/test/search/maps_test.dart index 3dda22250b..ffb0374d85 100644 --- a/app/test/search/maps_test.dart +++ b/app/test/search/maps_test.dart @@ -26,7 +26,6 @@ void main() { expect(json.decode(json.encode(result)), { 'timestamp': isNotNull, 'totalCount': 2, - 'nameMatches': ['maps'], 'sdkLibraryHits': [], 'packageHits': [ {'package': 'maps', 'score': 1.0}, @@ -44,8 +43,8 @@ void main() { 'nameMatches': ['map'], 'sdkLibraryHits': [], 'packageHits': [ - {'package': 'maps', 'score': 1.0}, {'package': 'map', 'score': 1.0}, + {'package': 'maps', 'score': 1.0}, ], }); }); diff --git a/app/test/search/mem_index_test.dart b/app/test/search/mem_index_test.dart index f928fe516b..c9e0edf0bf 100644 --- a/app/test/search/mem_index_test.dart +++ b/app/test/search/mem_index_test.dart @@ -95,7 +95,6 @@ server.dart adds a small, prescriptive server (PicoServer) that can be configure expect(json.decode(json.encode(result)), { 'timestamp': isNotNull, 'totalCount': 1, - 'nameMatches': ['async'], 'sdkLibraryHits': [], 'packageHits': [ {'package': 'async', 'score': closeTo(0.71, 0.01)}, @@ -254,7 +253,6 @@ server.dart adds a small, prescriptive server (PicoServer) that can be configure expect(json.decode(json.encode(result)), { 'timestamp': isNotNull, 'totalCount': 2, - 'nameMatches': ['http'], 'sdkLibraryHits': [], 'packageHits': [ {'package': 'http'}, @@ -628,7 +626,7 @@ server.dart adds a small, prescriptive server (PicoServer) that can be configure ] }, ); - // exact name match without tags + // exact name match without tags - promoted expect( (index.search(ServiceSearchQuery.parse(query: 'abc'))).toJson(), { 'timestamp': isNotEmpty, @@ -641,19 +639,29 @@ server.dart adds a small, prescriptive server (PicoServer) that can be configure {'package': 'def', 'score': closeTo(0.85, 0.01)}, ] }); - // exact name match with tags + // exact name match without tags - first anyway + expect( + (index.search(ServiceSearchQuery.parse(query: 'def'))).toJson(), { + 'timestamp': isNotEmpty, + 'totalCount': 2, + 'sdkLibraryHits': [], + 'packageHits': [ + {'package': 'def', 'score': closeTo(0.85, 0.01)}, + {'package': 'abc', 'score': closeTo(0.70, 0.01)}, + ] + }); + // absent exact name match with tags expect( (index.search(ServiceSearchQuery.parse(query: 'abc sdk:dart'))) .toJson(), { 'timestamp': isNotEmpty, 'totalCount': 2, - 'nameMatches': ['abc'], 'sdkLibraryHits': [], 'packageHits': [ - // `abc` is at the first position, score is kept - {'package': 'abc', 'score': closeTo(0.70, 0.01)}, + // `abc` is at the original position {'package': 'def', 'score': closeTo(0.85, 0.01)}, + {'package': 'abc', 'score': closeTo(0.70, 0.01)}, ] }); // absent exact name match with tags @@ -662,12 +670,10 @@ server.dart adds a small, prescriptive server (PicoServer) that can be configure .toJson(), { 'timestamp': isNotEmpty, - 'totalCount': 2, - 'nameMatches': ['abc'], + 'totalCount': 1, 'sdkLibraryHits': [], 'packageHits': [ - // `abc` is at the first position, score is zero - {'package': 'abc', 'score': 0.0}, + // `abc` is absent {'package': 'def', 'score': closeTo(0.85, 0.01)}, ] }); diff --git a/app/test/search/stack_trace_test.dart b/app/test/search/stack_trace_test.dart index 059d34e3fd..816f704dd7 100644 --- a/app/test/search/stack_trace_test.dart +++ b/app/test/search/stack_trace_test.dart @@ -32,7 +32,6 @@ void main() { expect(json.decode(json.encode(result)), { 'timestamp': isNotNull, 'totalCount': 1, - 'nameMatches': ['stack_trace'], 'sdkLibraryHits': [], 'packageHits': [ { diff --git a/app/test/search/travis_test.dart b/app/test/search/travis_test.dart index 2ecdf1add8..fbee204051 100644 --- a/app/test/search/travis_test.dart +++ b/app/test/search/travis_test.dart @@ -55,7 +55,6 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i expect(json.decode(json.encode(result)), { 'timestamp': isNotNull, 'totalCount': 1, - 'nameMatches': ['travis'], 'sdkLibraryHits': [], 'packageHits': [ {'package': 'travis', 'score': 1.0},