Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In-app feature parity #308

Merged
merged 153 commits into from
Jan 15, 2024
Merged
Changes from 1 commit
Commits
Show all changes
153 commits
Select commit Hold shift + click to select a range
ffec62a
Add InApp Trigger and Limit Adapters and Matchers, ImpressionManager
nzagorchev Sep 2, 2023
02cd86f
Remove event name from matchCharged
nzagorchev Sep 4, 2023
69f8832
Add sample test
nzagorchev Sep 4, 2023
cbb9e62
Added trigger match evaluations and tests
Sep 10, 2023
b5732c7
added charged tests and trigger logic
Sep 11, 2023
155582d
Use ordinal for CTTriggerOperator
nzagorchev Sep 11, 2023
4c4962d
Add test for event without props
nzagorchev Sep 11, 2023
3ddc662
Add TriggerManager
nzagorchev Sep 12, 2023
8c32890
Add BatchSentDelegate, implement todos in EvaluationManager
nzagorchev Sep 12, 2023
90b0360
added whenlimits and tests
Sep 15, 2023
0fe4605
Merge branch 'client_side_inapps' of https://github.com/CleverTap/cle…
Sep 15, 2023
5be573a
Fix sorting, add tests
nzagorchev Sep 19, 2023
c7ab2a5
modified onEvery and onExact limits to use triggers instead of impres…
Sep 19, 2023
55e7623
Refactor CTInAppFCManager WIP
nzagorchev Sep 19, 2023
215641a
Merge branch 'client_side_inapps' of github.com:CleverTap/clevertap-i…
nzagorchev Sep 19, 2023
b327de3
modified days/weeks whenLimits
Sep 20, 2023
f61a3f5
Merge branch 'client_side_inapps' of https://github.com/CleverTap/cle…
Sep 20, 2023
f0419ca
Use excludeGlobalFCaps and efc
nzagorchev Sep 20, 2023
9bb1d48
Refactor CTInAppFCManager WIP 2
nzagorchev Sep 20, 2023
00bf4d1
Remove dismissedThisSession, fix inAppCounts
nzagorchev Sep 20, 2023
4d876c8
Refactor CTInAppFCManager, use current storage keys since legacy are …
nzagorchev Sep 21, 2023
b57cb47
added fetchInapps api
Sep 25, 2023
9c01915
added extra checks in trigger matches and unit tests
Sep 25, 2023
909c99f
Add InApp store
nzagorchev Sep 25, 2023
4fbae8e
Evaluate triggers and limits
nzagorchev Sep 25, 2023
4bc449e
added storage methods for inapp store
Sep 28, 2023
8f33f29
added encryption test
Sep 28, 2023
f0299f3
added plaintext and encryption inapp store getters/setters
Sep 28, 2023
af948b9
Attach to batch header using a delegate, EvaluationManager improvements
nzagorchev Sep 29, 2023
06f316f
added completion block for fetchInApps
Oct 3, 2023
681eab4
Create CTInAppDisplayManager and move all in-apps logic from CleverTap
nzagorchev Oct 5, 2023
b5ceab2
Initialize managers
nzagorchev Oct 5, 2023
dac96aa
Remove unused methods
nzagorchev Oct 5, 2023
0f3f60f
Improvements and refactoring
nzagorchev Oct 7, 2023
b188c69
added swizzle and queue managers
Oct 8, 2023
0039930
moved private methods to an internal file. added push primer manager.…
Oct 8, 2023
6d842f8
Merge pull request #298 from CleverTap/refactor_swizzle_threading
akashvercetti Oct 9, 2023
cd5e2e9
Move in-apps parse response in category, refactor CleverTapInternal
nzagorchev Oct 9, 2023
1ffacff
Move params and keys to Constants
nzagorchev Oct 9, 2023
e3969b4
Add response handler to project
nzagorchev Oct 9, 2023
5f3c1a3
Add values to Constants
nzagorchev Oct 9, 2023
1076f71
Use new limits
nzagorchev Oct 9, 2023
b25df07
Improvements
nzagorchev Oct 9, 2023
a43ae22
Check daily limits as is
nzagorchev Oct 9, 2023
7e4479e
Organize in-app imports and usages
nzagorchev Oct 9, 2023
670258f
removed duplicate notification queue
Oct 10, 2023
8769c2c
added test cases
Oct 11, 2023
f0ee654
removed some todos
Oct 11, 2023
cd8eb2c
Improve In App managers initialisation, add CTDelegateManager, refact…
nzagorchev Oct 13, 2023
84dd5a9
Fix tests
nzagorchev Oct 13, 2023
38064fa
Fix CTInAppStore
nzagorchev Oct 17, 2023
bc99593
added session manager and tests
Oct 17, 2023
f2ffd05
updated tests
Oct 18, 2023
baf419a
fixed inappfcmanager being nil in display manager
Oct 22, 2023
d4485df
fixed incorrect calls to "runningInsideAppExtension"
Oct 23, 2023
32c7838
fixed wrong method being called for inapp store
Oct 24, 2023
6d0fa4e
ImpressionManager abstract time and date
nzagorchev Oct 27, 2023
94e6ca6
Fix ImpressionManager and add tests
nzagorchev Oct 31, 2023
d6e42b6
ImpressionManager perWeek fix and more tests
nzagorchev Nov 1, 2023
5f9a306
Use constants for evtName, evtData and Items
nzagorchev Nov 1, 2023
65a854d
Rename DelegateManager, move App Launched check in a helper
nzagorchev Nov 1, 2023
a23d447
Update name
nzagorchev Nov 1, 2023
a6c7aa0
Format campaign ti to string
nzagorchev Nov 1, 2023
d81a8b1
Add LimitsMatcher tests for minute, hour, day, week
nzagorchev Nov 1, 2023
4238d30
Rewrite InAppStore and add tests
nzagorchev Nov 3, 2023
bfb2fe0
Add trigger geoRadius part1
nzagorchev Nov 5, 2023
f16a8b9
Add trigger geoRadius
nzagorchev Nov 8, 2023
62bdfa7
Do not evaluate events without eventName
nzagorchev Nov 8, 2023
93da11b
Add geoRadius tests
nzagorchev Nov 8, 2023
513ad08
Added CTInAppImagePrefetchManager class to handling preloading of images
nishant-clevertap Nov 9, 2023
5b7507f
Match triggers when value is numerical string and handle arrays
nzagorchev Nov 9, 2023
c33b64d
Fix trigger evaluations and refactor tests
nzagorchev Nov 12, 2023
99f6ce6
Move inapp_notifs to InAppStore
nzagorchev Nov 13, 2023
44f8f2d
Add nullability specifiers for InAppStore
nzagorchev Nov 14, 2023
383d481
Update storage keys format to match others
nzagorchev Nov 14, 2023
8f31ff3
Fix locale for scanner
nzagorchev Nov 15, 2023
1637728
Send inapp_evals only with events queue
nzagorchev Nov 15, 2023
9436814
Send inapp_evals only with events queue cont
nzagorchev Nov 15, 2023
8ccb66a
Fix limits matching for empty limits, tests for empty and multiple
nzagorchev Nov 15, 2023
dbedaa0
Streamline InApp notification ti parsing
nzagorchev Nov 15, 2023
f2d8ff1
TriggerManager storage per deviceId
nzagorchev Nov 16, 2023
d9b5d31
Fix suppression error if cgId is nil
nzagorchev Nov 16, 2023
c1a5dc9
Add InAppHelper for tests
nzagorchev Nov 16, 2023
ce84465
Add EvaluationManager tests
nzagorchev Nov 16, 2023
a547d80
Use InAppHelper in tests
nzagorchev Nov 16, 2023
719a4cd
Move encryption test
nzagorchev Nov 16, 2023
f884646
Add evaluated campaign ids as numbers
nzagorchev Nov 17, 2023
35c2ce3
Prevent out of bounds when removing elements in EvaluationManager
nzagorchev Nov 17, 2023
ee937eb
Add EvaluationManager tests
nzagorchev Nov 17, 2023
faddc7f
Fix SessionManager test
nzagorchev Nov 17, 2023
645fe52
Move the tests extensions into separate files
nzagorchev Nov 17, 2023
9106c41
Use deviceId for inapp_notifs storage
nzagorchev Nov 20, 2023
ac90f8e
Add InAppFCManager tests
nzagorchev Nov 20, 2023
a13d7a7
Add pragma marks
nzagorchev Nov 20, 2023
43ca0b4
Set the inAppStore
nzagorchev Nov 21, 2023
b6df198
Rename value to propertyValue
nzagorchev Nov 21, 2023
8f20a72
Use long value for impression timestamp
nzagorchev Nov 21, 2023
3fe3d9a
Bump version to 60000
nzagorchev Nov 21, 2023
0da0b6d
moved the observer handling for Push notification center delegate bac…
Nov 22, 2023
9f0c203
Fix pending notifications
nzagorchev Nov 22, 2023
3fb58e0
Get actual prop value to support campaign properties
nzagorchev Nov 22, 2023
2018455
Merge branch 'client_side_inapps' of github.com:CleverTap/clevertap-i…
nzagorchev Nov 22, 2023
3db772e
Updated SDWebImage to v5.18.5
nishant-clevertap Nov 23, 2023
059d540
Fix mdc session limit
nzagorchev Nov 23, 2023
fd3c5cb
Evaluate App Launched properties and map keys to System Props
nzagorchev Nov 24, 2023
eb894e6
minor bug fixes and improvements. removed duplicate and redundant code.
Nov 27, 2023
fbbd048
Refactor event evaluation from queueEvent
nzagorchev Nov 27, 2023
f292deb
Use constants for app fields
nzagorchev Nov 27, 2023
a650fa8
Remove campaign type - not supported for in-apps
nzagorchev Nov 28, 2023
31affe2
Evaluate contains operator for numbers and arrays
nzagorchev Nov 28, 2023
f654a58
Add tests for app launched, system, and notification properties
nzagorchev Nov 28, 2023
52139e3
fixed build errors Swift Package Manager apps
Nov 29, 2023
8656dcc
Merge branch 'client_side_inapps' of https://github.com/CleverTap/cle…
Nov 29, 2023
6975931
Linting
nzagorchev Nov 29, 2023
c63802b
Refactor fetchInAppsBlock and handle in InAppsResponseHandler
nzagorchev Nov 29, 2023
63f9ec5
Merge develop into client_side_inapps
nzagorchev Nov 29, 2023
889908a
Fix event property name validation (#303)
nzagorchev Dec 1, 2023
0ca7afd
Revert "Updated SDWebImage to v5.18.5"
nishant-clevertap Dec 4, 2023
738236e
Updated prefetch manager to use prefetchURLs API.
nishant-clevertap Dec 4, 2023
e4c72c0
Added test case for image preloading
nishant-clevertap Dec 4, 2023
c3d1aff
Added support to prefetch landscape image urls.
nishant-clevertap Dec 5, 2023
ff6291e
added more allowed class types to fix unarchive errors.
Dec 11, 2023
d8a9070
Added support to render images from disk for each in-app templates.
nishant-clevertap Dec 12, 2023
e6fa5cd
Fix equals boolean
nzagorchev Dec 12, 2023
ab388bf
Merge branch 'client_side_inapps' of https://github.com/CleverTap/cle…
nishant-clevertap Dec 13, 2023
18c426c
Image interstitial preview (#306)
nzagorchev Dec 18, 2023
0c68612
Cache evaluated server-side in-app ids and suppressed client-side in-…
nzagorchev Dec 20, 2023
7bb5a25
Merge branch 'client_side_inapps' of github.com:CleverTap/clevertap-i…
nzagorchev Dec 21, 2023
56c53a1
- Added support for storing multi user images.
nishant-clevertap Dec 26, 2023
e170a54
Add delegate manager to InAppStore
nzagorchev Dec 28, 2023
9453edf
Merge branch 'client_side_inapps' of github.com:CleverTap/clevertap-i…
nzagorchev Dec 28, 2023
1e6f0b4
- Added public api to delete images from disk cache.
nishant-clevertap Jan 3, 2024
3374f5e
Fix InAppStore initialization
nzagorchev Jan 4, 2024
a3a9437
Make default init unavailable
nzagorchev Jan 4, 2024
ae5409a
Add unit tests to ensure delegates are added and behave correctly
nzagorchev Jan 4, 2024
5ad2406
Fix inactive image assets and add tests
nzagorchev Jan 9, 2024
adaa0bc
Remove impressions and triggers for stale inapps
nzagorchev Jan 9, 2024
5a55506
Merge branch 'client_side_inapps' of github.com:CleverTap/clevertap-i…
nzagorchev Jan 9, 2024
d1ed8fd
Fix update of last deleted ts and ensure cleanup ts is expired
nzagorchev Jan 9, 2024
4165624
Updated storing image assets with accountID only
nishant-clevertap Jan 10, 2024
ad8b4bb
Merge pull request #307 from CleverTap/feat/SDK-3339/image_preloading
nishant-clevertap Jan 10, 2024
b51e3a0
feat(inApps): Add display condition for HTML in-apps to prevent showi…
nishant-clevertap Jan 10, 2024
fe6e84a
Used deviceInfo class to check network is reachable or not.
nishant-clevertap Jan 10, 2024
ee82d94
Add isOnline to DeviceInfo and use it in HTML template
nzagorchev Jan 10, 2024
9cc3212
fixed tvos errors
Jan 11, 2024
278a25a
Update storage key formats
nzagorchev Jan 11, 2024
75075d7
Fix duplicate header and use path directly
nzagorchev Jan 11, 2024
7b8944e
Unit tests improvements
nzagorchev Jan 11, 2024
abe11bd
Add more InAppFCManager tests
nzagorchev Jan 11, 2024
64e82fa
Update CHANGELOG.md
akashvercetti Jan 12, 2024
104c7f3
tvos compatibility fixes
nzagorchev Jan 12, 2024
ff1bf1b
Merge branch 'client_side_inapps' of github.com:CleverTap/clevertap-i…
nzagorchev Jan 12, 2024
a50230c
Fix display controller presented before scene became active (#309)
nzagorchev Jan 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix update of last deleted ts and ensure cleanup ts is expired
  • Loading branch information
nzagorchev committed Jan 9, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit d1ed8fd8746794c17ceb24a6a6f08c4e4c33219a
4 changes: 2 additions & 2 deletions CleverTapSDK/InApps/CTInAppImagePrefetchManager.m
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ - (void)_clearImageAssets:(BOOL)expiredOnly {
long lastDeletedTime = [self getLastDeletedTimestamp];
if (!expiredOnly) {
[self moveAssetsToInactive];
lastDeletedTime = ([self getLastDeletedTimestamp] - kDefaultInAppExpiryTime);
lastDeletedTime = ([self getLastDeletedTimestamp] - (kDefaultInAppExpiryTime + 1));
}

if ([self.inactiveImageSet allObjects].count > 0) {
@@ -151,7 +151,7 @@ - (void)removeInactiveExpiredAssets:(long)lastDeletedTime {
// 4. Update lastDeletedTime as currentTime and image assets in preference
dispatch_group_t deleteGroup = dispatch_group_create();
dispatch_queue_t deleteConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
if (lastDeletedTime > 0 && [self.inactiveImageSet count] > 0) {
if (lastDeletedTime > 0) {
long currentTime = (long) [[NSDate date] timeIntervalSince1970];
if (currentTime - lastDeletedTime > self.inAppExpiryTime) {
// Delete all inactive expired images.
2 changes: 2 additions & 0 deletions CleverTapSDKTests/InApps/CTInAppImagePrefetchManager+Tests.h
Original file line number Diff line number Diff line change
@@ -14,5 +14,7 @@
- (void)prefetchURLs:(NSArray<NSString *> *)mediaURLs;
- (NSString *)storageKeyWithSuffix:(NSString *)suffix;
- (NSArray<NSString *> *)getImageURLs:(NSArray *)csInAppNotifs;
- (void)removeInactiveExpiredAssets:(long)lastDeletedTime;
- (long)getLastDeletedTimestamp;

@end
84 changes: 69 additions & 15 deletions CleverTapSDKTests/InApps/CTInAppImagePrefetchManagerTest.m
Original file line number Diff line number Diff line change
@@ -22,7 +22,6 @@ - (void)setUp {
[super setUp];
InAppHelper *helper = [InAppHelper new];
self.prefetchManager = helper.imagePrefetchManager;

// Stub the image download request
[HTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
// Match requests with ct_test_image
@@ -39,7 +38,8 @@ - (void)setUp {
- (void)tearDown {
[super tearDown];
[HTTPStubs removeAllStubs];

[CTPreferences removeObjectForKey:[self.prefetchManager storageKeyWithSuffix:CLTAP_PREFS_CS_INAPP_ASSETS_LAST_DELETED_TS]];

XCTestExpectation *expectation = [self expectationWithDescription:@"Wait for cleanup"];
[self.prefetchManager _clearImageAssets:NO];
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC);
@@ -51,7 +51,7 @@ - (void)tearDown {
}

- (void)preloadImagesToDisk:(NSArray *)urls {
XCTestExpectation *expectation = [self expectationWithDescription:@"Image Preload to Disk Cache"];
XCTestExpectation *expectation = [self expectationWithDescription:@"Preload images"];
// Preload Images
[self.prefetchManager prefetchURLs:urls];

@@ -75,8 +75,8 @@ - (NSArray *)generateImageURLs:(int)count {
- (void)setLastDeletedPastExpiry {
// Expiration is 2 weeks
// Set the last deleted timestamp to 15 days ago
long now = (long) [[NSDate date] timeIntervalSince1970] - (60 * 60 * 24 * (2 * 7 + 1));
[CTPreferences putInt:now
long ts = (long) [[NSDate date] timeIntervalSince1970] - (60 * 60 * 24 * (2 * 7 + 1));
[CTPreferences putInt:ts
forKey:[self.prefetchManager storageKeyWithSuffix:CLTAP_PREFS_CS_INAPP_ASSETS_LAST_DELETED_TS]];
}

@@ -121,7 +121,7 @@ - (void)testImagePresentInDiskCache {
XCTAssertNotNil(image);
}

- (void)testPreloadingInAppImages {
- (void)testPreloadClientSideInAppImages {
NSArray *urls = [self generateImageURLs:2];
NSArray *csInAppNotifs = @[
@{
@@ -137,7 +137,7 @@ - (void)testPreloadingInAppImages {
}
}
];
XCTestExpectation *expectation = [self expectationWithDescription:@"Image Preload to Disk Cache"];
XCTestExpectation *expectation = [self expectationWithDescription:@"Image preload to disk cache"];
// Preload Images
[self.prefetchManager preloadClientSideInAppImages:csInAppNotifs];

@@ -152,25 +152,29 @@ - (void)testPreloadingInAppImages {
[self waitForExpectations:@[expectation] timeout:2.5];
}

- (void)testImagePresentInDiskCache3 {
- (void)testPreloadImages {
// 1. Test preloading images adds to active assets
NSArray *urls = [self generateImageURLs:3];
// Load the images to disk, new images are directly added to the active set
[self preloadImagesToDisk:@[urls[0], urls[1]]];

XCTAssertEqual([[self.prefetchManager activeImageSet] count], 2);

// 2. Test preloading already present images removes them from inactive assets
// Set the inactive URLs set
NSMutableSet *urlsSet = [[NSMutableSet alloc] initWithArray:urls];
[self.prefetchManager setInactiveImageSet:urlsSet];

//XCTestExpectation *expectation = [self expectationWithDescription:@"Image Preload to Disk Cache"];
// Load the images to disk again, so the already saved ones are removed from the inactive set
[self preloadImagesToDisk:@[urls[0], urls[1]]];

XCTAssertEqual([[self.prefetchManager activeImageSet] count], 2, @"Active images ");
XCTAssertEqual([[self.prefetchManager activeImageSet] count], 2);
XCTAssertEqual([[self.prefetchManager inactiveImageSet] count], 1);

// 3. Test preloading images triggers remove of expired assets when expiration time has come
[self setLastDeletedPastExpiry];
[self preloadImagesToDisk:@[urls[0]]];
XCTAssertEqual([[self.prefetchManager activeImageSet] count], 0, @"number of active images");
// Active assets are moved to inactive to start expiration again
XCTAssertEqual([[self.prefetchManager activeImageSet] count], 0);
XCTAssertEqual([[self.prefetchManager inactiveImageSet] count], 2);
}

@@ -182,7 +186,7 @@ - (void)testClearAllImageAssets {
XCTAssertNotNil(image);

[self.prefetchManager _clearImageAssets:NO];
XCTestExpectation *expectation = [self expectationWithDescription:@"Clear Disk Cache"];
XCTestExpectation *expectation = [self expectationWithDescription:@"Clear all assets"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
UIImage *image = [self.prefetchManager loadImageFromDisk:urls[0]];
XCTAssertNil(image);
@@ -202,7 +206,7 @@ - (void)testClearInactiveImageAssets {

[self setLastDeletedPastExpiry];
[self.prefetchManager _clearImageAssets:YES];
XCTestExpectation *expectation = [self expectationWithDescription:@"Clear Disk Cache"];
XCTestExpectation *expectation = [self expectationWithDescription:@"Clear inactive assets"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
UIImage *inactiveImage = [self.prefetchManager loadImageFromDisk:urls[0]];
XCTAssertNil(inactiveImage);
@@ -226,7 +230,7 @@ - (void)testSetImageAssetsInactiveAndClearExpired {

[self setLastDeletedPastExpiry];
[self.prefetchManager setImageAssetsInactiveAndClearExpired];
XCTestExpectation *expectation = [self expectationWithDescription:@"Clear Disk Cache"];
XCTestExpectation *expectation = [self expectationWithDescription:@"Clear disk cache"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
XCTAssertEqual([[self.prefetchManager inactiveImageSet] count], 0);
XCTAssertEqual([[self.prefetchManager activeImageSet] count], 0);
@@ -238,4 +242,54 @@ - (void)testSetImageAssetsInactiveAndClearExpired {
[self waitForExpectations:@[expectation] timeout:2.5];
}

- (void)testRemoveInactiveExpiredAssetsUpdatesDeletedTs {
long ts = (long) [[NSDate date] timeIntervalSince1970] - (60 * 60 * 24 * (2 * 7 + 1));
[CTPreferences putInt:ts
forKey:[self.prefetchManager storageKeyWithSuffix:CLTAP_PREFS_CS_INAPP_ASSETS_LAST_DELETED_TS]];
NSMutableSet *urlsSet = [[NSMutableSet alloc] initWithArray:[self generateImageURLs:4]];
[self.prefetchManager setActiveImageSet:urlsSet];
// Timestamp is expired, will trigger delete of expired assets
// There are no inactive assets to be removed
// Last deleted timestamp must be updated
// Active assets must be moved to inactive
XCTAssertEqual([[self.prefetchManager inactiveImageSet] count], 0);
[self.prefetchManager removeInactiveExpiredAssets:ts];
XCTestExpectation *expectation = [self expectationWithDescription:@"Remove expired assets"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
XCTAssertEqual([urlsSet count], [[self.prefetchManager inactiveImageSet] count]);
XCTAssertEqual(0, [[self.prefetchManager activeImageSet] count]);
XCTAssertNotEqual(ts, [self.prefetchManager getLastDeletedTimestamp]);
// Must be set to current timestamp (now and set timestamp might differ slightly)
XCTAssertTrue([[NSDate date] timeIntervalSince1970] - [self.prefetchManager getLastDeletedTimestamp] < 3);
[expectation fulfill];
});

[self waitForExpectations:@[expectation] timeout:1.5];
}

- (void)testRemoveInactiveExpiredAssetsNoop {
long ts = (long) [[NSDate date] timeIntervalSince1970] - (60 * 60 * 24 * 12); // 12 days
[CTPreferences putInt:ts
forKey:[self.prefetchManager storageKeyWithSuffix:CLTAP_PREFS_CS_INAPP_ASSETS_LAST_DELETED_TS]];
NSArray *urls = [self generateImageURLs:5];
NSMutableSet *urlsSetActive = [[NSMutableSet alloc] initWithArray:@[urls[0], urls[1]]];
[self.prefetchManager setActiveImageSet:urlsSetActive];
NSMutableSet *urlsSetInactive = [[NSMutableSet alloc] initWithArray:@[urls[2], urls[3], urls[4]]];
[self.prefetchManager setInactiveImageSet:urlsSetInactive];
// Timestamp is not expired, will not trigger delete of expired assets
// No assets must be removed
// Active and Inactive assets must remain the same
// Delete timestamp must not change
[self.prefetchManager removeInactiveExpiredAssets:ts];
XCTestExpectation *expectation = [self expectationWithDescription:@"Remove expired assets"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
XCTAssertEqual(ts, [self.prefetchManager getLastDeletedTimestamp]);
XCTAssertEqual([urlsSetActive count], [[self.prefetchManager activeImageSet] count]);
XCTAssertEqual([urlsSetInactive count], [[self.prefetchManager inactiveImageSet] count]);
[expectation fulfill];
});

[self waitForExpectations:@[expectation] timeout:1.5];
}

@end