Skip to content

Commit d3161bf

Browse files
authored
[Woo POS][Surveys] Store in-app if survey notification has been scheduled (#16233)
2 parents 98d4ad1 + 7a73f6f commit d3161bf

File tree

7 files changed

+176
-12
lines changed

7 files changed

+176
-12
lines changed

Modules/Sources/Storage/Model/Copiable/Models+Copiable.generated.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ extension Storage.GeneralAppSettings {
6464
featureAnnouncementCampaignSettings: CopiableProp<[FeatureAnnouncementCampaign: FeatureAnnouncementCampaignSettings]> = .copy,
6565
sitesWithAtLeastOneIPPTransactionFinished: CopiableProp<Set<Int64>> = .copy,
6666
isEUShippingNoticeDismissed: CopiableProp<Bool> = .copy,
67-
isCustomFieldsTopBannerDismissed: CopiableProp<Bool> = .copy
67+
isCustomFieldsTopBannerDismissed: CopiableProp<Bool> = .copy,
68+
isPOSSurveyNotificationScheduled: CopiableProp<Bool> = .copy
6869
) -> Storage.GeneralAppSettings {
6970
let installationDate = installationDate ?? self.installationDate
7071
let feedbacks = feedbacks ?? self.feedbacks
@@ -77,6 +78,7 @@ extension Storage.GeneralAppSettings {
7778
let sitesWithAtLeastOneIPPTransactionFinished = sitesWithAtLeastOneIPPTransactionFinished ?? self.sitesWithAtLeastOneIPPTransactionFinished
7879
let isEUShippingNoticeDismissed = isEUShippingNoticeDismissed ?? self.isEUShippingNoticeDismissed
7980
let isCustomFieldsTopBannerDismissed = isCustomFieldsTopBannerDismissed ?? self.isCustomFieldsTopBannerDismissed
81+
let isPOSSurveyNotificationScheduled = isPOSSurveyNotificationScheduled ?? self.isPOSSurveyNotificationScheduled
8082

8183
return Storage.GeneralAppSettings(
8284
installationDate: installationDate,
@@ -89,7 +91,8 @@ extension Storage.GeneralAppSettings {
8991
featureAnnouncementCampaignSettings: featureAnnouncementCampaignSettings,
9092
sitesWithAtLeastOneIPPTransactionFinished: sitesWithAtLeastOneIPPTransactionFinished,
9193
isEUShippingNoticeDismissed: isEUShippingNoticeDismissed,
92-
isCustomFieldsTopBannerDismissed: isCustomFieldsTopBannerDismissed
94+
isCustomFieldsTopBannerDismissed: isCustomFieldsTopBannerDismissed,
95+
isPOSSurveyNotificationScheduled: isPOSSurveyNotificationScheduled
9396
)
9497
}
9598
}

Modules/Sources/Storage/Model/GeneralAppSettings.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ public struct GeneralAppSettings: Codable, Equatable, GeneratedCopiable {
5656
///
5757
public var isCustomFieldsTopBannerDismissed: Bool
5858

59+
/// Whether the Point of Sale survey notification has been scheduled
60+
///
61+
public var isPOSSurveyNotificationScheduled: Bool
62+
5963
public init(installationDate: Date?,
6064
feedbacks: [FeedbackType: FeedbackSettings],
6165
isViewAddOnsSwitchEnabled: Bool,
@@ -66,7 +70,8 @@ public struct GeneralAppSettings: Codable, Equatable, GeneratedCopiable {
6670
featureAnnouncementCampaignSettings: [FeatureAnnouncementCampaign: FeatureAnnouncementCampaignSettings],
6771
sitesWithAtLeastOneIPPTransactionFinished: Set<Int64>,
6872
isEUShippingNoticeDismissed: Bool,
69-
isCustomFieldsTopBannerDismissed: Bool) {
73+
isCustomFieldsTopBannerDismissed: Bool,
74+
isPOSSurveyNotificationScheduled: Bool) {
7075
self.installationDate = installationDate
7176
self.feedbacks = feedbacks
7277
self.isViewAddOnsSwitchEnabled = isViewAddOnsSwitchEnabled
@@ -78,6 +83,7 @@ public struct GeneralAppSettings: Codable, Equatable, GeneratedCopiable {
7883
self.sitesWithAtLeastOneIPPTransactionFinished = sitesWithAtLeastOneIPPTransactionFinished
7984
self.isEUShippingNoticeDismissed = isEUShippingNoticeDismissed
8085
self.isCustomFieldsTopBannerDismissed = isCustomFieldsTopBannerDismissed
86+
self.isPOSSurveyNotificationScheduled = isPOSSurveyNotificationScheduled
8187
}
8288

8389
public static var `default`: Self {
@@ -90,7 +96,8 @@ public struct GeneralAppSettings: Codable, Equatable, GeneratedCopiable {
9096
featureAnnouncementCampaignSettings: [:],
9197
sitesWithAtLeastOneIPPTransactionFinished: [],
9298
isEUShippingNoticeDismissed: false,
93-
isCustomFieldsTopBannerDismissed: false)
99+
isCustomFieldsTopBannerDismissed: false,
100+
isPOSSurveyNotificationScheduled: false)
94101
}
95102

96103
/// Returns the status of a given feedback type. If the feedback is not stored in the feedback array. it is assumed that it has a pending status.
@@ -120,7 +127,8 @@ public struct GeneralAppSettings: Codable, Equatable, GeneratedCopiable {
120127
featureAnnouncementCampaignSettings: featureAnnouncementCampaignSettings,
121128
sitesWithAtLeastOneIPPTransactionFinished: sitesWithAtLeastOneIPPTransactionFinished,
122129
isEUShippingNoticeDismissed: isEUShippingNoticeDismissed,
123-
isCustomFieldsTopBannerDismissed: isCustomFieldsTopBannerDismissed
130+
isCustomFieldsTopBannerDismissed: isCustomFieldsTopBannerDismissed,
131+
isPOSSurveyNotificationScheduled: isPOSSurveyNotificationScheduled
124132
)
125133
}
126134

@@ -141,7 +149,8 @@ public struct GeneralAppSettings: Codable, Equatable, GeneratedCopiable {
141149
featureAnnouncementCampaignSettings: updatedSettings,
142150
sitesWithAtLeastOneIPPTransactionFinished: sitesWithAtLeastOneIPPTransactionFinished,
143151
isEUShippingNoticeDismissed: isEUShippingNoticeDismissed,
144-
isCustomFieldsTopBannerDismissed: isCustomFieldsTopBannerDismissed
152+
isCustomFieldsTopBannerDismissed: isCustomFieldsTopBannerDismissed,
153+
isPOSSurveyNotificationScheduled: isPOSSurveyNotificationScheduled
145154
)
146155
}
147156
}
@@ -167,7 +176,7 @@ extension GeneralAppSettings {
167176
forKey: .sitesWithAtLeastOneIPPTransactionFinished) ?? Set<Int64>([])
168177
self.isEUShippingNoticeDismissed = try container.decodeIfPresent(Bool.self, forKey: .isEUShippingNoticeDismissed) ?? false
169178
self.isCustomFieldsTopBannerDismissed = try container.decodeIfPresent(Bool.self, forKey: .isCustomFieldsTopBannerDismissed) ?? false
170-
179+
self.isPOSSurveyNotificationScheduled = try container.decodeIfPresent(Bool.self, forKey: .isPOSSurveyNotificationScheduled) ?? false
171180
// Decode new properties with `decodeIfPresent` and provide a default value if necessary.
172181
}
173182
}

Modules/Sources/Yosemite/Actions/AppSettingsAction.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,4 +366,18 @@ public enum AppSettingsAction: Action {
366366
/// Loads Loads the state of the App Passwords Experiment feature
367367
///
368368
case getAppPasswordsExperimentSettingState(onCompletion: (Bool) -> Void)
369+
370+
// MARK: - Point of Sale Surveys
371+
372+
/// Sets the POS survey notification as scheduled
373+
///
374+
case setPOSSurveyNotificationScheduled(onCompletion: (Result<Void, Error>) -> Void)
375+
376+
/// Gets whether the POS survey notification has been scheduled
377+
///
378+
case getPOSSurveyNotificationScheduled(onCompletion: (Bool) -> Void)
379+
380+
/// Resets the POS survey notification scheduled state
381+
/// At the moment this one is used for testing only. To remove in WOOMOB-1480
382+
case resetPOSSurveyNotificationScheduled(onCompletion: (Result<Void, Error>) -> Void)
369383
}

Modules/Sources/Yosemite/Stores/AppSettingsStore.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,12 @@ public class AppSettingsStore: Store {
293293
setAppPasswordsExperimentSettingEnabled(isOn: value, onCompletion: onCompletion)
294294
case .getAppPasswordsExperimentSettingState(let onCompletion):
295295
getAppPasswordsExperimentSettingEnabled(onCompletion: onCompletion)
296+
case .setPOSSurveyNotificationScheduled(onCompletion: let onCompletion):
297+
setPOSSurveyNotificationScheduled(onCompletion: onCompletion)
298+
case .getPOSSurveyNotificationScheduled(onCompletion: let onCompletion):
299+
getPOSSurveyNotificationScheduled(onCompletion: onCompletion)
300+
case .resetPOSSurveyNotificationScheduled(onCompletion: let onCompletion):
301+
resetPOSSurveyNotificationScheduled(onCompletion: onCompletion)
296302
}
297303
}
298304
}
@@ -1290,6 +1296,32 @@ private extension AppSettingsStore {
12901296
}
12911297
}
12921298

1299+
// MARK: - Point of Sale surveys
1300+
//
1301+
private extension AppSettingsStore {
1302+
func setPOSSurveyNotificationScheduled(onCompletion: (Result<Void, Error>) -> Void) {
1303+
do {
1304+
try generalAppSettings.setValue(true, for: \.isPOSSurveyNotificationScheduled)
1305+
onCompletion(.success(()))
1306+
} catch {
1307+
onCompletion(.failure(error))
1308+
}
1309+
}
1310+
1311+
func getPOSSurveyNotificationScheduled(onCompletion: (Bool) -> Void) {
1312+
onCompletion(generalAppSettings.value(for: \.isPOSSurveyNotificationScheduled))
1313+
}
1314+
1315+
func resetPOSSurveyNotificationScheduled(onCompletion: (Result<Void, Error>) -> Void) {
1316+
do {
1317+
try generalAppSettings.setValue(false, for: \.isPOSSurveyNotificationScheduled)
1318+
onCompletion(.success(()))
1319+
} catch {
1320+
onCompletion(.failure(error))
1321+
}
1322+
}
1323+
}
1324+
12931325
// MARK: - Errors
12941326

12951327
/// Errors

Modules/Tests/StorageTests/Model/AppSettings/GeneralAppSettingsTests.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ final class GeneralAppSettingsTests: XCTestCase {
5151
XCTAssertEqual(newSettings.feedbacks[.general], newFeedback)
5252
}
5353

54+
func test_isPOSSurveyNotificationScheduled_defaults_to_false() {
55+
// Given
56+
let settings = createGeneralAppSettings()
57+
58+
// Then
59+
XCTAssertFalse(settings.isPOSSurveyNotificationScheduled)
60+
}
61+
5462
func test_updating_properties_to_generalAppSettings_does_not_breaks_decoding() throws {
5563
// Given
5664
let installationDate = Date(timeIntervalSince1970: 1630314000) // Mon Aug 30 2021 09:00:00 UTC+0000
@@ -63,6 +71,7 @@ final class GeneralAppSettingsTests: XCTestCase {
6371
FeatureAnnouncementCampaignSettings(dismissedDate: Date(), remindAfter: nil)]
6472
let sitesWithAtLeastOneIPPTransactionFinished: Set<Int64> = [1234, 123, 12, 1]
6573
let isCustomFieldsTopBannerDismissed = true
74+
let isPOSSurveyNotificationScheduled = true
6675
let previousSettings = GeneralAppSettings(installationDate: installationDate,
6776
feedbacks: feedbackSettings,
6877
isViewAddOnsSwitchEnabled: true,
@@ -73,13 +82,15 @@ final class GeneralAppSettingsTests: XCTestCase {
7382
featureAnnouncementCampaignSettings: featureAnnouncementCampaignSettings,
7483
sitesWithAtLeastOneIPPTransactionFinished: sitesWithAtLeastOneIPPTransactionFinished,
7584
isEUShippingNoticeDismissed: false,
76-
isCustomFieldsTopBannerDismissed: isCustomFieldsTopBannerDismissed)
85+
isCustomFieldsTopBannerDismissed: isCustomFieldsTopBannerDismissed,
86+
isPOSSurveyNotificationScheduled: isPOSSurveyNotificationScheduled)
7787

7888
let previousEncodedSettings = try JSONEncoder().encode(previousSettings)
7989
var previousSettingsJson = try JSONSerialization.jsonObject(with: previousEncodedSettings, options: .allowFragments) as? [String: Any]
8090

8191
// When
8292
previousSettingsJson?.removeValue(forKey: "isViewAddOnsSwitchEnabled")
93+
previousSettingsJson?.removeValue(forKey: "isPOSSurveyNotificationScheduled")
8394
let newEncodedSettings = try JSONSerialization.data(withJSONObject: previousSettingsJson as Any, options: .fragmentsAllowed)
8495
let newSettings = try JSONDecoder().decode(GeneralAppSettings.self, from: newEncodedSettings)
8596

@@ -93,6 +104,7 @@ final class GeneralAppSettingsTests: XCTestCase {
93104
assertEqual(newSettings.featureAnnouncementCampaignSettings, featureAnnouncementCampaignSettings)
94105
assertEqual(newSettings.sitesWithAtLeastOneIPPTransactionFinished, sitesWithAtLeastOneIPPTransactionFinished)
95106
assertEqual(newSettings.isCustomFieldsTopBannerDismissed, isCustomFieldsTopBannerDismissed)
107+
assertEqual(newSettings.isPOSSurveyNotificationScheduled, false)
96108
}
97109
}
98110

@@ -122,6 +134,7 @@ private extension GeneralAppSettingsTests {
122134
featureAnnouncementCampaignSettings: featureAnnouncementCampaignSettings,
123135
sitesWithAtLeastOneIPPTransactionFinished: sitesWithAtLeastOneIPPTransactionFinished,
124136
isEUShippingNoticeDismissed: isEUShippingNoticeDismissed,
125-
isCustomFieldsTopBannerDismissed: isCustomFieldsTopBannerDismissed)
137+
isCustomFieldsTopBannerDismissed: isCustomFieldsTopBannerDismissed,
138+
isPOSSurveyNotificationScheduled: false)
126139
}
127140
}

Modules/Tests/YosemiteTests/Stores/AppSettings/InAppFeedbackCardVisibilityUseCaseTests.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,8 @@ private extension InAppFeedbackCardVisibilityUseCaseTests {
244244
featureAnnouncementCampaignSettings: [:],
245245
sitesWithAtLeastOneIPPTransactionFinished: [],
246246
isEUShippingNoticeDismissed: false,
247-
isCustomFieldsTopBannerDismissed: false)
247+
isCustomFieldsTopBannerDismissed: false,
248+
isPOSSurveyNotificationScheduled: false)
248249
return settings
249250
}
250251
}

Modules/Tests/YosemiteTests/Stores/AppSettingsStoreTests.swift

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,96 @@ extension AppSettingsStoreTests {
15061506
// Then
15071507
XCTAssertNil(loadedOrderStatus)
15081508
}
1509+
1510+
// MARK: - Point of Sale Survey Notification
1511+
1512+
func test_getPOSSurveyNotificationScheduled_returns_false_on_new_generalAppSettings() throws {
1513+
// Given
1514+
try fileStorage?.deleteFile(at: expectedGeneralAppSettingsFileURL)
1515+
1516+
// When
1517+
let result: Bool = waitFor { promise in
1518+
let action = AppSettingsAction.getPOSSurveyNotificationScheduled { isScheduled in
1519+
promise(isScheduled)
1520+
}
1521+
self.subject?.onAction(action)
1522+
}
1523+
1524+
// Then
1525+
XCTAssertFalse(result)
1526+
}
1527+
1528+
func test_getPOSSurveyNotificationScheduled_returns_true_after_setting_as_scheduled() throws {
1529+
// Given
1530+
try fileStorage?.deleteFile(at: expectedGeneralAppSettingsFileURL)
1531+
let setAction = AppSettingsAction.setPOSSurveyNotificationScheduled { _ in }
1532+
subject?.onAction(setAction)
1533+
1534+
// When
1535+
let result: Bool = waitFor { promise in
1536+
let action = AppSettingsAction.getPOSSurveyNotificationScheduled { isScheduled in
1537+
promise(isScheduled)
1538+
}
1539+
self.subject?.onAction(action)
1540+
}
1541+
1542+
// Then
1543+
XCTAssertTrue(result)
1544+
}
1545+
1546+
func test_setPOSSurveyNotificationScheduled_stores_value_correctly() throws {
1547+
// Given
1548+
try fileStorage?.deleteFile(at: expectedGeneralAppSettingsFileURL)
1549+
1550+
// When
1551+
var result: Result<Void, Error>?
1552+
let action = AppSettingsAction.setPOSSurveyNotificationScheduled { aResult in
1553+
result = aResult
1554+
}
1555+
subject?.onAction(action)
1556+
1557+
// Then
1558+
XCTAssertTrue(try XCTUnwrap(result).isSuccess)
1559+
1560+
let savedSettings: GeneralAppSettings = try XCTUnwrap(fileStorage?.data(for: expectedGeneralAppSettingsFileURL))
1561+
XCTAssertTrue(savedSettings.isPOSSurveyNotificationScheduled)
1562+
}
1563+
1564+
func test_resetPOSSurveyNotificationScheduled_resets_to_false_after_being_set_to_true() throws {
1565+
// Given
1566+
try fileStorage?.deleteFile(at: expectedGeneralAppSettingsFileURL)
1567+
1568+
// 1. Set to true
1569+
let setAction = AppSettingsAction.setPOSSurveyNotificationScheduled { _ in }
1570+
subject?.onAction(setAction)
1571+
1572+
// 2. Verify it's true
1573+
let checkBeforeReset: Bool = waitFor { promise in
1574+
let action = AppSettingsAction.getPOSSurveyNotificationScheduled { isScheduled in
1575+
promise(isScheduled)
1576+
}
1577+
self.subject?.onAction(action)
1578+
}
1579+
XCTAssertTrue(checkBeforeReset)
1580+
1581+
// When - 3. Reset it
1582+
var resetResult: Result<Void, Error>?
1583+
let resetAction = AppSettingsAction.resetPOSSurveyNotificationScheduled { aResult in
1584+
resetResult = aResult
1585+
}
1586+
subject?.onAction(resetAction)
1587+
1588+
// Then - 4. Verify it's false
1589+
XCTAssertTrue(try XCTUnwrap(resetResult).isSuccess)
1590+
1591+
let checkAfterReset: Bool = waitFor { promise in
1592+
let action = AppSettingsAction.getPOSSurveyNotificationScheduled { isScheduled in
1593+
promise(isScheduled)
1594+
}
1595+
self.subject?.onAction(action)
1596+
}
1597+
XCTAssertFalse(checkAfterReset)
1598+
}
15091599
}
15101600

15111601
// MARK: - Utils
@@ -1527,7 +1617,8 @@ private extension AppSettingsStoreTests {
15271617
featureAnnouncementCampaignSettings: [:],
15281618
sitesWithAtLeastOneIPPTransactionFinished: [],
15291619
isEUShippingNoticeDismissed: false,
1530-
isCustomFieldsTopBannerDismissed: false
1620+
isCustomFieldsTopBannerDismissed: false,
1621+
isPOSSurveyNotificationScheduled: false
15311622
)
15321623
return (settings, feedback)
15331624
}
@@ -1542,7 +1633,8 @@ private extension AppSettingsStoreTests {
15421633
featureAnnouncementCampaignSettings: featureAnnouncementCampaignSettings,
15431634
sitesWithAtLeastOneIPPTransactionFinished: [],
15441635
isEUShippingNoticeDismissed: false,
1545-
isCustomFieldsTopBannerDismissed: false
1636+
isCustomFieldsTopBannerDismissed: false,
1637+
isPOSSurveyNotificationScheduled: false
15461638
)
15471639
return settings
15481640
}

0 commit comments

Comments
 (0)