diff --git a/.github/workflows/build_notarized.yml b/.github/workflows/build_notarized.yml index c0dc2e22c7..76d8ff71f4 100644 --- a/.github/workflows/build_notarized.yml +++ b/.github/workflows/build_notarized.yml @@ -40,6 +40,11 @@ on: description: "Branch name" required: false type: string + skip-notify: + description: "Skip Mattermost notification" + required: false + default: false + type: boolean secrets: APPLE_API_KEY_BASE64: required: true @@ -360,7 +365,7 @@ jobs: name: Send Mattermost message needs: [export-notarized-app, create-dmg] - if: always() + if: ${{ always() && inputs.skip-notify == false }} runs-on: ubuntu-latest diff --git a/.github/workflows/sync_end_to_end.yml b/.github/workflows/sync_end_to_end.yml index 91308789b7..f1b46005df 100644 --- a/.github/workflows/sync_end_to_end.yml +++ b/.github/workflows/sync_end_to_end.yml @@ -13,6 +13,7 @@ jobs: release-type: review create-dmg: false branch: ${{ github.sha }} + skip-notify: true secrets: APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }} APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} diff --git a/.github/workflows/ui_tests.yml b/.github/workflows/ui_tests.yml index 611b105a5a..857158c321 100644 --- a/.github/workflows/ui_tests.yml +++ b/.github/workflows/ui_tests.yml @@ -17,6 +17,7 @@ jobs: release-type: review create-dmg: false branch: ${{ github.sha }} + skip-notify: true secrets: APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }} APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} diff --git a/DuckDuckGo/Freemium/DBP/FreemiumDBPPromotionViewCoordinator.swift b/DuckDuckGo/Freemium/DBP/FreemiumDBPPromotionViewCoordinator.swift index d764c8f154..56631b6b0c 100644 --- a/DuckDuckGo/Freemium/DBP/FreemiumDBPPromotionViewCoordinator.swift +++ b/DuckDuckGo/Freemium/DBP/FreemiumDBPPromotionViewCoordinator.swift @@ -31,9 +31,10 @@ final class FreemiumDBPPromotionViewCoordinator: ObservableObject { /// Published property that determines whether the promotion is visible on the home page. @Published var isHomePagePromotionVisible: Bool = false - /// The view model representing the promotion, which updates based on the user's state. - var viewModel: PromotionViewModel { - createViewModel() + /// The view model representing the promotion, which updates based on the user's state. Returns `nil` if the feature is not enabled + var viewModel: PromotionViewModel? { + guard freemiumDBPFeature.isAvailable else { return nil } + return createViewModel() } /// Stores whether the user has dismissed the home page promotion. diff --git a/DuckDuckGo/HomePage/View/HomePageView.swift b/DuckDuckGo/HomePage/View/HomePageView.swift index 428c7b85db..511213a45d 100644 --- a/DuckDuckGo/HomePage/View/HomePageView.swift +++ b/DuckDuckGo/HomePage/View/HomePageView.swift @@ -224,10 +224,15 @@ extension HomePage.Views { } } + @ViewBuilder func freemiumPromotionView() -> some View { - PromotionView(viewModel: freemiumDBPPromotionViewCoordinator.viewModel) - .padding(.bottom, 16) - .visibility(freemiumDBPPromotionViewCoordinator.isHomePagePromotionVisible ? .visible : .gone) + if let viewModel = freemiumDBPPromotionViewCoordinator.viewModel { + PromotionView(viewModel: viewModel) + .padding(.bottom, 16) + .visibility(freemiumDBPPromotionViewCoordinator.isHomePagePromotionVisible ? .visible : .gone) + } else { + EmptyView() + } } @ViewBuilder diff --git a/UnitTests/Freemium/DBP/FreemiumDBPPromotionViewCoordinatorTests.swift b/UnitTests/Freemium/DBP/FreemiumDBPPromotionViewCoordinatorTests.swift index bb5329ba78..fca8c31aec 100644 --- a/UnitTests/Freemium/DBP/FreemiumDBPPromotionViewCoordinatorTests.swift +++ b/UnitTests/Freemium/DBP/FreemiumDBPPromotionViewCoordinatorTests.swift @@ -37,6 +37,7 @@ final class FreemiumDBPPromotionViewCoordinatorTests: XCTestCase { override func setUpWithError() throws { mockUserStateManager = MockFreemiumDBPUserStateManager() mockFeature = MockFreemiumDBPFeature() + mockFeature.featureAvailable = true mockPresenter = MockFreemiumDBPPresenter() mockPixelHandler = MockFreemiumDBPExperimentPixelHandler() @@ -97,7 +98,7 @@ final class FreemiumDBPPromotionViewCoordinatorTests: XCTestCase { // When let viewModel = sut.viewModel - viewModel.proceedAction() + viewModel!.proceedAction() // Then XCTAssertTrue(mockUserStateManager.didDismissHomePagePromotion) @@ -109,7 +110,7 @@ final class FreemiumDBPPromotionViewCoordinatorTests: XCTestCase { func testCloseAction_dismissesPromotion_andFiresPixel() { // When let viewModel = sut.viewModel - viewModel.closeAction() + viewModel!.closeAction() // Then XCTAssertTrue(mockUserStateManager.didDismissHomePagePromotion) @@ -124,7 +125,7 @@ final class FreemiumDBPPromotionViewCoordinatorTests: XCTestCase { // When let viewModel = sut.viewModel - viewModel.proceedAction() + viewModel!.proceedAction() // Then XCTAssertTrue(mockUserStateManager.didDismissHomePagePromotion) @@ -139,7 +140,7 @@ final class FreemiumDBPPromotionViewCoordinatorTests: XCTestCase { // When let viewModel = sut.viewModel - viewModel.closeAction() + viewModel!.closeAction() // Then XCTAssertTrue(mockUserStateManager.didDismissHomePagePromotion) @@ -154,7 +155,7 @@ final class FreemiumDBPPromotionViewCoordinatorTests: XCTestCase { // When let viewModel = sut.viewModel - viewModel.proceedAction() + viewModel!.proceedAction() // Then XCTAssertTrue(mockUserStateManager.didDismissHomePagePromotion) @@ -169,7 +170,7 @@ final class FreemiumDBPPromotionViewCoordinatorTests: XCTestCase { // When let viewModel = sut.viewModel - viewModel.closeAction() + viewModel!.closeAction() // Then XCTAssertTrue(mockUserStateManager.didDismissHomePagePromotion) @@ -185,7 +186,7 @@ final class FreemiumDBPPromotionViewCoordinatorTests: XCTestCase { let viewModel = sut.viewModel // Then - XCTAssertEqual(viewModel.description, UserText.homePagePromotionFreemiumDBPPostScanEngagementResultPluralDescription(resultCount: 5, brokerCount: 2)) + XCTAssertEqual(viewModel!.description, UserText.homePagePromotionFreemiumDBPPostScanEngagementResultPluralDescription(resultCount: 5, brokerCount: 2)) } @MainActor @@ -197,7 +198,19 @@ final class FreemiumDBPPromotionViewCoordinatorTests: XCTestCase { let viewModel = sut.viewModel // Then - XCTAssertEqual(viewModel.description, UserText.homePagePromotionFreemiumDBPDescriptionMarkdown) + XCTAssertEqual(viewModel!.description, UserText.homePagePromotionFreemiumDBPDescriptionMarkdown) + } + + @MainActor + func testViewModel_whenFeatureNotEnabled() { + // Given + mockFeature.featureAvailable = false + + // When + let viewModel = sut.viewModel + + // Then + XCTAssertNil(viewModel) } func testNotificationObservation_updatesPromotionVisibility() {