Files
purchases-ios/Tests/UnitTests/SubscriberAttributes/DeviceCacheSubscriberAttributesTests.swift
T
NachoSoto 7b3b03d2b3 Xcode 14.3: fixed compilation errors (#2399)
See also #2397.
Xcode 14.3 introduced the following error:
> Heterogeneous collection literal could only be inferred to '[String :
Any]'; add explicit type annotation if this is intentional

### Changes:
- Added explicit types to fix this new error
- Removed unnecessary `@preconcurrency` imports
- Added new `CustomerInfo.emptyInfo` to reduce duplication of same fake
`CustomerInfo` creation
2023-04-11 08:55:21 -07:00

656 lines
32 KiB
Swift

//
// Created by RevenueCat.
// Copyright (c) 2019 RevenueCat. All rights reserved.
//
import Nimble
import XCTest
@testable import RevenueCat
class DeviceCacheSubscriberAttributesTests: TestCase {
private var mockUserDefaults: MockUserDefaults! = nil
private var deviceCache: DeviceCache! = nil
override func setUp() {
super.setUp()
UserDefaults.resetStandardUserDefaults()
self.mockUserDefaults = MockUserDefaults()
self.deviceCache = DeviceCache(sandboxEnvironmentDetector: MockSandboxEnvironmentDetector(),
userDefaults: self.mockUserDefaults)
self.mockDateProvider = MockDateProvider(stubbedNow: self.now)
self.subscriberAttributeHeight = SubscriberAttribute(withKey: "height",
value: "183",
dateProvider: self.mockDateProvider)
self.subscriberAttributeWeight = SubscriberAttribute(withKey: "weight",
value: "160",
dateProvider: self.mockDateProvider)
}
private var now = Date(timeIntervalSince1970: 2_000_000_000) // 2033-05-18 03:33:20Z
private var mockDateProvider: MockDateProvider!
private var subscriberAttributeHeight: SubscriberAttribute!
private var subscriberAttributeWeight: SubscriberAttribute!
func testStoreSubscriberAttributeStoresCorrectly() {
let appUserID = "waldo"
self.deviceCache.store(subscriberAttribute: subscriberAttributeHeight, appUserID: appUserID)
let expectedStoreKey = "com.revenuecat.userdefaults.subscriberAttributes"
expect(self.mockUserDefaults.setObjectForKeyCalledValue) == expectedStoreKey
expect(self.mockUserDefaults.mockValues.count) == 1
guard let storedValue = self.mockUserDefaults.mockValues[expectedStoreKey],
let storedDict = storedValue as? NSDictionary else {
fatalError("didn't actually store the value or it wasn't a dictionary")
}
let expectedStoredDict = [
appUserID: [
self.subscriberAttributeHeight.key: subscriberAttributeHeight.asDictionary()
]
]
expect(storedDict) == expectedStoredDict as NSDictionary
}
func testStoreSubscriberAttributeDoesNotModifyExistingValuesWithDifferentKeys() {
let appUserID = "waldo"
self.deviceCache.store(subscriberAttribute: subscriberAttributeHeight, appUserID: appUserID)
expect(self.mockUserDefaults.mockValues.count) == 1
let subscriberAttributeWeight = SubscriberAttribute(withKey: "weight",
value: "160",
dateProvider: mockDateProvider)
self.deviceCache.store(subscriberAttribute: subscriberAttributeWeight, appUserID: appUserID)
expect(self.mockUserDefaults.mockValues.count) == 1
let expectedStoreKey = "com.revenuecat.userdefaults.subscriberAttributes"
expect(self.mockUserDefaults.setObjectForKeyCalledValue) == expectedStoreKey
guard let storedValue = self.mockUserDefaults.mockValues[expectedStoreKey],
let storedDict = storedValue as? NSDictionary else {
fatalError("didn't actually store the value or it wasn't a dictionary")
}
let expectedStoredDict = [
appUserID: [
subscriberAttributeWeight.key: subscriberAttributeWeight.asDictionary(),
subscriberAttributeHeight.key: subscriberAttributeHeight.asDictionary()
]
]
expect(storedDict) == expectedStoredDict as NSDictionary
}
func testStoreSubscriberAttributeUpdatesExistingValue() {
let oldSubscriberAttribute = SubscriberAttribute(withKey: "height",
value: "183",
dateProvider: mockDateProvider)
let appUserID = "waldo"
self.deviceCache.store(subscriberAttribute: oldSubscriberAttribute, appUserID: appUserID)
let newSubscriberAttribute = SubscriberAttribute(withKey: "height",
value: "250",
dateProvider: mockDateProvider)
self.deviceCache.store(subscriberAttribute: newSubscriberAttribute, appUserID: appUserID)
let expectedStoreKey = "com.revenuecat.userdefaults.subscriberAttributes"
expect(self.mockUserDefaults.setObjectForKeyCalledValue) == expectedStoreKey
guard let storedValue = self.mockUserDefaults.mockValues[expectedStoreKey],
let storedDict = storedValue as? NSDictionary else {
fatalError("didn't actually store the value or it wasn't a dictionary")
}
expect(self.mockUserDefaults.mockValues.count) == 1
let expectedStoredDict = [
appUserID: [
newSubscriberAttribute.key: newSubscriberAttribute.asDictionary()
]
]
expect(storedDict) == expectedStoredDict as NSDictionary
}
func testStoreSubscriberAttributesStoresCorrectly() {
let appUserID = "waldo"
self.deviceCache.store(subscriberAttributesByKey: [subscriberAttributeHeight.key: subscriberAttributeHeight,
subscriberAttributeWeight.key: subscriberAttributeWeight],
appUserID: appUserID)
let expectedStoreKey = "com.revenuecat.userdefaults.subscriberAttributes"
expect(self.mockUserDefaults.setObjectForKeyCalledValue) == expectedStoreKey
expect(self.mockUserDefaults.mockValues.count) == 1
guard let storedValue = self.mockUserDefaults.mockValues[expectedStoreKey],
let storedDict = storedValue as? NSDictionary else {
fatalError("didn't actually store the value or it wasn't a dictionary")
}
let expectedStoredDict = [
appUserID: [
subscriberAttributeWeight.key: subscriberAttributeWeight.asDictionary(),
subscriberAttributeHeight.key: subscriberAttributeHeight.asDictionary()
]
]
expect(storedDict) == expectedStoredDict as NSDictionary
}
func testStoreSubscriberAttributesNoOpIfAttributesDictIsEmpty() {
self.deviceCache.store(subscriberAttributesByKey: [:], appUserID: "waldo")
expect(self.mockUserDefaults.setObjectForKeyCalledValue).to(beNil())
expect(self.mockUserDefaults.mockValues.count) == 0
}
func testStoreSubscriberAttributesDoesNotModifyExistingValuesWithDifferentKeys() {
let otherSubscriberAttribute = SubscriberAttribute(withKey: "age",
value: "46",
dateProvider: mockDateProvider)
let appUserID = "waldo"
self.deviceCache.store(subscriberAttribute: otherSubscriberAttribute, appUserID: appUserID)
self.deviceCache.store(subscriberAttributesByKey: [subscriberAttributeHeight.key: subscriberAttributeHeight,
subscriberAttributeWeight.key: subscriberAttributeWeight],
appUserID: appUserID)
let expectedStoreKey = "com.revenuecat.userdefaults.subscriberAttributes"
expect(self.mockUserDefaults.setObjectForKeyCalledValue) == expectedStoreKey
expect(self.mockUserDefaults.mockValues.count) == 1
guard let storedValue = self.mockUserDefaults.mockValues[expectedStoreKey],
let storedDict = storedValue as? NSDictionary else {
fatalError("didn't actually store the value or it wasn't a dictionary")
}
let expectedStoredDict = [
appUserID: [
subscriberAttributeWeight.key: subscriberAttributeWeight.asDictionary(),
subscriberAttributeHeight.key: subscriberAttributeHeight.asDictionary(),
otherSubscriberAttribute.key: otherSubscriberAttribute.asDictionary()
]
]
expect(storedDict) == expectedStoredDict as NSDictionary
}
func testStoreSubscriberAttributesUpdatesExistingValue() {
let appUserID = "waldo"
self.deviceCache.store(subscriberAttribute: subscriberAttributeHeight, appUserID: appUserID)
let subscriberAttributeNewHeight = SubscriberAttribute(withKey: "height",
value: "460",
dateProvider: mockDateProvider)
self.deviceCache.store(subscriberAttributesByKey:
[subscriberAttributeNewHeight.key: subscriberAttributeNewHeight,
subscriberAttributeWeight.key: subscriberAttributeWeight],
appUserID: appUserID)
let expectedStoreKey = "com.revenuecat.userdefaults.subscriberAttributes"
expect(self.mockUserDefaults.setObjectForKeyCalledValue) == expectedStoreKey
expect(self.mockUserDefaults.mockValues.count) == 1
guard let storedValue = self.mockUserDefaults.mockValues[expectedStoreKey],
let storedDict = storedValue as? NSDictionary else {
fatalError("didn't actually store the value or it wasn't a dictionary")
}
let expectedStoredDict = [
appUserID: [
subscriberAttributeWeight.key: subscriberAttributeWeight.asDictionary(),
subscriberAttributeHeight.key: subscriberAttributeNewHeight.asDictionary()
]
]
expect(storedDict) == expectedStoredDict as NSDictionary
}
func testSubscriberAttributeWithKeyReturnsCorrectly() {
self.deviceCache.store(subscriberAttribute: subscriberAttributeHeight, appUserID: "waldo")
let storedAttribute = self.deviceCache.subscriberAttribute(attributeKey: subscriberAttributeHeight.key,
appUserID: "waldo")
expect(storedAttribute).toNot(beNil())
expect(storedAttribute).to(equal(subscriberAttributeHeight))
}
func testSubscriberAttributeWithKeyReturnsNilIfNotFound() {
expect(self.deviceCache.subscriberAttribute(attributeKey: "doesn't exist", appUserID: "whoever")).to(beNil())
}
func testUnsyncedAttributesByKeyReturnsEmptyIfNoneStored() {
expect(self.deviceCache.unsyncedAttributesByKey(appUserID: "waldo")).to(beEmpty())
}
func testUnsyncedAttributesByKeyReturnsEmptyIfNoneUnsynced() {
subscriberAttributeHeight.isSynced = true
self.deviceCache.store(subscriberAttribute: subscriberAttributeHeight, appUserID: "waldo")
expect(self.deviceCache.unsyncedAttributesByKey(appUserID: "waldo")).to(beEmpty())
}
func testUnsyncedAttributesByKeyReturnsCorrectlyWhenFound() {
let subscriberAttribute1 = SubscriberAttribute(withKey: "height",
value: "460",
isSynced: true,
setTime: now)
let subscriberAttribute2 = SubscriberAttribute(withKey: "weight",
value: "120",
isSynced: false,
setTime: now)
let subscriberAttribute3 = SubscriberAttribute(withKey: "age",
value: "66",
isSynced: false,
setTime: now)
let subscriberAttribute4 = SubscriberAttribute(withKey: "device",
value: "iPhone",
isSynced: true,
setTime: now)
self.deviceCache.store(subscriberAttributesByKey: [subscriberAttribute1.key: subscriberAttribute1,
subscriberAttribute2.key: subscriberAttribute2,
subscriberAttribute3.key: subscriberAttribute3,
subscriberAttribute4.key: subscriberAttribute4],
appUserID: "waldo")
let receivedUnsyncedAttributes = self.deviceCache.unsyncedAttributesByKey(appUserID: "waldo")
expect(receivedUnsyncedAttributes).toNot(beEmpty())
expect(receivedUnsyncedAttributes.count) == 2
expect(receivedUnsyncedAttributes[subscriberAttribute2.key]).to(equal(subscriberAttribute2))
expect(receivedUnsyncedAttributes[subscriberAttribute3.key]).to(equal(subscriberAttribute3))
}
func testNumberOfUnsyncedAttributesReturnsEmptyIfNoneStored() {
expect(self.deviceCache.numberOfUnsyncedAttributes(appUserID: "waldo")) == 0
}
func testNumberOfUnsyncedAttributesReturnsEmptyIfNoneUnsynced() {
subscriberAttributeHeight.isSynced = true
self.deviceCache.store(subscriberAttribute: subscriberAttributeHeight, appUserID: "waldo")
expect(self.deviceCache.numberOfUnsyncedAttributes(appUserID: "waldo")) == 0
}
func testNumberOfUnsyncedAttributesReturnsCorrectlyWhenFound() {
let subscriberAttribute1 = SubscriberAttribute(withKey: "height",
value: "460",
isSynced: true,
setTime: now)
let subscriberAttribute2 = SubscriberAttribute(withKey: "weight",
value: "120",
isSynced: false,
setTime: now)
let subscriberAttribute3 = SubscriberAttribute(withKey: "age",
value: "66",
isSynced: false,
setTime: now)
let subscriberAttribute4 = SubscriberAttribute(withKey: "device",
value: "iPhone",
isSynced: true,
setTime: now)
self.deviceCache.store(subscriberAttributesByKey: [subscriberAttribute1.key: subscriberAttribute1,
subscriberAttribute2.key: subscriberAttribute2,
subscriberAttribute3.key: subscriberAttribute3,
subscriberAttribute4.key: subscriberAttribute4],
appUserID: "waldo")
expect(self.deviceCache.numberOfUnsyncedAttributes(appUserID: "waldo")) == 2
}
// MARK: cleanupSubscriberAttributes
func testCleanupSubscriberAttributesMigratesIfOldAttributesFound() {
let userID1 = "userID1"
let userID2 = "userID2"
let userID1Attributes = [
"band": SubscriberAttribute(withKey: "band", value: "Led Zeppelin").asDictionary(),
"song": SubscriberAttribute(withKey: "song", value: "Whole Lotta Love").asDictionary()
]
let userID2Attributes = [
"band": SubscriberAttribute(withKey: "band", value: "Metallica").asDictionary(),
"song": SubscriberAttribute(withKey: "song", value: "Ride the Lightning").asDictionary()
]
let newSubscriberAttributes = [
userID1: userID1Attributes,
userID2: userID2Attributes
]
mockUserDefaults.mockValues = [
"com.revenuecat.userdefaults.subscriberAttributes.\(userID1)": userID1Attributes,
"com.revenuecat.userdefaults.subscriberAttributes.\(userID2)": userID2Attributes,
"com.revenuecat.userdefaults.appUserID.new": userID1
]
deviceCache.cleanupSubscriberAttributes()
let storedAttributes = self.mockUserDefaults.mockValues[
"com.revenuecat.userdefaults.subscriberAttributes"
] as? [String: [String: [String: NSObject]]]
expect(storedAttributes) == newSubscriberAttributes
}
func testCleanupSubscriberAttributesSkipsIfNoOldAttributesFound() {
let userID1 = "userID1"
let userID2 = "userID2"
let userID1Attributes = [
"band": SubscriberAttribute(withKey: "band", value: "Led Zeppelin").asDictionary(),
"song": SubscriberAttribute(withKey: "song", value: "Whole Lotta Love").asDictionary()
]
let userID2Attributes = [
"band": SubscriberAttribute(withKey: "band", value: "Metallica").asDictionary(),
"song": SubscriberAttribute(withKey: "song", value: "Ride the Lightning").asDictionary()
]
let subscriberAttributesNewKey = "com.revenuecat.userdefaults.subscriberAttributes"
let appUserIDKey = "com.revenuecat.userdefaults.appUserID.new"
let valuesBeforeMigration = [
subscriberAttributesNewKey: [
userID1: userID1Attributes,
userID2: userID2Attributes
],
appUserIDKey: userID1
] as [String: Any]
mockUserDefaults.mockValues = valuesBeforeMigration
deviceCache.cleanupSubscriberAttributes()
expect(valuesBeforeMigration[subscriberAttributesNewKey] as? [String: [String: NSDictionary]])
== mockUserDefaults.mockValues[subscriberAttributesNewKey] as? [String: [String: NSDictionary]]
expect(valuesBeforeMigration[appUserIDKey] as? String) ==
mockUserDefaults.mockValues[appUserIDKey] as? String
}
func testCleanupSubscriberAttributesDeletesOldFormatAfterFinishing() {
let userID1 = "userID1"
let userID2 = "userID2"
let userID1Attributes = [
"band": SubscriberAttribute(withKey: "band", value: "Led Zeppelin").asDictionary(),
"song": SubscriberAttribute(withKey: "song", value: "Whole Lotta Love").asDictionary()
]
let userID2Attributes = [
"band": SubscriberAttribute(withKey: "band", value: "Metallica").asDictionary(),
"song": SubscriberAttribute(withKey: "song", value: "Ride the Lightning").asDictionary()
]
let userID1AttributesKey = "com.revenuecat.userdefaults.subscriberAttributes.\(userID1)"
let userID2AttributesKey = "com.revenuecat.userdefaults.subscriberAttributes.\(userID2)"
mockUserDefaults.mockValues = [
userID1AttributesKey: userID1Attributes,
userID2AttributesKey: userID2Attributes,
"com.revenuecat.userdefaults.appUserID.new": userID1
]
self.deviceCache.cleanupSubscriberAttributes()
expect(self.mockUserDefaults.mockValues[userID1AttributesKey]).to(beNil())
expect(self.mockUserDefaults.mockValues[userID2AttributesKey]).to(beNil())
}
func testCleanupSubscriberAttributesMergesAttributesInOldAndNewFormat() {
let userID = "userID"
let legacyAttributeBand = SubscriberAttribute(withKey: "band", value: "Led Zeppelin")
let legacyAttributeSong = SubscriberAttribute(withKey: "song", value: "Whole Lotta Love")
let legacyFormatAttributes = [
legacyAttributeBand.key: legacyAttributeBand.asDictionary(),
legacyAttributeSong.key: legacyAttributeSong.asDictionary()
]
let newAttributeBand = SubscriberAttribute(withKey: "band", value: "Metallica")
let newAttributeDrummer = SubscriberAttribute(withKey: "drummer", value: "Lars Ulrich")
let newFormatAttributes = [
newAttributeBand.key: newAttributeBand.asDictionary(),
newAttributeDrummer.key: newAttributeDrummer.asDictionary()
]
let legacyAttributesKey = "com.revenuecat.userdefaults.subscriberAttributes.\(userID)"
let newAttributesKey = "com.revenuecat.userdefaults.subscriberAttributes"
let appUserIDKey = "com.revenuecat.userdefaults.appUserID.new"
mockUserDefaults.mockValues = [
legacyAttributesKey: legacyFormatAttributes,
newAttributesKey: [userID: newFormatAttributes],
appUserIDKey: userID
]
self.deviceCache.cleanupSubscriberAttributes()
let receivedAttributes: [String: [String: NSObject]]? =
self.mockUserDefaults.mockValues[newAttributesKey] as? [String: [String: NSObject]]
expect(receivedAttributes?[userID]).toNot(beNil())
let expectedAttributes: [String: [String: NSObject]] = [
newAttributeBand.key: newAttributeBand.asDictionary(),
newAttributeDrummer.key: newAttributeDrummer.asDictionary(),
legacyAttributeSong.key: legacyAttributeSong.asDictionary()
]
expect(receivedAttributes?[userID] as? [String: [String: NSObject]]) == expectedAttributes
}
func testCleanupSubscriberAttributesDeletesSyncedAttributesForOtherUsers() throws {
let userID1 = "userID1"
let userID2 = "userID2"
let currentUserID = "currentUserID"
let date = Date()
let unsyncedAttribute = SubscriberAttribute(
withKey: "song",
value: "Ride the Lightning",
isSynced: false,
setTime: date
)
let userID1Attributes = [
"band": SubscriberAttribute(withKey: "band", value: "Led Zeppelin", isSynced: true, setTime: date)
.asDictionary(),
"song": SubscriberAttribute(withKey: "song", value: "Whole Lotta Love", isSynced: true, setTime: date)
.asDictionary()
]
let userID2Attributes = [
"band": SubscriberAttribute(withKey: "band", value: "Metallica", isSynced: true, setTime: date)
.asDictionary(),
unsyncedAttribute.key: unsyncedAttribute.asDictionary()
]
let userID1AttributesKey = "com.revenuecat.userdefaults.subscriberAttributes.\(userID1)"
let userID2AttributesKey = "com.revenuecat.userdefaults.subscriberAttributes.\(userID2)"
mockUserDefaults.mockValues = [
userID1AttributesKey: userID1Attributes,
userID2AttributesKey: userID2Attributes,
"com.revenuecat.userdefaults.appUserID.new": currentUserID
]
self.deviceCache.cleanupSubscriberAttributes()
let subscriberAttributesNewKey = "com.revenuecat.userdefaults.subscriberAttributes"
let receivedAttributes = mockUserDefaults.mockValues[subscriberAttributesNewKey]
let unwrappedAttributes = try XCTUnwrap(receivedAttributes as? [String: [String: NSObject]])
expect(unwrappedAttributes[userID1]).to(beNil())
expect(unwrappedAttributes[userID2]).toNot(beNil())
expect(unwrappedAttributes[userID2]?[unsyncedAttribute.key] as? [String: NSObject]) ==
unsyncedAttribute.asDictionary()
}
func testCleanupSubscriberAttributesDoesntDeleteSyncedAttributesForCurrentUser() throws {
let userID1 = "userID1"
let currentUserID = "currentUserID"
let date = Date()
let unsyncedAttribute = SubscriberAttribute(
withKey: "song",
value: "Ride the Lightning",
isSynced: false,
setTime: date
)
let syncedAttribute = SubscriberAttribute(withKey: "band", value: "Metallica", isSynced: true, setTime: date)
let userID1Attributes = [
"band": SubscriberAttribute(withKey: "band", value: "Led Zeppelin", isSynced: true, setTime: date)
.asDictionary(),
"song": SubscriberAttribute(withKey: "song", value: "Whole Lotta Love", isSynced: true, setTime: date)
.asDictionary()
]
let currentUserIDAttributes = [
syncedAttribute.key: syncedAttribute.asDictionary(),
unsyncedAttribute.key: unsyncedAttribute.asDictionary()
]
let userID1AttributesKey = "com.revenuecat.userdefaults.subscriberAttributes.\(userID1)"
let currentUserIDAttributesKey = "com.revenuecat.userdefaults.subscriberAttributes.\(currentUserID)"
mockUserDefaults.mockValues = [
userID1AttributesKey: userID1Attributes,
currentUserIDAttributesKey: currentUserIDAttributes,
"com.revenuecat.userdefaults.appUserID.new": currentUserID
]
self.deviceCache.cleanupSubscriberAttributes()
let subscriberAttributesNewKey = "com.revenuecat.userdefaults.subscriberAttributes"
let receivedAttributes = mockUserDefaults.mockValues[subscriberAttributesNewKey]
let unwrappedAttributes = try XCTUnwrap(receivedAttributes as? [String: [String: NSObject]])
expect(unwrappedAttributes[userID1]).to(beNil())
expect(unwrappedAttributes[currentUserID]).toNot(beNil())
expect(unwrappedAttributes[currentUserID]?[unsyncedAttribute.key] as? [String: NSObject]) ==
unsyncedAttribute.asDictionary()
expect(unwrappedAttributes[currentUserID]?[syncedAttribute.key] as? [String: NSObject]) ==
syncedAttribute.asDictionary()
}
// MARK: unsyncedAttributesForAllUsers
func testUnsyncedAttributesByKeyForAllUsersReturnsCorrectly() {
let attributeLedZeppelin = SubscriberAttribute(withKey: "band", value: "Led Zeppelin")
let attributeWholeLottaLove = SubscriberAttribute(withKey: "song", value: "Whole Lotta Love")
let attributeMetallica = SubscriberAttribute(withKey: "band", value: "Metallica")
let attributeRideTheLightning = SubscriberAttribute(withKey: "song", value: "Ride the Lightning")
let syncedAttribute = SubscriberAttribute(withKey: "album", value: "... And Justice for All", isSynced: true,
setTime: Date())
mockUserDefaults.mockValues = [
"com.revenuecat.userdefaults.subscriberAttributes": [
"userID1": [
"band": attributeLedZeppelin.asDictionary(),
"song": attributeWholeLottaLove.asDictionary()
],
"userID2": [
"band": attributeMetallica.asDictionary(),
"song": attributeRideTheLightning.asDictionary(),
"album": syncedAttribute.asDictionary()
]
]
]
let receivedUnsyncedAttributes = self.deviceCache.unsyncedAttributesForAllUsers()
expect(receivedUnsyncedAttributes["userID1"]) == [
"band": attributeLedZeppelin,
"song": attributeWholeLottaLove
]
expect(receivedUnsyncedAttributes["userID2"]) == [
"band": attributeMetallica,
"song": attributeRideTheLightning
]
expect(receivedUnsyncedAttributes["userID2"]?.keys).notTo(contain("album"))
}
func testUnsyncedAttributesByKeyForAllUsersOnlyIncludesUsersWithUnsyncedAttributes() {
let attributeLedZeppelin = SubscriberAttribute(withKey: "band", value: "Led Zeppelin")
let attributeWholeLottaLove = SubscriberAttribute(withKey: "song", value: "Whole Lotta Love")
let syncedAttribute = SubscriberAttribute(withKey: "album", value: "... And Justice for All", isSynced: true,
setTime: Date())
mockUserDefaults.mockValues = [
"com.revenuecat.userdefaults.subscriberAttributes": [
"userID1": [
"band": attributeLedZeppelin.asDictionary(),
"song": attributeWholeLottaLove.asDictionary()
],
"userID2": [
"album": syncedAttribute.asDictionary()
]
]
]
let receivedUnsyncedAttributes = self.deviceCache.unsyncedAttributesForAllUsers()
expect(receivedUnsyncedAttributes["userID1"]) == [
"band": attributeLedZeppelin,
"song": attributeWholeLottaLove
]
expect(receivedUnsyncedAttributes["userID2"]).to(beNil())
}
// MARK: deleteAttributesIfSyncedForAppUserID
func testDeleteAttributesIfSyncedForAppUserIDDeletesIfSynced() {
let userID = "userID"
let subscriberAttributes = [
userID: [
"band": SubscriberAttribute(withKey: "band",
value: "Led Zeppelin",
isSynced: true,
setTime: Date()).asDictionary(),
"song": SubscriberAttribute(withKey: "song",
value: "Whole Lotta Love",
isSynced: true,
setTime: Date()).asDictionary()
]
]
mockUserDefaults.mockValues = [
"com.revenuecat.userdefaults.subscriberAttributes": subscriberAttributes
]
self.deviceCache.deleteAttributesIfSynced(appUserID: userID)
let storedAttributes: [String: [String: [String: NSObject]]]? = self.mockUserDefaults.mockValues[
"com.revenuecat.userdefaults.subscriberAttributes"
] as? [String: [String: [String: NSObject]]]
expect(storedAttributes?["userID"]).to(beNil())
}
func testDeleteAttributesIfSyncedForAppUserIDDoesntAffectOtherUserIDs() {
let userIDToDelete = "userIDToDelete"
let userIDWithUnsyncedAttributes = "userIDWithUnsyncedAttributes"
let subscriberAttributes: [String: [String: [String: NSObject]]] = [
userIDToDelete: [
"band": SubscriberAttribute(withKey: "band",
value: "Led Zeppelin",
isSynced: true,
setTime: Date()).asDictionary(),
"song": SubscriberAttribute(withKey: "song",
value: "Whole Lotta Love",
isSynced: true,
setTime: Date()).asDictionary()
],
userIDWithUnsyncedAttributes: [
"band": SubscriberAttribute(withKey: "band",
value: "Metallica").asDictionary()
]
]
mockUserDefaults.mockValues = [
"com.revenuecat.userdefaults.subscriberAttributes": subscriberAttributes
]
self.deviceCache.deleteAttributesIfSynced(appUserID: userIDToDelete)
let storedAttributes: [String: [String: [String: NSObject]]]? = self.mockUserDefaults.mockValues[
"com.revenuecat.userdefaults.subscriberAttributes"
] as? [String: [String: [String: NSObject]]]
expect(storedAttributes?[userIDWithUnsyncedAttributes]) == subscriberAttributes[userIDWithUnsyncedAttributes]
}
func testDeleteAttributesIfSyncedForAppUserIDDoesntDeleteIfNotSynced() {
let userID = "userID"
let subscriberAttributes = [
userID: [
"band": SubscriberAttribute(withKey: "band", value: "Led Zeppelin").asDictionary(),
"song": SubscriberAttribute(withKey: "song", value: "Whole Lotta Love").asDictionary()
]
]
mockUserDefaults.mockValues = [
"com.revenuecat.userdefaults.subscriberAttributes": subscriberAttributes
]
self.deviceCache.deleteAttributesIfSynced(appUserID: userID)
let valuesAfterCallingDelete: [String: [String: [String: NSObject]]]? = mockUserDefaults
.mockValues["com.revenuecat.userdefaults.subscriberAttributes"] as? [String: [String: [String: NSObject]]]
expect(valuesAfterCallingDelete) == subscriberAttributes
}
}