Skip to content

Commit 097c751

Browse files
Merge branch 'trunk' into merge/release-10.5-into-trunk
2 parents 73e494b + dad1d1c commit 097c751

File tree

9 files changed

+101
-53
lines changed

9 files changed

+101
-53
lines changed

RELEASE-NOTES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
10.6
44
-----
55

6+
- [*] Fixed a rare crash when selecting a store in the store picker. [https://github.com/woocommerce/woocommerce-ios/pull/7765]
7+
- [*] Help center: Added help center web page with FAQs for "Not a WooCommerce site" error screen. [https://github.com/woocommerce/woocommerce-ios/pull/7767]
68

79
10.5
810
-----

WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -406,36 +406,6 @@ private extension StorePickerViewController {
406406
dismissButton.isEnabled = enabled
407407
}
408408

409-
/// This method will reload the [Selected Row]
410-
///
411-
func reloadSelectedStoreRows(afterRunning block: () -> Void) {
412-
/// Preserve: Selected and Checked Rows
413-
///
414-
var rowsToReload = [IndexPath]()
415-
416-
if let oldSiteID = currentlySelectedSite?.siteID,
417-
let oldCheckedRow = viewModel.indexPath(for: oldSiteID) {
418-
rowsToReload.append(oldCheckedRow)
419-
}
420-
421-
if let oldSelectedRow = tableView.indexPathForSelectedRow {
422-
rowsToReload.append(oldSelectedRow)
423-
}
424-
425-
/// Update the Default Store
426-
///
427-
block()
428-
429-
if let newSiteID = currentlySelectedSite?.siteID,
430-
let selectedRow = viewModel.indexPath(for: newSiteID) {
431-
rowsToReload.append(selectedRow)
432-
}
433-
434-
/// Refresh: Selected and Checked Rows
435-
///
436-
tableView.reloadRows(at: rowsToReload, with: .none)
437-
}
438-
439409
/// Re-initializes the Login Flow, forcing a logout. This may be required if the WordPress.com Account has no Stores available.
440410
///
441411
func restartAuthentication() {
@@ -699,12 +669,8 @@ extension StorePickerViewController: UITableViewDelegate {
699669
return tableView.deselectRow(at: indexPath, animated: true)
700670
}
701671

702-
reloadSelectedStoreRows() {
703-
currentlySelectedSite = site
704-
}
705-
706-
tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
707-
tableView.deselectRow(at: indexPath, animated: true)
672+
currentlySelectedSite = site
673+
tableView.reloadData()
708674
}
709675

710676
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

WooCommerce/Classes/Authentication/Epilogue/StorePickerViewModel.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -146,21 +146,6 @@ extension StorePickerViewModel {
146146
}
147147
return resultsController.safeObject(at: indexPath)
148148
}
149-
150-
/// Returns the IndexPath for the specified Site.
151-
///
152-
func indexPath(for siteID: Int64) -> IndexPath? {
153-
guard resultsController.numberOfObjects > 0 else {
154-
return nil
155-
}
156-
157-
for (sectionIndex, section) in resultsController.sections.enumerated() {
158-
if let rowIndex = section.objects.firstIndex(where: { $0.siteID == siteID }) {
159-
return IndexPath(row: rowIndex, section: sectionIndex)
160-
}
161-
}
162-
return nil
163-
}
164149
}
165150

166151
private extension StorePickerViewModel {

WooCommerce/Classes/Authentication/Navigation Exceptions/NoWooErrorViewModel.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,22 @@ final class NoWooErrorViewModel: ULErrorViewModel {
99
private let analytics: Analytics
1010
private let stores: StoresManager
1111
private let setupCompletionHandler: (Int64) -> Void
12+
private let authentication: Authentication
1213

1314
private var storePickerCoordinator: StorePickerCoordinator?
1415

1516
init(site: Site,
1617
showsConnectedStores: Bool,
1718
analytics: Analytics = ServiceLocator.analytics,
1819
stores: StoresManager = ServiceLocator.stores,
20+
authentication: Authentication = ServiceLocator.authenticationManager,
1921
onSetupCompletion: @escaping (Int64) -> Void) {
2022
self.site = site
2123
self.title = site.name
2224
self.showsConnectedStores = showsConnectedStores
2325
self.analytics = analytics
2426
self.stores = stores
27+
self.authentication = authentication
2528
self.setupCompletionHandler = onSetupCompletion
2629
}
2730

@@ -56,6 +59,11 @@ final class NoWooErrorViewModel: ULErrorViewModel {
5659

5760
let secondaryButtonTitle = Localization.secondaryButtonTitle
5861

62+
// Configures `Help` button title
63+
var rightBarButtonItemTitle: String? {
64+
Localization.helpBarButtonItemTitle
65+
}
66+
5967
// MARK: - Actions
6068
func didTapPrimaryButton(in viewController: UIViewController?) {
6169
analytics.track(.loginWooCommerceSetupButtonTapped)
@@ -89,6 +97,13 @@ final class NoWooErrorViewModel: ULErrorViewModel {
8997
storePickerCoordinator?.start()
9098
}
9199

100+
func didTapRightBarButtonItem(in viewController: UIViewController?) {
101+
guard let viewController = viewController else {
102+
return
103+
}
104+
authentication.presentSupport(from: viewController, screen: .noWooError)
105+
}
106+
92107
func viewDidLoad(_ viewController: UIViewController?) {
93108
analytics.track(.loginWooCommerceErrorShown)
94109
}
@@ -162,5 +177,9 @@ private extension NoWooErrorViewModel {
162177
comment: "Message displayed when checking whether a site has successfully installed WooCommerce")
163178
static let setupErrorMessage = NSLocalizedString("Cannot verify your site's WooCommerce installation.",
164179
comment: "Error message displayed when failed to check for WooCommerce in a site.")
180+
181+
static let helpBarButtonItemTitle = NSLocalizedString("Help",
182+
comment: "Action button for opening Help."
183+
+ "Presented when logging in with a site address that does not have WooCommerce")
165184
}
166185
}

WooCommerce/Classes/Model/CustomHelpCenterContent.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ extension CustomHelpCenterContent {
7373
/// Account mismatch / Wrong WordPress.com account screen - `WrongAccountErrorViewModel`
7474
///
7575
case wrongAccountError
76+
77+
/// No WooCommerce site error using `NoWooErrorViewModel`
78+
///
79+
case noWooError
7680
}
7781

7882
init(screen: Screen, flow: AuthenticatorAnalyticsTracker.Flow) {
@@ -87,6 +91,9 @@ extension CustomHelpCenterContent {
8791
case .wrongAccountError:
8892
step = "wrong_wordpress_account" // Matching Android `Step` value
8993
url = WooConstants.URLs.helpCenterForWrongAccountError.asURL()
94+
case .noWooError:
95+
step = "not_woo_store" // Matching Android `Step` value
96+
url = WooConstants.URLs.helpCenterForNoWooError.asURL()
9097
}
9198

9299
trackingProperties = [

WooCommerce/Classes/System/WooConstants.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ extension WooConstants {
127127
///
128128
case helpCenterForWrongAccountError = "https://woocommerce.com/document/android-ios-apps-login-help-faq/#wrong-account"
129129

130+
/// Help Center for No WooCommerce site error
131+
///
132+
case helpCenterForNoWooError = "https://woocommerce.com/document/android-ios-apps-login-help-faq/#not-a-woocommerce-site"
133+
130134
/// Help Center for "Store picker" screen
131135
///
132136
case helpCenterForStorePicker = "https://woocommerce.com/document/android-ios-apps-login-help-faq/#pick-store-after-entering-password"

WooCommerce/WooCommerceTests/Authentication/NoWooErrorViewModelTests.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,49 @@ final class NoWooErrorViewModelTests: XCTestCase {
158158
// Then
159159
XCTAssertNotNil(analyticsProvider.receivedEvents.first(where: { $0 == "login_woocommerce_error_shown" }))
160160
}
161+
162+
func test_viewmodel_provides_expected_title_for_right_bar_button_item() {
163+
// Given
164+
let site = Site.fake().copy(url: "https://test.com")
165+
let viewModel = NoWooErrorViewModel(site: site,
166+
showsConnectedStores: false,
167+
onSetupCompletion: { _ in })
168+
169+
// Then
170+
XCTAssertEqual(viewModel.rightBarButtonItemTitle, Localization.helpBarButtonItemTitle)
171+
}
172+
173+
func test_viewModel_invokes_present_support_when_the_help_button_is_tapped() throws {
174+
// Given
175+
let site = Site.fake().copy(url: "https://test.com")
176+
let mockAuthentication = MockAuthentication()
177+
let viewModel = NoWooErrorViewModel(site: site,
178+
showsConnectedStores: false,
179+
authentication: mockAuthentication,
180+
onSetupCompletion: { _ in })
181+
182+
// When
183+
viewModel.didTapRightBarButtonItem(in: UIViewController())
184+
185+
// Then
186+
XCTAssertTrue(mockAuthentication.presentSupportFromScreenInvoked)
187+
}
188+
189+
func test_viewModel_sends_correct_screen_value_in_present_support_method() throws {
190+
// Given
191+
let site = Site.fake().copy(url: "https://test.com")
192+
let mockAuthentication = MockAuthentication()
193+
let viewModel = NoWooErrorViewModel(site: site,
194+
showsConnectedStores: false,
195+
authentication: mockAuthentication,
196+
onSetupCompletion: { _ in })
197+
198+
// When
199+
viewModel.didTapRightBarButtonItem(in: UIViewController())
200+
201+
// Then
202+
XCTAssertEqual(mockAuthentication.presentSupportFromScreen, .noWooError)
203+
}
161204
}
162205

163206
private extension NoWooErrorViewModelTests {
@@ -176,5 +219,9 @@ private extension NoWooErrorViewModelTests {
176219
static let secondaryButtonTitle = NSLocalizedString("Log In With Another Account",
177220
comment: "Action button that will restart the login flow."
178221
+ "Presented when logging in with a site address that does not have WooCommerce")
222+
223+
static let helpBarButtonItemTitle = NSLocalizedString("Help",
224+
comment: "Action button for opening Help."
225+
+ "Presented when logging in with a site address that does not have WooCommerce")
179226
}
180227
}

WooCommerce/WooCommerceTests/Authentication/StorePickerViewModelTests.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ final class StorePickerViewModelTests: XCTestCase {
109109
XCTAssertEqual(viewModel.titleForSection(at: 0), Localization.connectedStore)
110110
XCTAssertEqual(viewModel.numberOfRows(inSection: 0), 1)
111111
XCTAssertEqual(viewModel.site(at: IndexPath(row: 0, section: 0))?.siteID, testSite1.siteID)
112-
XCTAssertEqual(viewModel.indexPath(for: testSite1.siteID), IndexPath(row: 0, section: 0))
113112
}
114113

115114
func test_table_view_configs_are_correct_for_list_with_both_woo_and_non_woo_sites() {
@@ -143,7 +142,6 @@ final class StorePickerViewModelTests: XCTestCase {
143142
XCTAssertEqual(viewModel.numberOfRows(inSection: 1), 1)
144143
XCTAssertEqual(viewModel.site(at: IndexPath(row: 1, section: 0))?.siteID, testSite2.siteID)
145144
XCTAssertEqual(viewModel.site(at: IndexPath(row: 0, section: 1))?.siteID, testSite3.siteID)
146-
XCTAssertEqual(viewModel.indexPath(for: testSite3.siteID), IndexPath(row: 0, section: 1))
147145
}
148146

149147
func test_trackScreenView_tracks_both_number_of_woo_and_non_woo_sites() throws {

WooCommerce/WooCommerceTests/Model/CustomHelpCenterContentTests.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,4 +269,24 @@ final class CustomHelpCenterContentTests: XCTestCase {
269269
XCTAssertEqual(sut.trackingProperties[CustomHelpCenterContent.Key.flow.rawValue], flow.rawValue)
270270
XCTAssertEqual(sut.trackingProperties[CustomHelpCenterContent.Key.url.rawValue], helpContentURL.absoluteString)
271271
}
272+
273+
// MARK: Not a WooCommerce site error screen presented using `NoWooErrorViewModel`
274+
//
275+
func test_init_screen_returns_valid_instance_for_not_a_woocommerce_site_error_screen() throws {
276+
// Given
277+
let step = "not_woo_store"
278+
let flow: AuthenticatorAnalyticsTracker.Flow = .loginWithPasswordWithMagicLinkEmphasis
279+
280+
// When
281+
let sut = CustomHelpCenterContent(screen: .noWooError, flow: flow)
282+
283+
// Then
284+
let helpContentURL = WooConstants.URLs.helpCenterForNoWooError.asURL()
285+
XCTAssertEqual(sut.url, helpContentURL)
286+
287+
// Test the `trackingProperties` dictionary values
288+
XCTAssertEqual(sut.trackingProperties[CustomHelpCenterContent.Key.step.rawValue], step)
289+
XCTAssertEqual(sut.trackingProperties[CustomHelpCenterContent.Key.flow.rawValue], flow.rawValue)
290+
XCTAssertEqual(sut.trackingProperties[CustomHelpCenterContent.Key.url.rawValue], helpContentURL.absoluteString)
291+
}
272292
}

0 commit comments

Comments
 (0)