Skip to content

Commit

Permalink
Domains Dashboard Card: Presentation Criteria (#20423)
Browse files Browse the repository at this point in the history
* Implement directDomainPurchaseDashboardCard remote feature flag

* Created DomainsDashboardCardHelper with shouldShowCard logic

- Added blog and user conditions based on which we show domains dashboard card
- Added DomainsDashboardCardHelperTests to tests the different cases

* Integrate domain dashboard card presentation logic into DashboardCard

* Use blog.domainList instead of blog.domains to only include non-wpcom domains

* Refresh domains when blog is synced

Until now, domains were only refreshed when the blog details were opened, however, now we need to have blog domains list up-to-date

* Remove extra empty line
  • Loading branch information
staskus authored Mar 29, 2023
1 parent 0562505 commit 4eaf88b
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 1 deletion.
10 changes: 9 additions & 1 deletion WordPress/Classes/Services/BlogService.m
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,15 @@ - (void)syncBlogAndAllMetadata:(Blog *)blog completionHandler:(void (^)(void))co
[blazeService getStatusFor:blog completion:^{
dispatch_group_leave(syncGroup);
}];


dispatch_group_enter(syncGroup);
[self refreshDomainsFor:blog success:^{
dispatch_group_leave(syncGroup);
} failure:^(NSError * _Nonnull error) {
DDLogError(@"Failed refreshing domains: %@", error);
dispatch_group_leave(syncGroup);
}];

// When everything has left the syncGroup (all calls have ended with success
// or failure) perform the completionHandler
dispatch_group_notify(syncGroup, dispatch_get_main_queue(),^{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ enum RemoteFeatureFlag: Int, CaseIterable {
case wordPressSupportForum
case blaze
case wordPressIndividualPluginSupport
case directDomainsPurchaseDashboardCard

var defaultValue: Bool {
switch self {
Expand All @@ -38,6 +39,8 @@ enum RemoteFeatureFlag: Int, CaseIterable {
return false
case .wordPressIndividualPluginSupport:
return AppConfiguration.isWordPress
case .directDomainsPurchaseDashboardCard:
return false
}
}

Expand Down Expand Up @@ -66,6 +69,8 @@ enum RemoteFeatureFlag: Int, CaseIterable {
return "blaze"
case .wordPressIndividualPluginSupport:
return "wp_individual_plugin_overlay"
case .directDomainsPurchaseDashboardCard:
return "direct_domain_purchase_dashboard_card"
}
}

Expand Down Expand Up @@ -93,6 +98,8 @@ enum RemoteFeatureFlag: Int, CaseIterable {
return "Blaze"
case .wordPressIndividualPluginSupport:
return "Jetpack Individual Plugin Support for WordPress"
case .directDomainsPurchaseDashboardCard:
return "Direct Domains Purchase Dashboard Card"
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Foundation

final class DomainsDashboardCardHelper {

/// Checks conditions for showing domain dashboard cards
static func shouldShowCard(
for blog: Blog,
isJetpack: Bool = AppConfiguration.isJetpack,
featureFlagEnabled: Bool = RemoteFeatureFlag.directDomainsPurchaseDashboardCard.enabled()
) -> Bool {
guard isJetpack, featureFlagEnabled else {
return false
}

let isHostedAtWPcom = blog.isHostedAtWPcom
let isAtomic = blog.isAtomic()
let isAdmin = blog.isAdmin
let hasOtherDomains = blog.domainsList.count > 0
let hasDomainCredit = blog.hasDomainCredit

return (isHostedAtWPcom || isAtomic) && isAdmin && !hasOtherDomains && !hasDomainCredit
}

static func hideCard(for blog: Blog?) {
guard let blog,
let siteID = blog.dotComID?.intValue else {
DDLogError("Domains Dashboard Card: error hiding the card.")
return
}

BlogDashboardPersonalizationService(siteID: siteID)
.setEnabled(false, for: .domainsDashboardCard)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum DashboardCard: String, CaseIterable {
case quickStart
case prompts
case blaze
case domainsDashboardCard
case todaysStats = "todays_stats"
case draftPosts
case scheduledPosts
Expand Down Expand Up @@ -48,6 +49,9 @@ enum DashboardCard: String, CaseIterable {
return DashboardBadgeCell.self
case .blaze:
return DashboardBlazeCardCell.self
case .domainsDashboardCard:
/// TODO
return DashboardFailureCardCell.self
}
}

Expand Down Expand Up @@ -82,6 +86,8 @@ enum DashboardCard: String, CaseIterable {
return JetpackBrandingVisibility.all.enabled
case .blaze:
return BlazeHelper.shouldShowCard(for: blog)
case .domainsDashboardCard:
return DomainsDashboardCardHelper.shouldShowCard(for: blog)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ private func makeKey(for card: DashboardCard) -> String? {
// have a "-card" component in the key name. Keeping it like this to
// avoid having to migrate data.
return "prompts-enabled-site-settings"
case .domainsDashboardCard:
return "domains-dashboard-enabled-site-settings"
case .quickStart, .jetpackBadge, .jetpackInstall, .nextPost, .createPost, .failure, .ghost:
return nil
}
Expand Down
18 changes: 18 additions & 0 deletions WordPress/WordPress.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@
0107E18D29000E3300DE87DB /* AppStyleGuide.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD2538E26116A1600EDAF88 /* AppStyleGuide.swift */; };
0107E18E29000EA100DE87DB /* UIColor+MurielColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435B762122973D0600511813 /* UIColor+MurielColors.swift */; };
0107E18F29000EA200DE87DB /* UIColor+MurielColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435B762122973D0600511813 /* UIColor+MurielColors.swift */; };
0118968F29D1EB5E00D34BA9 /* DomainsDashboardCardHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0118968E29D1EB5E00D34BA9 /* DomainsDashboardCardHelper.swift */; };
0118969129D1F2FE00D34BA9 /* DomainsDashboardCardHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0118969029D1F2FE00D34BA9 /* DomainsDashboardCardHelperTests.swift */; };
0118969229D2CA6F00D34BA9 /* DomainsDashboardCardHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0118968E29D1EB5E00D34BA9 /* DomainsDashboardCardHelper.swift */; };
0141929C2983F0A300CAEDB0 /* SupportConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0141929B2983F0A300CAEDB0 /* SupportConfiguration.swift */; };
0141929D2983F0A300CAEDB0 /* SupportConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0141929B2983F0A300CAEDB0 /* SupportConfiguration.swift */; };
014192A02983F5E800CAEDB0 /* SupportConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0141929F2983F5E800CAEDB0 /* SupportConfigurationTests.swift */; };
Expand Down Expand Up @@ -5692,6 +5695,8 @@
0107E1832900043200DE87DB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0107E1842900059300DE87DB /* LocalizationConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationConfiguration.swift; sourceTree = "<group>"; };
0107E1862900065400DE87DB /* LocalizationConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalizationConfiguration.swift; sourceTree = "<group>"; };
0118968E29D1EB5E00D34BA9 /* DomainsDashboardCardHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainsDashboardCardHelper.swift; sourceTree = "<group>"; };
0118969029D1F2FE00D34BA9 /* DomainsDashboardCardHelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainsDashboardCardHelperTests.swift; sourceTree = "<group>"; };
011A2815DB0DE7E3973CBC0E /* Pods-Apps-Jetpack.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Apps-Jetpack.release.xcconfig"; path = "../Pods/Target Support Files/Pods-Apps-Jetpack/Pods-Apps-Jetpack.release.xcconfig"; sourceTree = "<group>"; };
0141929B2983F0A300CAEDB0 /* SupportConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportConfiguration.swift; sourceTree = "<group>"; };
0141929F2983F5E800CAEDB0 /* SupportConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportConfigurationTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -9525,6 +9530,14 @@
path = JetpackStatsWidgets;
sourceTree = "<group>";
};
0118968D29D1EAC900D34BA9 /* Domains */ = {
isa = PBXGroup;
children = (
0118968E29D1EB5E00D34BA9 /* DomainsDashboardCardHelper.swift */,
);
path = Domains;
sourceTree = "<group>";
};
0141929E2983F5D900CAEDB0 /* Support */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -13366,6 +13379,7 @@
8B4DDF23278F3AED0022494D /* Cards */ = {
isa = PBXGroup;
children = (
0118968D29D1EAC900D34BA9 /* Domains */,
FA98B61429A3B71E0071AAE8 /* Blaze */,
FE18495627F5ACA400D26879 /* Prompts */,
8B92D69427CD51CE001F5371 /* Ghost */,
Expand Down Expand Up @@ -13413,6 +13427,7 @@
806E53E327E01CFE0064315E /* DashboardStatsViewModelTests.swift */,
80B016CE27FEBDC900D15566 /* DashboardCardTests.swift */,
80EF9283280CFEB60064A971 /* DashboardPostsSyncManagerTests.swift */,
0118969029D1F2FE00D34BA9 /* DomainsDashboardCardHelperTests.swift */,
);
path = Dashboard;
sourceTree = "<group>";
Expand Down Expand Up @@ -21333,6 +21348,7 @@
08E39B4528A3DEB200874CB8 /* UserPersistentStoreFactory.swift in Sources */,
C81CCD67243AECA200A83E27 /* TenorGIFCollection.swift in Sources */,
4AD5656C28E3D0670054C676 /* ReaderPost+Helper.swift in Sources */,
0118968F29D1EB5E00D34BA9 /* DomainsDashboardCardHelper.swift in Sources */,
E137B1661F8B77D4006AC7FC /* WebNavigationDelegate.swift in Sources */,
937D9A0F19F83812007B9D5F /* WordPress-22-23.xcmappingmodel in Sources */,
803DE81328FFAE36007D4E9C /* RemoteConfigStore.swift in Sources */,
Expand Down Expand Up @@ -23202,6 +23218,7 @@
933D1F471EA64108009FB462 /* TestingAppDelegate.m in Sources */,
5789E5C822D7D40800333698 /* AztecPostViewControllerAttachmentTests.swift in Sources */,
0A9687BC28B40771009DCD2F /* FullScreenCommentReplyViewModelMock.swift in Sources */,
0118969129D1F2FE00D34BA9 /* DomainsDashboardCardHelperTests.swift in Sources */,
400199AB222590E100EB0906 /* AllTimeStatsRecordValueTests.swift in Sources */,
C8567498243F41CA001A995E /* MockTenorService.swift in Sources */,
1D19C56629C9DB0A00FB0087 /* GutenbergVideoPressUploadProcessorTests.swift in Sources */,
Expand Down Expand Up @@ -25076,6 +25093,7 @@
F1C740C026B1D4D2005D0809 /* StoreSandboxSecretScreen.swift in Sources */,
801D94F02919E7D70051993E /* JetpackFullscreenOverlayGeneralViewModel.swift in Sources */,
FABB25FF2602FC2C00C8785C /* RegisterDomainDetailsViewModel+RowDefinitions.swift in Sources */,
0118969229D2CA6F00D34BA9 /* DomainsDashboardCardHelper.swift in Sources */,
98E082A02637545C00537BF1 /* PostService+Likes.swift in Sources */,
FABB26002602FC2C00C8785C /* GravatarProfile.swift in Sources */,
FABB26012602FC2C00C8785C /* ReaderShareAction.swift in Sources */,
Expand Down
17 changes: 17 additions & 0 deletions WordPress/WordPressTest/BlogBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,23 @@ final class BlogBuilder {
return self
}

func with(registeredDomainCount: Int) -> Self {
var domains: [ManagedDomain] = []
for _ in 0..<registeredDomainCount {
let domain = NSEntityDescription.insertNewObject(forEntityName: ManagedDomain.entityName(), into: context) as! ManagedDomain
domain.domainType = .registered
domains.append(domain)
}

blog.domains = Set(domains)
return self
}

func with(hasDomainCredit: Bool) -> Self {
blog.hasDomainCredit = hasDomainCredit
return self
}

@discardableResult
func build() -> Blog {
return blog
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import XCTest
@testable import WordPress

final class DomainsDashboardCardHelperTests: CoreDataTestCase {
func testShouldShowCardEnabledFeatureFlagAndHostedAtWPcom() {
let blog = BlogBuilder(mainContext)
.isHostedAtWPcom()
.with(atomic: false)
.with(isAdmin: true)
.with(registeredDomainCount: 0)
.with(hasDomainCredit: false)
.build()

let result = DomainsDashboardCardHelper.shouldShowCard(for: blog, isJetpack: true, featureFlagEnabled: true)

XCTAssertTrue(result, "Card should show for WPcom hosted blogs")
}

func testShouldShowCardEnabledFeatureFlagAndAtomic() {
let blog = BlogBuilder(mainContext)
.isNotHostedAtWPcom()
.with(atomic: true)
.with(isAdmin: true)
.with(registeredDomainCount: 0)
.with(hasDomainCredit: false)
.build()

let result = DomainsDashboardCardHelper.shouldShowCard(for: blog, isJetpack: true, featureFlagEnabled: true)

XCTAssertTrue(result, "Card should show for Atomic blogs")
}

func testShouldNotShowCardNotAdmin() {
let blog = BlogBuilder(mainContext)
.isHostedAtWPcom()
.with(atomic: false)
.with(isAdmin: false)
.with(registeredDomainCount: 0)
.with(hasDomainCredit: false)
.build()

let result = DomainsDashboardCardHelper.shouldShowCard(for: blog, isJetpack: true, featureFlagEnabled: true)

XCTAssertFalse(result, "Card should not show for non-admin users")
}

func testShouldNotShowCardHasOtherDomains() {
let blog = BlogBuilder(mainContext)
.isHostedAtWPcom()
.with(atomic: false)
.with(isAdmin: true)
.with(registeredDomainCount: 2)
.with(hasDomainCredit: false)
.build()

let result = DomainsDashboardCardHelper.shouldShowCard(for: blog, isJetpack: true, featureFlagEnabled: true)

XCTAssertFalse(result, "Card should not show for blogs with more than one domain")
}

func testShouldNotShowCardHasDomainCredit() {
let blog = BlogBuilder(mainContext)
.isHostedAtWPcom()
.with(atomic: false)
.with(isAdmin: true)
.with(registeredDomainCount: 0)
.with(hasDomainCredit: true)
.build()

let result = DomainsDashboardCardHelper.shouldShowCard(for: blog, isJetpack: true, featureFlagEnabled: true)

XCTAssertFalse(result, "Card should not show for blogs with domain credit")
}

func testShouldNotShowCardFeatureFlagDisabled() {
let blog = BlogBuilder(mainContext)
.isHostedAtWPcom()
.with(atomic: false)
.with(isAdmin: true)
.with(registeredDomainCount: 0)
.with(hasDomainCredit: false)
.build()

let result = DomainsDashboardCardHelper.shouldShowCard(for: blog, isJetpack: true, featureFlagEnabled: false)

XCTAssertFalse(result, "Card should not show when the feature flag is disabled")
}
}

0 comments on commit 4eaf88b

Please sign in to comment.