From bd852575e150a7c3878fcbbc0260ab0feec626e0 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Thu, 7 Nov 2024 19:58:14 +0000 Subject: [PATCH 1/5] exclude current tab --- DuckDuckGo/AutocompleteViewController.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/DuckDuckGo/AutocompleteViewController.swift b/DuckDuckGo/AutocompleteViewController.swift index c358fe97cd..bd18c79b5e 100644 --- a/DuckDuckGo/AutocompleteViewController.swift +++ b/DuckDuckGo/AutocompleteViewController.swift @@ -60,7 +60,10 @@ class AutocompleteViewController: UIHostingController { private lazy var openTabs: [BrowserTab] = { tabsModel.tabs.compactMap { - guard let url = $0.link?.url else { return nil } + guard let url = $0.link?.url, + tabsModel.currentTab != $0 + else { return nil } + return OpenTab(title: $0.link?.displayTitle ?? "", url: url) } }() From 6329573689a8bf0416762e5ce20c7eeeed6455e3 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Thu, 7 Nov 2024 20:19:47 +0000 Subject: [PATCH 2/5] compare against url instead --- DuckDuckGo/AutocompleteViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DuckDuckGo/AutocompleteViewController.swift b/DuckDuckGo/AutocompleteViewController.swift index bd18c79b5e..4b3f87a73a 100644 --- a/DuckDuckGo/AutocompleteViewController.swift +++ b/DuckDuckGo/AutocompleteViewController.swift @@ -61,7 +61,7 @@ class AutocompleteViewController: UIHostingController { private lazy var openTabs: [BrowserTab] = { tabsModel.tabs.compactMap { guard let url = $0.link?.url, - tabsModel.currentTab != $0 + tabsModel.currentTab?.link?.url != $0.link?.url else { return nil } return OpenTab(title: $0.link?.displayTitle ?? "", url: url) From ff8774ec52fff1bebd6764d59acf399019d94df1 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Mon, 11 Nov 2024 13:40:26 +0000 Subject: [PATCH 3/5] rename var for clarity --- DuckDuckGo/AutocompleteViewController.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/DuckDuckGo/AutocompleteViewController.swift b/DuckDuckGo/AutocompleteViewController.swift index 4b3f87a73a..6ca4b298bd 100644 --- a/DuckDuckGo/AutocompleteViewController.swift +++ b/DuckDuckGo/AutocompleteViewController.swift @@ -58,7 +58,8 @@ class AutocompleteViewController: UIHostingController { CachedBookmarks(bookmarksDatabase) }() - private lazy var openTabs: [BrowserTab] = { + /// Specifically open tabs that do not have the same URL as the current tab so that we avoid shown them in the results. + private lazy var candidateOpenTabs: [BrowserTab] = { tabsModel.tabs.compactMap { guard let url = $0.link?.url, tabsModel.currentTab?.link?.url != $0.link?.url @@ -306,7 +307,7 @@ extension AutocompleteViewController: SuggestionLoadingDataSource { func openTabs(for suggestionLoading: any SuggestionLoading) -> [BrowserTab] { if featureFlagger.isFeatureOn(.autcompleteTabs) { - return openTabs + return candidateOpenTabs } return [] } From 6cd99aa8a4b66053c3e76f9aaa4dca3a95875631 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Mon, 11 Nov 2024 16:44:43 +0000 Subject: [PATCH 4/5] extract data source into own file and add tests --- DuckDuckGo.xcodeproj/project.pbxproj | 18 ++- .../xcshareddata/swiftpm/Package.resolved | 7 +- .../AutocompleteSuggestionsDataSource.swift | 100 ++++++++++++ DuckDuckGo/AutocompleteViewController.swift | 86 +++------- ...tocompleteSuggestionsDataSourceTests.swift | 152 ++++++++++++++++++ DuckDuckGoTests/MockFeatureFlagger.swift | 2 +- 6 files changed, 293 insertions(+), 72 deletions(-) create mode 100644 DuckDuckGo/AutocompleteSuggestionsDataSource.swift create mode 100644 DuckDuckGoTests/AutocompleteSuggestionsDataSourceTests.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 58e5dfe98e..5be52f7a41 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -432,6 +432,8 @@ 851672D12BED1FC900592F24 /* AutocompleteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851672D02BED1FC900592F24 /* AutocompleteView.swift */; }; 851672D32BED23FE00592F24 /* AutocompleteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851672D22BED23FE00592F24 /* AutocompleteViewModel.swift */; }; 8517D98B221783A0006A8DD0 /* FindInPage.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8517D98A221783A0006A8DD0 /* FindInPage.xcassets */; }; + 851952682CE2522700578553 /* AutocompleteSuggestionsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851952672CE2522700578553 /* AutocompleteSuggestionsDataSource.swift */; }; + 8519526C2CE256BC00578553 /* AutocompleteSuggestionsDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8519526A2CE256A900578553 /* AutocompleteSuggestionsDataSourceTests.swift */; }; 851B1283221FE65E004781BC /* ImproveOnboardingExperiment1Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851B1281221FE64E004781BC /* ImproveOnboardingExperiment1Tests.swift */; }; 851B128822200575004781BC /* Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851B128722200575004781BC /* Onboarding.swift */; }; 851B12CC22369931004781BC /* AtbAndVariantCleanup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 850250B220D803F4002199C7 /* AtbAndVariantCleanup.swift */; }; @@ -1740,6 +1742,8 @@ 851672D02BED1FC900592F24 /* AutocompleteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutocompleteView.swift; sourceTree = ""; }; 851672D22BED23FE00592F24 /* AutocompleteViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutocompleteViewModel.swift; sourceTree = ""; }; 8517D98A221783A0006A8DD0 /* FindInPage.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = FindInPage.xcassets; sourceTree = ""; }; + 851952672CE2522700578553 /* AutocompleteSuggestionsDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutocompleteSuggestionsDataSource.swift; sourceTree = ""; }; + 8519526A2CE256A900578553 /* AutocompleteSuggestionsDataSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutocompleteSuggestionsDataSourceTests.swift; sourceTree = ""; }; 851B1281221FE64E004781BC /* ImproveOnboardingExperiment1Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImproveOnboardingExperiment1Tests.swift; sourceTree = ""; }; 851B128722200575004781BC /* Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Onboarding.swift; sourceTree = ""; }; 851B128B2220483A004781BC /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = ""; }; @@ -4318,10 +4322,19 @@ children = ( 851672CE2BED1F9500592F24 /* HistoryMessageManager.swift */, 851672D22BED23FE00592F24 /* AutocompleteViewModel.swift */, + 851952672CE2522700578553 /* AutocompleteSuggestionsDataSource.swift */, ); name = Model; sourceTree = ""; }; + 851952692CE2569600578553 /* Autocomplete */ = { + isa = PBXGroup; + children = ( + 8519526A2CE256A900578553 /* AutocompleteSuggestionsDataSourceTests.swift */, + ); + name = Autocomplete; + sourceTree = ""; + }; 851DFD88212C5ED600D95F20 /* Main */ = { isa = PBXGroup; children = ( @@ -5752,7 +5765,7 @@ F12D98401F266B30003C2EE3 /* DuckDuckGo */ = { isa = PBXGroup; children = ( - 6F03CAFF2C32ED22004179A8 /* NewTabPage */, + 851952692CE2569600578553 /* Autocomplete */, 6FF9157F2B88E04F0042AC87 /* AdAttribution */, F17669A21E411D63003D3222 /* Application */, 981FED7222045FFA008488D7 /* AutoClear */, @@ -5765,6 +5778,7 @@ 8588026724E4249800C24AB6 /* iPad */, 851DFD88212C5ED600D95F20 /* Main */, EE56DE3A2A6038F500375C41 /* NetworkProtection */, + 6F03CAFF2C32ED22004179A8 /* NewTabPage */, F1D477C71F2139210031ED49 /* OmniBar */, 9F23B8042C2BE20500950875 /* Onboarding */, 98EA2C3F218BB5140023E1DC /* Settings */, @@ -7373,6 +7387,7 @@ 8540BD5423D8D5080057FDD2 /* PreserveLoginsAlert.swift in Sources */, 1E87615928A1517200C7C5CE /* PrivacyDashboardViewController.swift in Sources */, 6F03CAFE2C32DD08004179A8 /* HomePageMessagesConfiguration.swift in Sources */, + 851952682CE2522700578553 /* AutocompleteSuggestionsDataSource.swift in Sources */, EE9D68D12AE00CF300B55EF4 /* NetworkProtectionVPNSettingsView.swift in Sources */, 319A371028299A850079FBCE /* PasswordHider.swift in Sources */, 982C87C42255559A00919035 /* UITableViewCellExtension.swift in Sources */, @@ -8027,6 +8042,7 @@ 310E79BD2949CAA5007C49E8 /* FireButtonReferenceTests.swift in Sources */, 4B62C4BA25B930DD008912C6 /* AppConfigurationFetchTests.swift in Sources */, 31C7D71C27515A6300A95D0A /* MockVoiceSearchHelper.swift in Sources */, + 8519526C2CE256BC00578553 /* AutocompleteSuggestionsDataSourceTests.swift in Sources */, 6F395BBB2CD2C87D00B92FC3 /* BoolFileMarkerTests.swift in Sources */, 8598F67B2405EB8D00FBC70C /* KeyboardSettingsTests.swift in Sources */, 98AAF8E4292EB46000DBDF06 /* BookmarksMigrationTests.swift in Sources */, diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 49d5d017ea..5cf27650ba 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/DuckDuckGo/BrowserServicesKit", "state" : { - "revision" : "17154907fe86c75942331ed6d037694c666ddd95", - "version" : "208.0.0" + "revision" : "2facb6fb34934b38210938347b77f87057c0893c" } }, { @@ -41,8 +40,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/content-scope-scripts", "state" : { - "revision" : "1733ee59f06f6e725a98cf6cd8322159f59d664b", - "version" : "6.31.0" + "revision" : "adca39c379b1a124f9990e9d0308c374f32f5018", + "version" : "6.32.0" } }, { diff --git a/DuckDuckGo/AutocompleteSuggestionsDataSource.swift b/DuckDuckGo/AutocompleteSuggestionsDataSource.swift new file mode 100644 index 0000000000..73ac458f63 --- /dev/null +++ b/DuckDuckGo/AutocompleteSuggestionsDataSource.swift @@ -0,0 +1,100 @@ +// +// AutocompleteSuggestionsDataSource.swift +// DuckDuckGo +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed 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 Core +import BrowserServicesKit +import Suggestions +import History +import Persistence +import Networking + +final class AutocompleteSuggestionsDataSource: SuggestionLoadingDataSource { + + typealias SuggestionsRequestCompletion = (Data?, Error?) -> Void + typealias SuggestionsRequest = (URLRequest, @escaping SuggestionsRequestCompletion) -> Void + + private let historyManager: HistoryManaging + private let bookmarksDatabase: CoreDataDatabase + private let featureFlagger: FeatureFlagger + private let tabsModel: TabsModel + + private var performSuggestionsRequest: SuggestionsRequest + + /// Specifically open tabs that do not have the same URL as the current tab so that we avoid shown them in the results. + private lazy var candidateOpenTabs: [BrowserTab] = { + tabsModel.tabs.compactMap { + guard let url = $0.link?.url, + tabsModel.currentTab?.link?.url != $0.link?.url + else { return nil } + + return OpenTab(title: $0.link?.displayTitle ?? "", url: url) + } + }() + + private lazy var cachedBookmarks: CachedBookmarks = { + CachedBookmarks(bookmarksDatabase) + }() + + var historyCoordinator: HistoryCoordinating { + historyManager.historyCoordinator + } + + var platform: Platform { + .mobile + } + + init(historyManager: HistoryManaging, bookmarksDatabase: CoreDataDatabase, featureFlagger: FeatureFlagger, tabsModel: TabsModel, performSuggestionsRequest: @escaping SuggestionsRequest) { + self.historyManager = historyManager + self.bookmarksDatabase = bookmarksDatabase + self.featureFlagger = featureFlagger + self.tabsModel = tabsModel + self.performSuggestionsRequest = performSuggestionsRequest + } + + func history(for suggestionLoading: Suggestions.SuggestionLoading) -> [HistorySuggestion] { + return historyCoordinator.history ?? [] + } + + func bookmarks(for suggestionLoading: Suggestions.SuggestionLoading) -> [Suggestions.Bookmark] { + return cachedBookmarks.all + } + + func internalPages(for suggestionLoading: Suggestions.SuggestionLoading) -> [Suggestions.InternalPage] { + return [] + } + + func openTabs(for suggestionLoading: any SuggestionLoading) -> [BrowserTab] { + if featureFlagger.isFeatureOn(.autcompleteTabs) { + return candidateOpenTabs + } + return [] + } + + func suggestionLoading(_ suggestionLoading: Suggestions.SuggestionLoading, suggestionDataFromUrl url: URL, withParameters parameters: [String: String], completion: @escaping (Data?, Error?) -> Void) { + var queryURL = url + parameters.forEach { + queryURL = queryURL.appendingParameter(name: $0.key, value: $0.value) + } + var request = URLRequest.developerInitiated(queryURL) + request.allHTTPHeaderFields = APIRequest.Headers().httpHeaders + + performSuggestionsRequest(request, completion) + } + +} diff --git a/DuckDuckGo/AutocompleteViewController.swift b/DuckDuckGo/AutocompleteViewController.swift index 6ca4b298bd..ba914b9418 100644 --- a/DuckDuckGo/AutocompleteViewController.swift +++ b/DuckDuckGo/AutocompleteViewController.swift @@ -40,40 +40,34 @@ class AutocompleteViewController: UIHostingController { weak var delegate: AutocompleteViewControllerDelegate? weak var presentationDelegate: AutocompleteViewControllerPresentationDelegate? - private let historyManager: HistoryManaging - var historyCoordinator: HistoryCoordinating { - historyManager.historyCoordinator - } - - private let bookmarksDatabase: CoreDataDatabase private let appSettings: AppSettings private let model: AutocompleteViewModel - private var task: URLSessionDataTask? - @Published private var query = "" private var queryDebounceCancellable: AnyCancellable? - private lazy var cachedBookmarks: CachedBookmarks = { - CachedBookmarks(bookmarksDatabase) - }() - - /// Specifically open tabs that do not have the same URL as the current tab so that we avoid shown them in the results. - private lazy var candidateOpenTabs: [BrowserTab] = { - tabsModel.tabs.compactMap { - guard let url = $0.link?.url, - tabsModel.currentTab?.link?.url != $0.link?.url - else { return nil } - - return OpenTab(title: $0.link?.displayTitle ?? "", url: url) - } - }() - private var lastResults: SuggestionResult? private var loader: SuggestionLoader? private var historyMessageManager: HistoryMessageManager - private var tabsModel: TabsModel private var featureFlagger: FeatureFlagger + private let historyManager: HistoryManaging + private let bookmarksDatabase: CoreDataDatabase + private let tabsModel: TabsModel + + private var task: URLSessionDataTask? + + lazy var dataSource: AutocompleteSuggestionsDataSource = { + return AutocompleteSuggestionsDataSource( + historyManager: historyManager, + bookmarksDatabase: bookmarksDatabase, + featureFlagger: featureFlagger, + tabsModel: tabsModel) { [weak self] request, completion in + self?.task = Self.session.dataTask(with: request) { data, _, error in + completion(data, error) + } + self?.task?.resume() + } + }() init(historyManager: HistoryManaging, bookmarksDatabase: CoreDataDatabase, @@ -85,6 +79,7 @@ class AutocompleteViewController: UIHostingController { self.tabsModel = tabsModel self.historyManager = historyManager self.bookmarksDatabase = bookmarksDatabase + self.appSettings = appSettings self.historyMessageManager = historyMessageManager self.featureFlagger = featureFlagger @@ -195,7 +190,7 @@ class AutocompleteViewController: UIHostingController { return url }) - loader?.getSuggestions(query: query, usingDataSource: self) { [weak self] result, error in + loader?.getSuggestions(query: query, usingDataSource: dataSource) { [weak self] result, error in guard let self, error == nil else { return } let updatedResults = result ?? .empty self.lastResults = updatedResults @@ -287,47 +282,6 @@ extension AutocompleteViewController: AutocompleteViewModelDelegate { } } -extension AutocompleteViewController: SuggestionLoadingDataSource { - - var platform: Platform { - .mobile - } - - func history(for suggestionLoading: Suggestions.SuggestionLoading) -> [HistorySuggestion] { - return historyCoordinator.history ?? [] - } - - func bookmarks(for suggestionLoading: Suggestions.SuggestionLoading) -> [Suggestions.Bookmark] { - return cachedBookmarks.all - } - - func internalPages(for suggestionLoading: Suggestions.SuggestionLoading) -> [Suggestions.InternalPage] { - return [] - } - - func openTabs(for suggestionLoading: any SuggestionLoading) -> [BrowserTab] { - if featureFlagger.isFeatureOn(.autcompleteTabs) { - return candidateOpenTabs - } - return [] - } - - func suggestionLoading(_ suggestionLoading: Suggestions.SuggestionLoading, suggestionDataFromUrl url: URL, withParameters parameters: [String: String], completion: @escaping (Data?, Error?) -> Void) { - var queryURL = url - parameters.forEach { - queryURL = queryURL.appendingParameter(name: $0.key, value: $0.value) - } - - var request = URLRequest.developerInitiated(queryURL) - request.allHTTPHeaderFields = APIRequest.Headers().httpHeaders - task = Self.session.dataTask(with: request) { data, _, error in - completion(data, error) - } - task?.resume() - } - -} - private extension SuggestionResult { static let empty = SuggestionResult(topHits: [], duckduckgoSuggestions: [], localSuggestions: []) } diff --git a/DuckDuckGoTests/AutocompleteSuggestionsDataSourceTests.swift b/DuckDuckGoTests/AutocompleteSuggestionsDataSourceTests.swift new file mode 100644 index 0000000000..fad5fbde4a --- /dev/null +++ b/DuckDuckGoTests/AutocompleteSuggestionsDataSourceTests.swift @@ -0,0 +1,152 @@ +// +// AutocompleteSuggestionsDataSourceTests.swift +// DuckDuckGo +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed 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 Foundation + +import XCTest +import Persistence +import CoreData +import Bookmarks +import BrowserServicesKit +import Suggestions +import History + +@testable import Core +@testable import DuckDuckGo +@testable import TestUtils + +final class AutocompleteSuggestionsDataSourceTests: XCTestCase { + + var db: CoreDataDatabase! + var mainContext: NSManagedObjectContext! + + override func setUpWithError() throws { + try super.setUpWithError() + + let model = CoreDataDatabase.loadModel(from: Bookmarks.bundle, named: "BookmarksModel")! + + db = CoreDataDatabase(name: "Test", containerLocation: tempDBDir(), model: model) + db.loadStore() + + self.mainContext = db.makeContext(concurrencyType: .mainQueueConcurrencyType, name: "TestContext") + BasicBookmarksStructure.populateDB(context: mainContext) + } + + override func tearDown() { + try? db.tearDown(deleteStores: true) + } + + func testDataSourceReturnsHistory() { + let dataSource = makeDataSource(tabsEnabled: false) + XCTAssertEqual(dataSource.history(for: MockSuggestionLoading()).count, 2) + } + + func testWhenSuggestTabsFeatureIsDisable_ThenNoTabsReturned() { + let dataSource = makeDataSource(tabsEnabled: false) + + // Current tab is the last one added, which has two tabs with the same URL, so only 2 of the 4 will be returned. + let result = dataSource.openTabs(for: MockSuggestionLoading()) + XCTAssertTrue(result.isEmpty) + } + + func testWhenSuggestTabsFeatureIsEnabled_ThenProvidesOpenTabsExcludingCurrent() { + let dataSource = makeDataSource() + + // Current tab is the last one added, which has two tabs with the same URL, so only 2 of the 4 will be returned. + let result = dataSource.openTabs(for: MockSuggestionLoading()) + XCTAssertEqual(result.count, 2) + XCTAssertEqual("Different", result[0].title) + XCTAssertEqual("DDG", result[1].title) + } + + func testDataSourceReturnsBookmarks() { + let dataSource = makeDataSource() + let bookmarks = dataSource.bookmarks(for: MockSuggestionLoading()) + XCTAssertEqual(bookmarks.count, 5) + } + + func testDataSourceReturnsEmptyInternalPages() { + let dataSource = makeDataSource() + XCTAssertTrue(dataSource.internalPages(for: MockSuggestionLoading()).isEmpty) + } + + private func makeDataSource(tabsEnabled: Bool = true) -> AutocompleteSuggestionsDataSource { + + var mockHistoryCoordinator = MockHistoryCoordinator() + mockHistoryCoordinator.history = [ + makeHistory(.appStore, "App Store"), + makeHistory(.mac, "DDG for macOS") + ] + // mockHistoryCoordinator. + + return AutocompleteSuggestionsDataSource( + historyManager: MockHistoryManager(historyCoordinator: mockHistoryCoordinator, isEnabledByUser: true, historyFeatureEnabled: true), + bookmarksDatabase: db, + featureFlagger: makeFeatureFlagger(tabsEnabled: tabsEnabled), + tabsModel: makeTabsModel()) { _, completion in + completion("[]".data(using: .utf8), nil) + } + } + + private func makeFeatureFlagger(tabsEnabled: Bool = true) -> FeatureFlagger { + let mock = MockFeatureFlagger() + if tabsEnabled { + mock.enabledFeatureFlags.append(.autcompleteTabs) + } + return mock + } + + private func makeTabsModel() -> TabsModel { + let model = TabsModel(desktop: false) + model.add(tab: Tab(uid: "uid1", link: Link(title: "Example", url: URL(string: "https://example.com")!))) + model.add(tab: Tab(uid: "uid2", link: Link(title: "Different", url: URL(string: "https://different.com")!))) + model.add(tab: Tab(uid: "uid3", link: Link(title: "DDG", url: URL(string: "https://duckduckgo.com")!))) + model.add(tab: Tab(uid: "uid4", link: Link(title: "Example", url: URL(string: "https://example.com")!))) + return model + } + + private func makeHistory(_ url: URL, _ title: String) -> HistoryEntry { + .init(identifier: UUID(), + url: url, + title: title, + failedToLoad: false, + numberOfTotalVisits: 0, + lastVisit: Date(), + visits: .init(), + numberOfTrackersBlocked: 0, + blockedTrackingEntities: .init(), + trackersFound: false) + } + +} + +final class MockSuggestionLoading: SuggestionLoading { + func getSuggestions(query: Query, usingDataSource dataSource: any SuggestionLoadingDataSource, completion: @escaping (SuggestionResult?, (any Error)?) -> Void) { + } +} + +private extension MenuBookmarksViewModel { + + convenience init(bookmarksDatabase: CoreDataDatabase) { + self.init(bookmarksDatabase: bookmarksDatabase, + errorEvents: .init(mapping: { event, _, _, _ in + XCTFail("Unexpected error: \(event)") + })) + } +} diff --git a/DuckDuckGoTests/MockFeatureFlagger.swift b/DuckDuckGoTests/MockFeatureFlagger.swift index 1d2c8d642b..5434453927 100644 --- a/DuckDuckGoTests/MockFeatureFlagger.swift +++ b/DuckDuckGoTests/MockFeatureFlagger.swift @@ -21,8 +21,8 @@ import BrowserServicesKit import Core final class MockFeatureFlagger: FeatureFlagger { + var enabledFeatureFlags: [FeatureFlag] = [] - var enabledFeatureFlag: FeatureFlag? func isFeatureOn(forProvider provider: F) -> Bool where F: BrowserServicesKit.FeatureFlagSourceProviding { guard let flag = provider as? FeatureFlag else { From a103362c255d83433416f3833d4604a739a9120b Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Mon, 11 Nov 2024 17:20:03 +0000 Subject: [PATCH 5/5] remove invalid comment --- DuckDuckGoTests/AutocompleteSuggestionsDataSourceTests.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/DuckDuckGoTests/AutocompleteSuggestionsDataSourceTests.swift b/DuckDuckGoTests/AutocompleteSuggestionsDataSourceTests.swift index fad5fbde4a..29ea8e5636 100644 --- a/DuckDuckGoTests/AutocompleteSuggestionsDataSourceTests.swift +++ b/DuckDuckGoTests/AutocompleteSuggestionsDataSourceTests.swift @@ -60,7 +60,6 @@ final class AutocompleteSuggestionsDataSourceTests: XCTestCase { func testWhenSuggestTabsFeatureIsDisable_ThenNoTabsReturned() { let dataSource = makeDataSource(tabsEnabled: false) - // Current tab is the last one added, which has two tabs with the same URL, so only 2 of the 4 will be returned. let result = dataSource.openTabs(for: MockSuggestionLoading()) XCTAssertTrue(result.isEmpty) }