From a0615d28519030eb99d26113d7c152b0f05e09b8 Mon Sep 17 00:00:00 2001 From: Dario Carlomagno Date: Mon, 11 Nov 2024 15:09:06 +0100 Subject: [PATCH] Update tests. Make `AnalyticsSpy` specific for each test --- EcosiaTests/Analytics/AnalyticsSpyTests.swift | 136 +++++++++++------- 1 file changed, 87 insertions(+), 49 deletions(-) diff --git a/EcosiaTests/Analytics/AnalyticsSpyTests.swift b/EcosiaTests/Analytics/AnalyticsSpyTests.swift index 0fd790f0d63b..b032f987eb78 100644 --- a/EcosiaTests/Analytics/AnalyticsSpyTests.swift +++ b/EcosiaTests/Analytics/AnalyticsSpyTests.swift @@ -102,8 +102,6 @@ final class AnalyticsSpyTests: XCTestCase { // MARK: - Properties and Setup - var analyticsSpy: AnalyticsSpy! - var profileMock: MockProfile { MockProfile() } var tabManagerMock: TabManager { let mock = MockTabManager() @@ -114,24 +112,22 @@ final class AnalyticsSpyTests: XCTestCase { override func setUp() { super.setUp() - analyticsSpy = AnalyticsSpy() - Analytics.shared = analyticsSpy DependencyHelperMock().bootstrapDependencies() } override func tearDown() { - super.tearDown() - analyticsSpy = nil - Analytics.shared = Analytics() DependencyHelperMock().reset() + super.tearDown() } // MARK: - AppDelegate Tests - + var appDelegate: AppDelegate { AppDelegate() } func testTrackLaunchAndInstallOnDidFinishLaunching() async { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy XCTAssertNil(analyticsSpy.activityActionCalled) let application = await UIApplication.shared @@ -147,6 +143,8 @@ final class AnalyticsSpyTests: XCTestCase { func testTrackResumeOnDidFinishLaunching() async { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy XCTAssertNil(analyticsSpy.activityActionCalled) let application = await UIApplication.shared @@ -160,7 +158,7 @@ final class AnalyticsSpyTests: XCTestCase { } // MARK: - Bookmarks Tests - + var panel: BookmarksPanel { let viewModel = BookmarksPanelViewModel(profile: profileMock, bookmarkFolderGUID: "TestGuid") return BookmarksPanel(viewModel: viewModel) @@ -168,6 +166,8 @@ final class AnalyticsSpyTests: XCTestCase { func testTrackImportClick() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy XCTAssertNil(analyticsSpy.bookmarksImportExportPropertyCalled) // Act @@ -179,6 +179,8 @@ final class AnalyticsSpyTests: XCTestCase { func testTrackExportClick() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy XCTAssertNil(analyticsSpy.bookmarksImportExportPropertyCalled) // Act @@ -190,6 +192,8 @@ final class AnalyticsSpyTests: XCTestCase { func testTrackLearnMoreClick() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let view = EmptyBookmarksView(initialBottomMargin: 0) XCTAssertFalse(analyticsSpy.bookmarksEmptyLearnMoreClickedCalled) @@ -201,7 +205,7 @@ final class AnalyticsSpyTests: XCTestCase { } // MARK: - Menu Tests - + var menuHelper: MainMenuActionHelper { MainMenuActionHelper(profile: profileMock, tabManager: tabManagerMock, @@ -225,7 +229,7 @@ final class AnalyticsSpyTests: XCTestCase { (.bookmarks, .AppMenu.Bookmarks) ] for (label, title) in testCases { - analyticsSpy = AnalyticsSpy() + let analyticsSpy = AnalyticsSpy() Analytics.shared = analyticsSpy XCTContext.runActivity(named: "Menu action \(label.rawValue) is tracked") { _ in // Arrange @@ -242,7 +246,7 @@ final class AnalyticsSpyTests: XCTestCase { if let action = action { action.tapHandler!(action) // Assert - XCTAssertEqual(self.analyticsSpy.menuClickItemCalled, label) + XCTAssertEqual(analyticsSpy.menuClickItemCalled, label) } else { XCTFail("No action title with \(title) found") } @@ -260,7 +264,7 @@ final class AnalyticsSpyTests: XCTestCase { (.ntp, nil) ] for (label, url) in testCases { - analyticsSpy = AnalyticsSpy() + let analyticsSpy = AnalyticsSpy() Analytics.shared = analyticsSpy XCTContext.runActivity(named: "Menu share \(label.rawValue) is tracked") { _ in // Arrange @@ -274,26 +278,25 @@ final class AnalyticsSpyTests: XCTestCase { } else { XCTFail("No sharing action found for url \(url?.absoluteString ?? "nil")") } + // Since the share action may be asynchronous, ensure any asynchronous tasks are completed + // For this example, assume the share action calls the analytics synchronously + // Otherwise, use expectations to wait for the analytics call } } } func testTrackMenuStatus() { - // swiftlint:disable:next large_tuple let testCases: [(Analytics.Label.MenuStatus, Bool, String)] = [ - // Adding and then removing for each case; this order matters! (.readingList, true, .ShareAddToReadingList), (.readingList, false, .AppMenu.RemoveReadingList), (.bookmark, true, .KeyboardShortcuts.AddBookmark), - // Removing bookmark does not work since it requires additional user interaction - // (.bookmark, false, .RemoveBookmarkContextMenuTitle), (.shortcut, true, .AddToShortcutsActionTitle), (.shortcut, false, .AppMenu.RemoveFromShortcuts) ] for (label, value, title) in testCases { - analyticsSpy = AnalyticsSpy() + let analyticsSpy = AnalyticsSpy() Analytics.shared = analyticsSpy - XCTContext.runActivity(named: "Menu share \(label.rawValue) is tracked") { _ in + XCTContext.runActivity(named: "Menu status change \(label.rawValue) to \(value) is tracked") { _ in // Arrange XCTAssertNil(analyticsSpy.menuStatusItemCalled) XCTAssertNil(analyticsSpy.menuStatusItemChangedTo) @@ -304,14 +307,14 @@ final class AnalyticsSpyTests: XCTestCase { // Act menuHelper.getToolbarActions(navigationController: .init()) { actions in let action = actions - .flatMap { $0 } // Flattens sections - .flatMap { $0.items } // Flattens items in sections + .flatMap { $0 } // Flatten sections + .flatMap { $0.items } // Flatten items in sections .first { $0.title == title } if let action = action { action.tapHandler!(action) // Assert - XCTAssertEqual(self.analyticsSpy.menuStatusItemCalled, label) - XCTAssertEqual(self.analyticsSpy.menuStatusItemChangedTo, value) + XCTAssertEqual(analyticsSpy.menuStatusItemCalled, label) + XCTAssertEqual(analyticsSpy.menuStatusItemChangedTo, value) } else { XCTFail("No action title with \(title) found") } @@ -323,9 +326,11 @@ final class AnalyticsSpyTests: XCTestCase { } // MARK: - Onboarding / Welcome Tests - + func testWelcomeViewDidAppearTracksIntroDisplayingAndIntroClickStart() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let welcomeDelegate = MockWelcomeDelegate() let welcome = Welcome(delegate: welcomeDelegate) XCTAssertNil(analyticsSpy.introDisplayingPageCalled) @@ -342,6 +347,8 @@ final class AnalyticsSpyTests: XCTestCase { func testWelcomeGetStartedTracksIntroClickNext() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let welcomeDelegate = MockWelcomeDelegate() let welcome = Welcome(delegate: welcomeDelegate) XCTAssertNil(analyticsSpy.introClickLabelCalled) @@ -359,6 +366,8 @@ final class AnalyticsSpyTests: XCTestCase { func testWelcomeSkipTracksIntroClickSkip() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let welcomeDelegate = MockWelcomeDelegate() let welcome = Welcome(delegate: welcomeDelegate) XCTAssertNil(analyticsSpy.introClickLabelCalled) @@ -375,9 +384,11 @@ final class AnalyticsSpyTests: XCTestCase { } // MARK: - Onboarding / Welcome Tour Tests - + func testWelcomeTourViewDidAppearTracksIntroDisplaying() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let welcomeTourDelegate = MockWelcomeTourDelegate() let welcomeTour = WelcomeTour(delegate: welcomeTourDelegate) XCTAssertNil(analyticsSpy.introDisplayingPageCalled) @@ -394,6 +405,8 @@ final class AnalyticsSpyTests: XCTestCase { func testWelcomeTourNextTracksIntroClickNext() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let welcomeTourDelegate = MockWelcomeTourDelegate() let welcomeTour = WelcomeTour(delegate: welcomeTourDelegate) XCTAssertNil(analyticsSpy.introClickLabelCalled) @@ -413,6 +426,8 @@ final class AnalyticsSpyTests: XCTestCase { func testWelcomeTourSkipTracksIntroClickSkip() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let welcomeTourDelegate = MockWelcomeTourDelegate() let welcomeTour = WelcomeTour(delegate: welcomeTourDelegate) XCTAssertNil(analyticsSpy.introClickLabelCalled) @@ -432,6 +447,8 @@ final class AnalyticsSpyTests: XCTestCase { func testWelcomeTourTracksAnalyticsForAllPages() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let welcomeTourDelegate = MockWelcomeTourDelegate() let welcomeTour = WelcomeTour(delegate: welcomeTourDelegate) let pages: [Analytics.Property.OnboardingPage] = [ @@ -466,9 +483,11 @@ final class AnalyticsSpyTests: XCTestCase { } // MARK: - News Detail Tests - + func testNewsControllerViewDidAppearTracksNavigationViewNews() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let item = try! createMockNewsModel()! let items = [item] let newsController = NewsController(items: items) @@ -486,6 +505,8 @@ final class AnalyticsSpyTests: XCTestCase { func testNewsControllerDidSelectItemTracksNavigationOpenNews() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let item = try! createMockNewsModel()! let items = [item] let newsController = NewsController(items: items) @@ -502,9 +523,11 @@ final class AnalyticsSpyTests: XCTestCase { } // MARK: - Multiply Impact - Referrals Tests - + func testMultiplyImpactViewDidAppearTracksReferralViewInviteScreen() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let referrals = Referrals() let multiplyImpact = MultiplyImpact(referrals: referrals) multiplyImpact.loadViewIfNeeded() @@ -519,6 +542,8 @@ final class AnalyticsSpyTests: XCTestCase { func testMultiplyImpactLearnMoreButtonTracksReferralClickLearnMore() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let referrals = Referrals() let multiplyImpact = MultiplyImpact(referrals: referrals) multiplyImpact.loadViewIfNeeded() @@ -537,6 +562,8 @@ final class AnalyticsSpyTests: XCTestCase { func testMultiplyImpactCopyCodeTracksReferralClickLinkCopying() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let referrals = Referrals() let multiplyImpact = MultiplyImpact(referrals: referrals) multiplyImpact.loadViewIfNeeded() @@ -555,9 +582,12 @@ final class AnalyticsSpyTests: XCTestCase { func testMultiplyImpactInviteFriendsTracksReferralClickInvite() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let referrals = Referrals() - let multiplyImpact = MultiplyImpact(referrals: referrals) + let originalCode = User.shared.referrals.code User.shared.referrals.code = "testCode" + let multiplyImpact = MultiplyImpact(referrals: referrals) multiplyImpact.loadViewIfNeeded() // Act @@ -570,13 +600,19 @@ final class AnalyticsSpyTests: XCTestCase { // Assert XCTAssertEqual(analyticsSpy.referralActionCalled, .click) XCTAssertEqual(analyticsSpy.referralLabelCalled, .invite) + + // Cleanup + User.shared.referrals.code = originalCode } func testMultiplyImpactInviteFriendsCompletionTracksReferralSendInvite() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let referrals = Referrals() - let multiplyImpact = MultiplyImpactTestable(referrals: referrals) + let originalCode = User.shared.referrals.code User.shared.referrals.code = "testCode" + let multiplyImpact = MultiplyImpactTestable(referrals: referrals) multiplyImpact.loadViewIfNeeded() // Act @@ -610,12 +646,17 @@ final class AnalyticsSpyTests: XCTestCase { } else { XCTFail("UIActivityViewController not found or completion handler not set") } + + // Cleanup + User.shared.referrals.code = originalCode } // MARK: - Top Sites Tests - + func testTilePressedTracksAnalyticsForPinnedSite() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let viewModel = TopSitesViewModel(profile: profileMock, isZeroSearch: false, theme: EcosiaLightTheme(), @@ -634,6 +675,8 @@ final class AnalyticsSpyTests: XCTestCase { func testTilePressedTracksAnalyticsForDefaultSite() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let viewModel = TopSitesViewModel(profile: profileMock, isZeroSearch: false, theme: EcosiaLightTheme(), @@ -652,6 +695,8 @@ final class AnalyticsSpyTests: XCTestCase { func testTilePressedTracksAnalyticsForMostVisitedSite() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let viewModel = TopSitesViewModel(profile: profileMock, isZeroSearch: false, theme: EcosiaLightTheme(), @@ -670,6 +715,8 @@ final class AnalyticsSpyTests: XCTestCase { func testTrackTopSiteMenuActionTracksAnalytics() { // Arrange + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let viewModel = TopSitesViewModel(profile: profileMock, isZeroSearch: false, theme: EcosiaLightTheme(), @@ -682,41 +729,32 @@ final class AnalyticsSpyTests: XCTestCase { // Assert XCTAssertEqual(analyticsSpy.ntpTopSiteActionCalled, action) - XCTAssertEqual(analyticsSpy.ntpTopSitePropertyCalled, .mostVisited) // Assuming site is mostVisited + // Assuming site is mostVisited as it's not `default` nor `pinned` + XCTAssertEqual(analyticsSpy.ntpTopSitePropertyCalled, .mostVisited) XCTAssertNil(analyticsSpy.ntpTopSitePositionCalled) } + // MARK: - NTPAboutEcosiaCell Tests + func testNTPAboutEcosiaCellLearnMoreActionTracksNavigationOpen() { // Arrange - - // Create an instance of the real NTPAboutEcosiaCellViewModel + let analyticsSpy = AnalyticsSpy() + Analytics.shared = analyticsSpy let aboutViewModel = NTPAboutEcosiaCellViewModel(theme: EcosiaLightTheme()) let sections = aboutViewModel.sections - - // Ensure that there are sections available + guard let testSection = sections.first else { XCTFail("No sections available in NTPAboutEcosiaCellViewModel") return } - - // Create an instance of NTPAboutEcosiaCell + let aboutCell = NTPAboutEcosiaCell(frame: CGRect(x: 0, y: 0, width: 320, height: 64)) - - // Configure the cell with the real section and view model aboutCell.configure(section: testSection, viewModel: aboutViewModel) - - // Ensure that the analytics methods have not been called yet - XCTAssertNil(analyticsSpy.navigationActionCalled) - XCTAssertNil(analyticsSpy.navigationLabelCalled) - + // Act - - // Simulate tapping the "Learn More" button by sending the touchUpInside action aboutCell.learnMoreButton.sendActions(for: .touchUpInside) - + // Assert - - // Verify that the analytics event was called with the correct action and label XCTAssertEqual(analyticsSpy.navigationActionCalled, .open) XCTAssertEqual(analyticsSpy.navigationLabelCalled, testSection.label) }