Skip to content

Commit

Permalink
Merge branch 'release/4.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
matus-tomlein committed Nov 16, 2022
2 parents 36b53bb + b6b5331 commit ec912a5
Show file tree
Hide file tree
Showing 27 changed files with 300 additions and 48 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
Version 4.1.0 (2022-11-16)
--------------------------
Anonymise previous session ID and user identifiers in subject when user anonymisation is enabled (#720)
Add DeepLink entity referrer and url to atomic properties in ScreenView events (#718)
Fix compiler warning in SPEmitterControllerImpl to synthesize customRetryForStatusCodes (#722)
Log an error when recreating tracker after being removed (#716)
Fix links in README (#724)

Version 4.0.1 (2022-10-18)
--------------------------
Add nullable modifier to prevent crashes in track function (#713) (Thanks to @mylifeasdog)
Expand Down
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The Snowplow iOS Tracker is maintained by the Engineering team at Snowplow Analy

We are extremely grateful for all contributions we receive, whether that is reporting an issue or a change to the code which can be made in the form of a pull request.

For support requests, please use our community support Discourse forum: https://discourse.snowplowanalytics.com/.
For support requests, please use our community support Discourse forum: https://discourse.snowplow.io/.

## Setting up an Environment

Expand All @@ -16,7 +16,7 @@ You should ensure you are comfortable building and testing the existing release

### Creating an issue

The project contains an issue template which should help guiding you through the process. However, please keep in mind that support requests should go to our Discourse forum: https://discourse.snowplowanalytics.com/ and not GitHub issues.
The project contains an issue template which should help guiding you through the process. However, please keep in mind that support requests should go to our Discourse forum: https://discourse.snowplow.io/ and not GitHub issues.

It's also a good idea to log an issue before starting to work on a pull request to discuss it with the maintainers. A pull request is just one solution to a problem and it is often a good idea to talk about the problem with the maintainers first.

Expand Down Expand Up @@ -75,6 +75,6 @@ The @snowplowcla bot will guide you through the process.

### Community support requests

Please do not log an issue if you are asking for support, all of our community support requests go through our Discourse forum: https://discourse.snowplowanalytics.com/.
Please do not log an issue if you are asking for support, all of our community support requests go through our Discourse forum: https://discourse.snowplow.io/.

Posting your problem there ensures more people will see it and you should get support faster than creating a new issue on GitHub. Please do create a new issue on GitHub if you think you've found a bug though!
Posting your problem there ensures more people will see it and you should get support faster than creating a new issue on GitHub. Please do create a new issue on GitHub if you think you've found a bug though!
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

[website]: https://snowplowanalytics.com
[website]: https://snowplow.io
[snowplow]: https://github.com/snowplow/snowplow
[docs]: https://docs.snowplowanalytics.com/
[mobile-docs]: https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/mobile-trackers/
[docs]: https://docs.snowplow.io/
[mobile-docs]: https://docs.snowplow.io/docs/collecting-data/collecting-from-own-applications/mobile-trackers/

[gh-actions]: https://github.com/snowplow/snowplow-objc-tracker/actions
[gh-actions-image]: https://github.com/snowplow/snowplow-objc-tracker/workflows/Build/badge.svg
Expand All @@ -74,10 +74,10 @@ limitations under the License.
[carthage]: https://github.com/Carthage/Carthage
[carthage-badge]: https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat

[setup-docs]: https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/mobile-trackers/mobile-trackers-v3-0/quick-start-guide/#tab-ios-tracker
[setup-docs]: https://docs.snowplow.io/docs/collecting-data/collecting-from-own-applications/mobile-trackers/installation-and-set-up/
[setup-docs-image]: https://d3i6fms1cm1j0i.cloudfront.net/github/images/setup.png

[tech-docs]: https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/mobile-trackers/mobile-trackers-v3-0/introduction/
[tech-docs]: https://docs.snowplow.io/docs/collecting-data/collecting-from-own-applications/mobile-trackers/
[tech-docs-image]: https://d3i6fms1cm1j0i.cloudfront.net/github/images/techdocs.png

[api-docs]: https://snowplow.github.io/snowplow-objc-tracker/
Expand Down
20 changes: 10 additions & 10 deletions Snowplow iOSTests/Configurations/TestRemoteConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ @implementation TestRemoteConfiguration
- (void)testJSONToConfigurations {
NSString *config = @"{\"$schema\":\"http://iglucentral.com/schemas/com.snowplowanalytics.mobile/remote_config/jsonschema/1-0-0\",\"configurationVersion\":12,\"configurationBundle\": [\
{\"namespace\": \"default1\",\
\"networkConfiguration\": {\"endpoint\":\"https://fake.snowplowanalytics.com\",\"method\":\"get\"},\
\"networkConfiguration\": {\"endpoint\":\"https://fake.snowplow.io\",\"method\":\"get\"},\
\"trackerConfiguration\": {\"applicationContext\":false,\"screenContext\":false,},\
\"sessionConfiguration\": {\"backgroundTimeout\":60,\"foregroundTimeout\":60}\
},\
Expand Down Expand Up @@ -76,7 +76,7 @@ - (void)testJSONToConfigurations {
}

- (void)testDownloadConfiguration {
NSString *endpoint = @"https://fake-snowplowanalytics.com/config.json";
NSString *endpoint = @"https://fake-snowplow.io/config.json";

[[LSNocilla sharedInstance] start];
stubRequest(@"GET", endpoint)
Expand Down Expand Up @@ -126,7 +126,7 @@ - (void)testConfigurationCache {

- (void)testConfigurationProvider_notDownloading_fails {
// prepare test
NSString *endpoint = @"https://fake-snowplowanalytics.com/config.json";
NSString *endpoint = @"https://fake-snowplow.io/config.json";
SPRemoteConfiguration *remoteConfig = [[SPRemoteConfiguration alloc] initWithEndpoint:endpoint method:SPHttpMethodGet];
SPConfigurationCache *cache = [[SPConfigurationCache alloc] initWithRemoteConfiguration:remoteConfig];
[cache clearCache];
Expand All @@ -149,7 +149,7 @@ - (void)testConfigurationProvider_notDownloading_fails {

- (void)testConfigurationProvider_downloadOfWrongSchema_fails {
// prepare test
NSString *endpoint = @"https://fake-snowplowanalytics.com/config.json";
NSString *endpoint = @"https://fake-snowplow.io/config.json";
SPRemoteConfiguration *remoteConfig = [[SPRemoteConfiguration alloc] initWithEndpoint:endpoint method:SPHttpMethodGet];
SPConfigurationCache *cache = [[SPConfigurationCache alloc] initWithRemoteConfiguration:remoteConfig];
[cache clearCache];
Expand All @@ -174,7 +174,7 @@ - (void)testConfigurationProvider_downloadOfWrongSchema_fails {

- (void)testConfigurationProvider_downloadSameConfigVersionThanCached_dontUpdate {
// prepare test
NSString *endpoint = @"https://fake-snowplowanalytics.com/config.json";
NSString *endpoint = @"https://fake-snowplow.io/config.json";
SPRemoteConfiguration *remoteConfig = [[SPRemoteConfiguration alloc] initWithEndpoint:endpoint method:SPHttpMethodGet];

SPConfigurationCache *cache = [[SPConfigurationCache alloc] initWithRemoteConfiguration:remoteConfig];
Expand Down Expand Up @@ -216,7 +216,7 @@ - (void)testConfigurationProvider_downloadSameConfigVersionThanCached_dontUpdate

- (void)testConfigurationProvider_downloadHigherConfigVersionThanCached_doUpdate {
// prepare test
NSString *endpoint = @"https://fake-snowplowanalytics.com/config.json";
NSString *endpoint = @"https://fake-snowplow.io/config.json";
SPRemoteConfiguration *remoteConfig = [[SPRemoteConfiguration alloc] initWithEndpoint:endpoint method:SPHttpMethodGet];

SPConfigurationCache *cache = [[SPConfigurationCache alloc] initWithRemoteConfiguration:remoteConfig];
Expand Down Expand Up @@ -259,7 +259,7 @@ - (void)testConfigurationProvider_downloadHigherConfigVersionThanCached_doUpdate

- (void)testConfigurationProvider_justRefresh_downloadSameConfigVersionThanCached_dontUpdate {
// prepare test
NSString *endpoint = @"https://fake-snowplowanalytics.com/config.json";
NSString *endpoint = @"https://fake-snowplow.io/config.json";
SPRemoteConfiguration *remoteConfig = [[SPRemoteConfiguration alloc] initWithEndpoint:endpoint method:SPHttpMethodGet];

SPConfigurationCache *cache = [[SPConfigurationCache alloc] initWithRemoteConfiguration:remoteConfig];
Expand Down Expand Up @@ -300,8 +300,8 @@ - (void)testConfigurationProvider_justRefresh_downloadSameConfigVersionThanCache

- (void)testDoesntUseCachedConfigurationIfDifferentRemoteEndpoint {
// prepare test
NSString *endpoint = @"https://fake-snowplowanalytics.com/config.json";
SPRemoteConfiguration *cachedRemoteConfig = [[SPRemoteConfiguration alloc] initWithEndpoint:@"https://cached-snowplowanalytics.com/config.json" method:SPHttpMethodGet];
NSString *endpoint = @"https://fake-snowplow.io/config.json";
SPRemoteConfiguration *cachedRemoteConfig = [[SPRemoteConfiguration alloc] initWithEndpoint:@"https://cached-snowplow.io/config.json" method:SPHttpMethodGet];
SPRemoteConfiguration *remoteConfig = [[SPRemoteConfiguration alloc] initWithEndpoint:endpoint method:SPHttpMethodGet];

// write configuration (version 2) to cache
Expand Down Expand Up @@ -340,7 +340,7 @@ - (void)testDoesntUseCachedConfigurationIfDifferentRemoteEndpoint {
/*
- (void)testConfigurationProvider_justRefresh_downloadHigherConfigVersionThanCached_doUpdate {
// prepare test
NSString *endpoint = @"https://fake-snowplowanalytics.com/config.json";
NSString *endpoint = @"https://fake-snowplow.io/config.json";
SPRemoteConfiguration *remoteConfig = [[SPRemoteConfiguration alloc] initWithEndpoint:endpoint method:SPHttpMethodGet];
SPConfigurationCache *cache = [[SPConfigurationCache alloc] initWithRemoteConfiguration:remoteConfig];
Expand Down
20 changes: 20 additions & 0 deletions Snowplow iOSTests/Configurations/TestTrackerController.m
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,24 @@ - (void)testSubjectGeoLocationCanBeUpdated {
XCTAssertEqualObjects([NSNumber numberWithFloat:0], tracker.subject.geoLatitude);
}

- (void)testStartsNewSessionWhenChangingAnonymousTracking {
id<SPTrackerController> tracker = [SPSnowplow createTrackerWithNamespace:@"namespace" endpoint:@"https://fake-url" method:SPHttpMethodPost];
[tracker.emitter pause];

[tracker track:[[SPStructured alloc] initWithCategory:@"c" action:@"a"]];
NSString *sessionIdBefore = tracker.session.sessionId;

tracker.userAnonymisation = true;
[tracker track:[[SPStructured alloc] initWithCategory:@"c" action:@"a"]];
NSString *sessionIdAnonymous = tracker.session.sessionId;

XCTAssertFalse([sessionIdBefore isEqualToString:sessionIdAnonymous]);

tracker.userAnonymisation = false;
[tracker track:[[SPStructured alloc] initWithCategory:@"c" action:@"a"]];
NSString *sessionIdNotAnonymous = tracker.session.sessionId;

XCTAssertFalse([sessionIdAnonymous isEqualToString:sessionIdNotAnonymous]);
}

@end
6 changes: 3 additions & 3 deletions Snowplow iOSTests/Legacy Tests/LegacyTestSubject.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ - (void)tearDown {

- (void)testSubjectInit {
SPSubject * subject = [[SPSubject alloc] init];
XCTAssertNotNil([subject getStandardDict]);
XCTAssertNotNil([subject getStandardDictWithUserAnonymisation:NO]);
}

- (void)testSubjectInitWithOptions {
SPSubject * subject = [[SPSubject alloc] initWithPlatformContext:YES andGeoContext:NO];
XCTAssertNotNil([subject getPlatformDictWithUserAnonymisation:NO]);
XCTAssertNotNil([subject getStandardDict]);
XCTAssertNotNil([subject getStandardDictWithUserAnonymisation:NO]);
}

- (void)testSubjectSetterFunctions {
Expand All @@ -66,7 +66,7 @@ - (void)testSubjectSetterFunctions {
[subject setNetworkUserId:@"aNuid"];
[subject setDomainUserId:@"aDuid"];

NSDictionary * values = [[subject getStandardDict] getAsDictionary];
NSDictionary * values = [[subject getStandardDictWithUserAnonymisation:NO] getAsDictionary];

XCTAssertEqual([values valueForKey:kSPUid], @"aUserId");
XCTAssertTrue([[values valueForKey:kSPResolution] isEqualToString:@"1920x1080" ]);
Expand Down
49 changes: 49 additions & 0 deletions Snowplow iOSTests/TestEvents.m
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,55 @@ - (void)testWorkaroundForCampaignAttributionEnrichment {
XCTAssertEqualObjects(referrer, @"referrer");
}

- (void)testDeepLinkContextAndAtomicPropertiesAddedToScreenView {
// Prepare DeepLinkReceived event
SPDeepLinkReceived *deepLink = [[SPDeepLinkReceived alloc] initWithUrl:@"the_url"];
deepLink.referrer = @"the_referrer";

// Prepare ScreenView event
SPScreenView *screenView = [[SPScreenView alloc] initWithName:@"SV" screenId:[NSUUID UUID]];

// Setup tracker
SPTrackerConfiguration *trackerConfiguration = [SPTrackerConfiguration new];
trackerConfiguration.base64Encoding = NO;
trackerConfiguration.installAutotracking = NO;
SPMockEventStore *eventStore = [SPMockEventStore new];
SPNetworkConfiguration *networkConfiguration = [[SPNetworkConfiguration alloc] initWithEndpoint:@"fake-url" method:SPHttpMethodPost];
SPEmitterConfiguration *emitterConfiguration = [[SPEmitterConfiguration alloc] init];
emitterConfiguration.eventStore = eventStore;
emitterConfiguration.threadPoolSize = 10;
id<SPTrackerController> trackerController = [SPSnowplow createTrackerWithNamespace:@"namespace" network:networkConfiguration configurations:@[trackerConfiguration, emitterConfiguration]];

// Track event
[trackerController track:deepLink];
NSUUID *screenViewId = [trackerController track:screenView];
for (int i=0; eventStore.count < 2 && i < 10; i++) {
[NSThread sleepForTimeInterval:1];
}
NSArray<SPEmitterEvent *> *events = [eventStore emittableEventsWithQueryLimit:10];
[eventStore removeAllEvents];
XCTAssertEqual(2, events.count);

SPPayload *screenViewPayload = nil;
for (SPEmitterEvent *event in events) {
if ([(NSString *)[[[event payload] getAsDictionary] objectForKey:@"eid"] isEqualToString:[screenViewId UUIDString]]) {
screenViewPayload = [event payload];
}
}
XCTAssertNotNil(screenViewPayload);

// Check the DeepLink context entity properties
NSString *screenViewContext = (NSString *)[[screenViewPayload getAsDictionary] objectForKey:@"co"];
XCTAssertTrue([screenViewContext containsString:@"\"referrer\":\"the_referrer\""]);
XCTAssertTrue([screenViewContext containsString:@"\"url\":\"the_url\""]);

// Check url and referrer fields for atomic table
NSString *url = (NSString *)[[screenViewPayload getAsDictionary] objectForKey:kSPPageUrl];
NSString *referrer = (NSString *)[[screenViewPayload getAsDictionary] objectForKey:kSPPageRefr];
XCTAssertEqualObjects(url, @"the_url");
XCTAssertEqualObjects(referrer, @"the_referrer");
}

- (void)testPageView {
// Valid construction
SPPageView *event = [[SPPageView alloc] initWithPageUrl:@"DemoPageUrl"];
Expand Down
8 changes: 6 additions & 2 deletions Snowplow iOSTests/TestSession.m
Original file line number Diff line number Diff line change
Expand Up @@ -493,12 +493,16 @@ - (void)testIncrementsEventIndex {

- (void)testAnonymisesUserIdentifiers {
SPSession *session = [[SPSession alloc] initWithForegroundTimeout:3 andBackgroundTimeout:3 andTracker:nil];
[session getSessionDictWithEventId:@"event_1" eventTimestamp:1654496481345 userAnonymisation:NO];
[session startNewSession]; // create previous session ID reference

NSDictionary *withoutAnonymisation = [session getSessionDictWithEventId:@"event_1" eventTimestamp:1654496481346 userAnonymisation:NO];
NSDictionary *withoutAnonymisation = [session getSessionDictWithEventId:@"event_2" eventTimestamp:1654496481346 userAnonymisation:NO];
XCTAssertFalse([[withoutAnonymisation objectForKey:kSPSessionUserId] isEqualToString:@"00000000-0000-0000-0000-000000000000"]);
XCTAssertNotNil([withoutAnonymisation objectForKey:kSPSessionPreviousId]);

NSDictionary *withAnonymisation = [session getSessionDictWithEventId:@"event_2" eventTimestamp:1654496481347 userAnonymisation:YES];
NSDictionary *withAnonymisation = [session getSessionDictWithEventId:@"event_3" eventTimestamp:1654496481347 userAnonymisation:YES];
XCTAssertTrue([[withAnonymisation objectForKey:kSPSessionUserId] isEqualToString:@"00000000-0000-0000-0000-000000000000"]);
XCTAssertEqualObjects([NSNull null], [withAnonymisation objectForKey:kSPSessionPreviousId]);
}

// Service methods
Expand Down
15 changes: 15 additions & 0 deletions Snowplow iOSTests/TestSubject.m
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,19 @@ - (void)testDoesntReturnGeolocationContextIfDisabled {
XCTAssertNil(geoLocationDict);
}

- (void)testAnonymisesUserIdentifiers {
SPSubject *subject = [[SPSubject alloc] initWithPlatformContext:NO andGeoContext:NO];
[subject setUserId:@"aUserId"];
[subject setIpAddress:@"127.0.0.1"];
[subject setNetworkUserId:@"aNuid"];
[subject setDomainUserId:@"aDuid"];
[subject setLanguage:@"EN"];

NSDictionary *values = [[subject getStandardDictWithUserAnonymisation:YES] getAsDictionary];
XCTAssertNil([values valueForKey:kSPUid]);
XCTAssertNil([values valueForKey:kSPIpAddress]);
XCTAssertNil([values valueForKey:kSPNetworkUid]);
XCTAssertNil([values valueForKey:kSPDomainUid]);
XCTAssertEqual([values valueForKey:kSPLanguage], @"EN");
}
@end
35 changes: 35 additions & 0 deletions Snowplow iOSTests/Utils/SPMockLoggerDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// SPMockLoggerDelegate.h
// Snowplow
//
// Copyright (c) 2013-2022 Snowplow Analytics Ltd. All rights reserved.
//
// This program is licensed to you under the Apache License Version 2.0,
// and you may not use this file except in compliance with the Apache License
// Version 2.0. You may obtain a copy of the Apache License Version 2.0 at
// http://www.apache.org/licenses/LICENSE-2.0.
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the Apache License Version 2.0 is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the Apache License Version 2.0 for the specific
// language governing permissions and limitations there under.
//
// Authors: Alex Benini, Matus Tomlein
// License: Apache License Version 2.0
//

#import <Foundation/Foundation.h>
#import "SPLoggerDelegate.h"

NS_ASSUME_NONNULL_BEGIN

@interface SPMockLoggerDelegate : NSObject <SPLoggerDelegate>

@property (nonatomic) NSMutableArray<NSString *> *errorLogs;
@property (nonatomic) NSMutableArray<NSString *> *debugLogs;
@property (nonatomic) NSMutableArray<NSString *> *verboseLogs;

@end

NS_ASSUME_NONNULL_END
47 changes: 47 additions & 0 deletions Snowplow iOSTests/Utils/SPMockLoggerDelegate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// SPMockLoggerDelegate.m
// Snowplow
//
// Copyright (c) 2013-2022 Snowplow Analytics Ltd. All rights reserved.
//
// This program is licensed to you under the Apache License Version 2.0,
// and you may not use this file except in compliance with the Apache License
// Version 2.0. You may obtain a copy of the Apache License Version 2.0 at
// http://www.apache.org/licenses/LICENSE-2.0.
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the Apache License Version 2.0 is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the Apache License Version 2.0 for the specific
// language governing permissions and limitations there under.
//
// Authors: Alex Benini, Matus Tomlein
// License: Apache License Version 2.0
//

#import "SPMockLoggerDelegate.h"

@implementation SPMockLoggerDelegate

- (instancetype)init {
if (self = [super init]) {
self.errorLogs = [NSMutableArray new];
self.debugLogs = [NSMutableArray new];
self.verboseLogs = [NSMutableArray new];
}
return self;
}

- (void)debug:(nonnull NSString *)tag message:(nonnull NSString *)message {
[self.debugLogs addObject:message];
}

- (void)error:(nonnull NSString *)tag message:(nonnull NSString *)message {
[self.errorLogs addObject:message];
}

- (void)verbose:(nonnull NSString *)tag message:(nonnull NSString *)message {
[self.verboseLogs addObject:message];
}

@end
Loading

0 comments on commit ec912a5

Please sign in to comment.