Skip to content

Commit 1833027

Browse files
authored
Merge pull request #7552 from woocommerce/issue/7549-non-atomic-site-explanation
Site picker: Add explanation for non-Atomic sites
2 parents b462ab4 + 92da4e9 commit 1833027

File tree

4 files changed

+211
-4
lines changed

4 files changed

+211
-4
lines changed

WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -686,10 +686,16 @@ extension StorePickerViewController: UITableViewDelegate {
686686
}
687687

688688
guard site.isWooCommerceActive else {
689-
ServiceLocator.analytics.track(.sitePickerNonWooSiteTapped, withProperties: ["is_non_atomic": !site.isJetpackConnected])
690-
tableView.deselectRow(at: indexPath, animated: true)
691-
showNoWooError(for: site)
692-
return
689+
let isNonAtomicSite = !site.isJetpackConnected
690+
ServiceLocator.analytics.track(.sitePickerNonWooSiteTapped, withProperties: ["is_non_atomic": isNonAtomicSite])
691+
692+
if isNonAtomicSite {
693+
showNonAtomicSiteError(for: site)
694+
} else {
695+
showNoWooError(for: site)
696+
}
697+
698+
return tableView.deselectRow(at: indexPath, animated: true)
693699
}
694700

695701
reloadSelectedStoreRows() {
@@ -722,6 +728,13 @@ private extension StorePickerViewController {
722728
}
723729
}
724730

731+
func showNonAtomicSiteError(for site: Site) {
732+
let viewModel = NonAtomicSiteViewModel(site: site, stores: stores)
733+
let errorController = ULErrorViewController(viewModel: viewModel)
734+
navigationController?.show(errorController, sender: nil)
735+
navigationController?.setNavigationBarHidden(false, animated: true)
736+
}
737+
725738
func showNoWooError(for site: Site) {
726739
let viewModel = NoWooErrorViewModel(
727740
site: site,
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import Foundation
2+
import Yosemite
3+
4+
/// Configuration and actions for an ULErrorViewController, modelling
5+
/// an error when the user tries to log in to the app with a simple WP.com site.
6+
struct NonAtomicSiteViewModel: ULErrorViewModel {
7+
private let site: Site
8+
private let stores: StoresManager
9+
10+
var title: String? { site.name }
11+
12+
let image: UIImage = .loginNoWordPressError
13+
14+
var text: NSAttributedString {
15+
let font: UIFont = .body
16+
let boldFont: UIFont = font.bold
17+
18+
let boldSiteAddress = NSAttributedString(string: site.url.trimHTTPScheme(),
19+
attributes: [.font: boldFont])
20+
let message = NSMutableAttributedString(string: Localization.errorMessage)
21+
22+
message.replaceFirstOccurrence(of: "%@", with: boldSiteAddress)
23+
24+
return message
25+
}
26+
27+
let isAuxiliaryButtonHidden = true
28+
let auxiliaryButtonTitle = ""
29+
30+
let isPrimaryButtonHidden = true
31+
let primaryButtonTitle = ""
32+
33+
let secondaryButtonTitle = Localization.secondaryButtonTitle
34+
35+
init(site: Site, stores: StoresManager = ServiceLocator.stores) {
36+
self.site = site
37+
self.stores = stores
38+
}
39+
40+
func viewDidLoad(_ viewController: UIViewController?) {
41+
// no-op
42+
}
43+
44+
func didTapPrimaryButton(in viewController: UIViewController?) {
45+
// no-op
46+
}
47+
48+
func didTapSecondaryButton(in viewController: UIViewController?) {
49+
stores.deauthenticate()
50+
viewController?.navigationController?.popToRootViewController(animated: true)
51+
}
52+
53+
func didTapAuxiliaryButton(in viewController: UIViewController?) {
54+
// no-op
55+
}
56+
}
57+
58+
private extension NonAtomicSiteViewModel {
59+
enum Localization {
60+
static let errorMessage = NSLocalizedString(
61+
"It seems that your site %@ is a simple WordPress.com site that cannot install plugins. Please upgrade your plan to use WooCommerce.",
62+
comment: "An error message displayed when the user tries to log in to the app with a simple WP.com site. " +
63+
"Reads like: It seems that your site google.com is a simple WordPress.com site that cannot install plugins. " +
64+
"Please upgrade your plan to use WooCommerce."
65+
)
66+
67+
static let secondaryButtonTitle = NSLocalizedString("Log In With Another Account",
68+
comment: "Action button that will restart the login flow."
69+
+ "Presented when the user tries to log in to the app with a simple WP.com site.")
70+
}
71+
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,6 +1635,8 @@
16351635
DE279BAF26EA03EA002BA963 /* ShippingLabelSinglePackageViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE279BAE26EA03EA002BA963 /* ShippingLabelSinglePackageViewModelTests.swift */; };
16361636
DE279BB126EA184A002BA963 /* ShippingLabelPackageListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE279BB026EA184A002BA963 /* ShippingLabelPackageListViewModel.swift */; };
16371637
DE2BF4FD2846192B00FBE68A /* CouponAllowedEmailsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE2BF4FC2846192B00FBE68A /* CouponAllowedEmailsViewModelTests.swift */; };
1638+
DE3404E828B4B96800CF0D97 /* NonAtomicSiteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3404E728B4B96800CF0D97 /* NonAtomicSiteViewModel.swift */; };
1639+
DE3404EA28B4C1D000CF0D97 /* NonAtomicSiteViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3404E928B4C1D000CF0D97 /* NonAtomicSiteViewModelTests.swift */; };
16381640
DE34771327F174C8009CA300 /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE34771227F174C8009CA300 /* StatusView.swift */; };
16391641
DE3877E0283B68CF0075D87E /* DiscountTypeBottomSheetListSelectorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3877DF283B68CF0075D87E /* DiscountTypeBottomSheetListSelectorCommand.swift */; };
16401642
DE3877E2283CCBC20075D87E /* BottomSheetListSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3877E1283CCBC20075D87E /* BottomSheetListSelector.swift */; };
@@ -3486,6 +3488,8 @@
34863488
DE279BAE26EA03EA002BA963 /* ShippingLabelSinglePackageViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelSinglePackageViewModelTests.swift; sourceTree = "<group>"; };
34873489
DE279BB026EA184A002BA963 /* ShippingLabelPackageListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPackageListViewModel.swift; sourceTree = "<group>"; };
34883490
DE2BF4FC2846192B00FBE68A /* CouponAllowedEmailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CouponAllowedEmailsViewModelTests.swift; sourceTree = "<group>"; };
3491+
DE3404E728B4B96800CF0D97 /* NonAtomicSiteViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonAtomicSiteViewModel.swift; sourceTree = "<group>"; };
3492+
DE3404E928B4C1D000CF0D97 /* NonAtomicSiteViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonAtomicSiteViewModelTests.swift; sourceTree = "<group>"; };
34893493
DE34771227F174C8009CA300 /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = "<group>"; };
34903494
DE3877DF283B68CF0075D87E /* DiscountTypeBottomSheetListSelectorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscountTypeBottomSheetListSelectorCommand.swift; sourceTree = "<group>"; };
34913495
DE3877E1283CCBC20075D87E /* BottomSheetListSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomSheetListSelector.swift; sourceTree = "<group>"; };
@@ -5842,6 +5846,7 @@
58425846
DE61978C289A5326005E4362 /* WooSetupWebViewModelTests.swift */,
58435847
DE61978E289A5674005E4362 /* NoWooErrorViewModelTests.swift */,
58445848
DE61979428A25842005E4362 /* StorePickerViewModelTests.swift */,
5849+
DE3404E928B4C1D000CF0D97 /* NonAtomicSiteViewModelTests.swift */,
58455850
);
58465851
path = Authentication;
58475852
sourceTree = "<group>";
@@ -7964,6 +7969,7 @@
79647969
DEF36DE72898D3CF00178AC2 /* PluginSetupWebViewModel.swift */,
79657970
DEFA3D922897D8930076FAE1 /* NoWooErrorViewModel.swift */,
79667971
DEFB3010289904E300A620B3 /* WooSetupWebViewModel.swift */,
7972+
DE3404E728B4B96800CF0D97 /* NonAtomicSiteViewModel.swift */,
79677973
);
79687974
path = "Navigation Exceptions";
79697975
sourceTree = "<group>";
@@ -10061,6 +10067,7 @@
1006110067
021FB44C24A5E3B00090E144 /* ProductListMultiSelectorSearchUICommand.swift in Sources */,
1006210068
456C7EEB25EE71F10016CBC6 /* ShippingLabelSuggestedAddressViewController.swift in Sources */,
1006310069
D89CFE9025B256E9000E4683 /* ULAccountMatcher.swift in Sources */,
10070+
DE3404E828B4B96800CF0D97 /* NonAtomicSiteViewModel.swift in Sources */,
1006410071
D8815B0126385E3F00EDAD62 /* CardPresentModalTapCard.swift in Sources */,
1006510072
773077EE251E943700178696 /* ProductDownloadFileViewController.swift in Sources */,
1006610073
45D1CF4523BAC2A500945A36 /* ProductTaxClassListSelectorDataSource.swift in Sources */,
@@ -10447,6 +10454,7 @@
1044710454
093B265927DF15100026F92D /* BulkUpdatePriceViewControllerTests.swift in Sources */,
1044810455
2614EB1C24EB611200968D4B /* TopBannerViewTests.swift in Sources */,
1044910456
B5DBF3C320E1484400B53AED /* StoresManagerTests.swift in Sources */,
10457+
DE3404EA28B4C1D000CF0D97 /* NonAtomicSiteViewModelTests.swift in Sources */,
1045010458
02E493EF245C1087000AEA9E /* ProductFormBottomSheetListSelectorCommandTests.swift in Sources */,
1045110459
D88D5A3B230B5D63007B6E01 /* MockAnalyticsProvider.swift in Sources */,
1045210460
B9C4AB29280031AB007008B8 /* PaymentReceiptEmailParameterDeterminerTests.swift in Sources */,
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import XCTest
2+
import Yosemite
3+
@testable import WooCommerce
4+
5+
final class NonAtomicSiteViewModelTests: XCTestCase {
6+
7+
func test_viewmodel_provides_expected_title() {
8+
// Given
9+
let site = Site.fake().copy(name: "Test")
10+
let viewModel = NonAtomicSiteViewModel(site: site)
11+
12+
// When
13+
let title = viewModel.title
14+
15+
// Then
16+
XCTAssertEqual(title, site.name)
17+
}
18+
19+
func test_viewmodel_provides_expected_image() {
20+
// Given
21+
let viewModel = NonAtomicSiteViewModel(site: Site.fake())
22+
23+
// When
24+
let image = viewModel.image
25+
26+
// Then
27+
XCTAssertEqual(image, Expectations.image)
28+
}
29+
30+
func test_viewmodel_provides_expected_error_message() {
31+
// Given
32+
let site = Site.fake().copy(url: "https://test.com")
33+
let viewModel = NonAtomicSiteViewModel(site: site)
34+
let expectation = Expectations.errorMessage.replacingOccurrences(of: "%@", with: "test.com")
35+
36+
// When
37+
let errorMessage = viewModel.text.string
38+
39+
// Then
40+
XCTAssertEqual(errorMessage, expectation)
41+
}
42+
43+
func test_viewmodel_provides_expected_visibility_for_auxiliary_button() {
44+
// Given
45+
let viewModel = NonAtomicSiteViewModel(site: Site.fake())
46+
47+
// When
48+
let isHidden = viewModel.isAuxiliaryButtonHidden
49+
50+
// Then
51+
XCTAssertTrue(isHidden)
52+
}
53+
54+
func test_viewmodel_provides_expected_title_for_auxiliary_button() {
55+
// Given
56+
let viewModel = NonAtomicSiteViewModel(site: Site.fake())
57+
58+
// When
59+
let auxiliaryButtonTitle = viewModel.auxiliaryButtonTitle
60+
61+
// Then
62+
XCTAssertEqual(auxiliaryButtonTitle, "")
63+
}
64+
65+
func test_viewmodel_provides_expected_visibility_for_primary_button() {
66+
// Given
67+
let viewModel = NonAtomicSiteViewModel(site: Site.fake())
68+
69+
// When
70+
let isHidden = viewModel.isPrimaryButtonHidden
71+
72+
// Then
73+
XCTAssertTrue(isHidden)
74+
}
75+
76+
func test_viewmodel_provides_expected_title_for_primary_button() {
77+
// Given
78+
let viewModel = NonAtomicSiteViewModel(site: Site.fake())
79+
80+
// When
81+
let primaryButtonTitle = viewModel.primaryButtonTitle
82+
83+
// Then
84+
XCTAssertEqual(primaryButtonTitle, "")
85+
}
86+
87+
func test_viewmodel_provides_expected_title_for_secondary_button() {
88+
// Given
89+
let viewModel = NonAtomicSiteViewModel(site: Site.fake())
90+
91+
// When
92+
let secondaryButtonTitle = viewModel.secondaryButtonTitle
93+
94+
// Then
95+
XCTAssertEqual(secondaryButtonTitle, Expectations.secondaryButtonTitle)
96+
}
97+
98+
}
99+
100+
private extension NonAtomicSiteViewModelTests {
101+
enum Expectations {
102+
static let image = UIImage.loginNoWordPressError
103+
104+
static let errorMessage = NSLocalizedString(
105+
"It seems that your site %@ is a simple WordPress.com site that cannot install plugins. Please upgrade your plan to use WooCommerce.",
106+
comment: "An error message displayed when the user tries to log in to the app with a simple WP.com site. " +
107+
"Reads like: It seems that your site google.com is a simple WordPress.com site that cannot install plugins. " +
108+
"Please upgrade your plan to use WooCommerce."
109+
)
110+
111+
static let secondaryButtonTitle = NSLocalizedString("Log In With Another Account",
112+
comment: "Action button that will restart the login flow."
113+
+ "Presented when the user tries to log in to the app with a simple WP.com site.")
114+
}
115+
}

0 commit comments

Comments
 (0)