diff --git a/Demo/Demo.xcconfig b/Demo/Demo.xcconfig index ef844c85..0af629ae 100644 --- a/Demo/Demo.xcconfig +++ b/Demo/Demo.xcconfig @@ -1,5 +1,5 @@ // Version information -MARKETING_VERSION = 8.2.0 +MARKETING_VERSION = 9.0.0 // Deployment targets IPHONEOS_DEPLOYMENT_TARGET = 12.0 diff --git a/Demo/SRGAnalytics-demo.xcodeproj/project.pbxproj b/Demo/SRGAnalytics-demo.xcodeproj/project.pbxproj index 3bb5cb7a..7cba3777 100644 --- a/Demo/SRGAnalytics-demo.xcodeproj/project.pbxproj +++ b/Demo/SRGAnalytics-demo.xcodeproj/project.pbxproj @@ -438,6 +438,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 6FD65C75233235A10016CCFE /* Demo.xcconfig */; buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "$(APP_ICONS_SOURCE)"; CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_MODULES = YES; DEBUG_INFORMATION_FORMAT = dwarf; @@ -459,6 +460,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 6FD65C75233235A10016CCFE /* Demo.xcconfig */; buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "$(APP_ICONS_SOURCE)"; CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_MODULES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; diff --git a/Demo/SRGAnalytics-demo.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Demo/SRGAnalytics-demo.xcworkspace/xcshareddata/swiftpm/Package.resolved index 29f738dd..075237e5 100644 --- a/Demo/SRGAnalytics-demo.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Demo/SRGAnalytics-demo.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -19,6 +19,15 @@ "version": "1.3.2-srg6" } }, + { + "package": "TagCommander SDK V5", + "repositoryURL": "https://github.com/CommandersAct/iOSV5.git", + "state": { + "branch": null, + "revision": "2e56e97db76d55657d0dc7d13e2fcd81ce4eaa6c", + "version": "5.3.3" + } + }, { "package": "libextobjc", "repositoryURL": "https://github.com/SRGSSR/libextobjc.git", @@ -118,24 +127,6 @@ "version": "3.1.0" } }, - { - "package": "TCCore", - "repositoryURL": "https://github.com/SRGSSR/TCCore-xcframework-apple.git", - "state": { - "branch": null, - "revision": "eb686883e63af28174472a09eda97acf07179c88", - "version": "4.5.4-srg5" - } - }, - { - "package": "TCSDK", - "repositoryURL": "https://github.com/SRGSSR/TCSDK-xcframework-apple.git", - "state": { - "branch": null, - "revision": "c4becb0b250258b78cb46225af5e269da834db5a", - "version": "4.4.1-srg5" - } - }, { "package": "UICKeyChainStore", "repositoryURL": "https://github.com/kishikawakatsumi/UICKeyChainStore.git", diff --git a/Demo/Sources/Application/AppDelegate.m b/Demo/Sources/Application/AppDelegate.m index 2c2a73b4..ffd05196 100644 --- a/Demo/Sources/Application/AppDelegate.m +++ b/Demo/Sources/Application/AppDelegate.m @@ -31,9 +31,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( [TCDebug setDebugLevel:TCLogLevel_Verbose]; [TCDebug setNotificationLog:YES]; - SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierRTS - container:10 - siteName:@"rts-app-test-v"]; + SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierSRG + sourceKey:@"39ae8f94-595c-4ca4-81f7-fb7748bd3f04" + siteName:@"srg-app-analytics-apple"]; [SRGAnalyticsTracker.sharedTracker startWithConfiguration:configuration dataSource:self identityService:SRGIdentityService.currentIdentityService]; diff --git a/Demo/Sources/Demos/DemosViewController.m b/Demo/Sources/Demos/DemosViewController.m index 0e858c3d..115d2679 100644 --- a/Demo/Sources/Demos/DemosViewController.m +++ b/Demo/Sources/Demos/DemosViewController.m @@ -235,7 +235,9 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath SRGMediaPlayerViewController *playerViewController = [[SRGMediaPlayerViewController alloc] init]; playerViewController.modalPresentationStyle = UIModalPresentationFullScreen; - playerViewController.allowsPictureInPicturePlayback = NO; + if (@available(tvOS 14.0, *)) { + playerViewController.allowsPictureInPicturePlayback = NO; + } [playerViewController.controller playURL:URL atPosition:nil withSegments:nil analyticsLabels:labels userInfo:nil]; [self presentViewController:playerViewController animated:YES completion:nil]; break; @@ -265,6 +267,11 @@ - (NSString *)srg_pageViewTitle return @"demos"; } +- (NSString *)srg_pageViewType +{ + return @"landing_page"; +} + #pragma mark UI - (void)reloadData diff --git a/Demo/Sources/Simple/SimpleViewController.m b/Demo/Sources/Simple/SimpleViewController.m index 462f039c..42048fe1 100644 --- a/Demo/Sources/Simple/SimpleViewController.m +++ b/Demo/Sources/Simple/SimpleViewController.m @@ -71,6 +71,11 @@ - (NSString *)srg_pageViewTitle return self.title; } +- (NSString *)srg_pageViewType +{ + return @"detail_page"; +} + - (NSArray *)srg_pageViewLevels { return self.levels; diff --git a/Demo/Sources/SwiftUI/SwiftUIView.swift b/Demo/Sources/SwiftUI/SwiftUIView.swift index 3ecdd49d..1282736f 100644 --- a/Demo/Sources/SwiftUI/SwiftUIView.swift +++ b/Demo/Sources/SwiftUI/SwiftUIView.swift @@ -20,7 +20,7 @@ struct SwiftUIView: View { Button(action: { /* Nothing. Just to have something focusable on tvOS */}) { Text("SwiftUI demo") } - .tracked(withTitle: "swift-ui") + .tracked(withTitle: "swift-ui", type: "detail_page") } } diff --git a/Demo/Sources/WebTester/WebTesterViewController~ios.m b/Demo/Sources/WebTester/WebTesterViewController~ios.m index 283850e9..f0d91811 100644 --- a/Demo/Sources/WebTester/WebTesterViewController~ios.m +++ b/Demo/Sources/WebTester/WebTesterViewController~ios.m @@ -66,6 +66,11 @@ - (NSString *)srg_pageViewTitle return @"web-tester"; } +- (NSString *)srg_pageViewType +{ + return @"detail_page"; +} + #pragma mark UITextFieldDelegate protocol - (BOOL)textFieldShouldReturn:(UITextField *)textField diff --git a/Package.resolved b/Package.resolved index 29f738dd..075237e5 100644 --- a/Package.resolved +++ b/Package.resolved @@ -19,6 +19,15 @@ "version": "1.3.2-srg6" } }, + { + "package": "TagCommander SDK V5", + "repositoryURL": "https://github.com/CommandersAct/iOSV5.git", + "state": { + "branch": null, + "revision": "2e56e97db76d55657d0dc7d13e2fcd81ce4eaa6c", + "version": "5.3.3" + } + }, { "package": "libextobjc", "repositoryURL": "https://github.com/SRGSSR/libextobjc.git", @@ -118,24 +127,6 @@ "version": "3.1.0" } }, - { - "package": "TCCore", - "repositoryURL": "https://github.com/SRGSSR/TCCore-xcframework-apple.git", - "state": { - "branch": null, - "revision": "eb686883e63af28174472a09eda97acf07179c88", - "version": "4.5.4-srg5" - } - }, - { - "package": "TCSDK", - "repositoryURL": "https://github.com/SRGSSR/TCSDK-xcframework-apple.git", - "state": { - "branch": null, - "revision": "c4becb0b250258b78cb46225af5e269da834db5a", - "version": "4.4.1-srg5" - } - }, { "package": "UICKeyChainStore", "repositoryURL": "https://github.com/kishikawakatsumi/UICKeyChainStore.git", diff --git a/Package.swift b/Package.swift index af44d056..d9be1175 100644 --- a/Package.swift +++ b/Package.swift @@ -3,7 +3,7 @@ import PackageDescription struct ProjectSettings { - static let marketingVersion: String = "8.2.0" + static let marketingVersion: String = "9.0.0" } let package = Package( @@ -42,13 +42,17 @@ let package = Package( .package(name: "SRGIdentity", url: "https://github.com/SRGSSR/srgidentity-apple.git", .upToNextMinor(from: "3.3.0")), .package(name: "SRGLogger", url: "https://github.com/SRGSSR/srglogger-apple.git", .upToNextMinor(from: "3.1.0")), .package(name: "SRGMediaPlayer", url: "https://github.com/SRGSSR/srgmediaplayer-apple.git", .upToNextMinor(from: "7.2.0")), - .package(name: "TCCore", url: "https://github.com/SRGSSR/TCCore-xcframework-apple.git", .exact("4.5.4-srg5")), - .package(name: "TCSDK", url: "https://github.com/SRGSSR/TCSDK-xcframework-apple.git", .exact("4.4.1-srg5")) + .package(name: "TagCommander", url: "https://github.com/CommandersAct/iOSV5.git", .upToNextMinor(from: "5.3.1")) ], targets: [ .target( name: "SRGAnalytics", - dependencies: ["ComScore", "SRGLogger", "TCCore", "TCSDK"], + dependencies: [ + "ComScore", + "SRGLogger", + .product(name: "TCCore", package: "TagCommander"), + .product(name: "TCServerSide_noIDFA", package: "TagCommander") + ], cSettings: [ .define("MARKETING_VERSION", to: "\"\(ProjectSettings.marketingVersion)\""), .define("NS_BLOCK_ASSERTIONS", to: "1", .when(configuration: .release)) diff --git a/Sources/SRGAnalytics/NSBundle+SRGAnalytics.h b/Sources/SRGAnalytics/NSBundle+SRGAnalytics.h deleted file mode 100644 index 9a82c8ea..00000000 --- a/Sources/SRGAnalytics/NSBundle+SRGAnalytics.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (c) SRG SSR. All rights reserved. -// -// License information is available from the LICENSE file. -// - -@import Foundation; - -NS_ASSUME_NONNULL_BEGIN - -@interface NSBundle (SRGAnalytics) - -/** - * Return `YES` iff the application bundle corresponds to an App Store or TestFlight release. - */ -@property (class, nonatomic, readonly) BOOL srg_isProductionVersion; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/SRGAnalytics/NSBundle+SRGAnalytics.m b/Sources/SRGAnalytics/NSBundle+SRGAnalytics.m deleted file mode 100644 index c495a537..00000000 --- a/Sources/SRGAnalytics/NSBundle+SRGAnalytics.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) SRG SSR. All rights reserved. -// -// License information is available from the LICENSE file. -// - -#import "NSBundle+SRGAnalytics.h" - -#import "SRGAnalyticsTracker.h" - -@import UIKit; - -@implementation NSBundle (SRGAnalytics) - -+ (BOOL)srg_isProductionVersion -{ - if ([NSProcessInfo processInfo].environment[@"SIMULATOR_DEVICE_NAME"] - || [UIDevice.currentDevice.name.lowercaseString containsString:@"simulator"]) { - return NO; - } - - if ([NSBundle.mainBundle pathForResource:@"embedded" ofType:@"mobileprovision"]) { - return NO; - } - - return (NSBundle.mainBundle.appStoreReceiptURL != nil); -} - -@end diff --git a/Sources/SRGAnalytics/SRGAnalyticsConfiguration.m b/Sources/SRGAnalytics/SRGAnalyticsConfiguration.m index bfa09607..0033bf0c 100644 --- a/Sources/SRGAnalytics/SRGAnalyticsConfiguration.m +++ b/Sources/SRGAnalytics/SRGAnalyticsConfiguration.m @@ -6,8 +6,6 @@ #import "SRGAnalyticsConfiguration.h" -#import "NSBundle+SRGAnalytics.h" - SRGAnalyticsBusinessUnitIdentifier const SRGAnalyticsBusinessUnitIdentifierRSI = @"rsi"; SRGAnalyticsBusinessUnitIdentifier const SRGAnalyticsBusinessUnitIdentifierRTR = @"rtr"; SRGAnalyticsBusinessUnitIdentifier const SRGAnalyticsBusinessUnitIdentifierRTS = @"rts"; @@ -15,13 +13,10 @@ SRGAnalyticsBusinessUnitIdentifier const SRGAnalyticsBusinessUnitIdentifierSRG = @"srg"; SRGAnalyticsBusinessUnitIdentifier const SRGAnalyticsBusinessUnitIdentifierSWI = @"swi"; -SRGAnalyticsEnvironment const SRGAnalyticsEnvironmentPreProduction = @"preprod"; -SRGAnalyticsEnvironment const SRGAnalyticsEnvironmentProduction = @"prod"; - @interface SRGAnalyticsConfiguration () @property (nonatomic, copy) SRGAnalyticsBusinessUnitIdentifier businessUnitIdentifier; -@property (nonatomic) NSInteger container; +@property (nonatomic, copy) NSString *sourceKey; @property (nonatomic, copy) NSString *siteName; @end @@ -31,15 +26,14 @@ @implementation SRGAnalyticsConfiguration #pragma mark Object lifecycle - (instancetype)initWithBusinessUnitIdentifier:(SRGAnalyticsBusinessUnitIdentifier)businessUnitIdentifier - container:(NSInteger)container + sourceKey:(NSString *)sourceKey siteName:(NSString *)siteName { if (self = [super init] ) { self.businessUnitIdentifier = businessUnitIdentifier; - self.container = container; + self.sourceKey = sourceKey; self.siteName = siteName; self.centralized = YES; - self.environmentMode = SRGAnalyticsEnvironmentModeAutomatic; } return self; } @@ -63,37 +57,15 @@ - (NSInteger)site return s_sites[businessUnitIdentifier].integerValue; } -- (SRGAnalyticsEnvironment)environment -{ - switch (self.environmentMode) { - case SRGAnalyticsEnvironmentModePreProduction: { - return SRGAnalyticsEnvironmentPreProduction; - break; - } - - case SRGAnalyticsEnvironmentModeProduction: { - return SRGAnalyticsEnvironmentProduction; - break; - } - - case SRGAnalyticsEnvironmentModeAutomatic: - default: { - return NSBundle.srg_isProductionVersion ? SRGAnalyticsEnvironmentProduction : SRGAnalyticsEnvironmentPreProduction; - break; - } - } -} - #pragma mark NSCopying protocol - (id)copyWithZone:(NSZone *)zone { SRGAnalyticsConfiguration *configuration = [self.class allocWithZone:zone]; configuration.businessUnitIdentifier = self.businessUnitIdentifier; - configuration.container = self.container; + configuration.sourceKey = self.sourceKey; configuration.siteName = self.siteName; configuration.centralized = self.centralized; - configuration.environmentMode = self.environmentMode; configuration.unitTesting = self.unitTesting; return configuration; } @@ -102,12 +74,12 @@ - (id)copyWithZone:(NSZone *)zone - (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p; businessUnitIdentifier = %@; site = %@; container = %@; siteName = %@", + return [NSString stringWithFormat:@"<%@: %p; businessUnitIdentifier = %@; site = %@; sourceKey = %@; siteName = %@", self.class, self, self.businessUnitIdentifier, @(self.site), - @(self.container), + self.sourceKey, self.siteName]; } diff --git a/Sources/SRGAnalytics/SRGAnalyticsHiddenEventLabels.m b/Sources/SRGAnalytics/SRGAnalyticsEventLabels.m similarity index 92% rename from Sources/SRGAnalytics/SRGAnalyticsHiddenEventLabels.m rename to Sources/SRGAnalytics/SRGAnalyticsEventLabels.m index 19d42f6a..c2a6a870 100644 --- a/Sources/SRGAnalytics/SRGAnalyticsHiddenEventLabels.m +++ b/Sources/SRGAnalytics/SRGAnalyticsEventLabels.m @@ -4,12 +4,12 @@ // License information is available from the LICENSE file. // -#import "SRGAnalyticsHiddenEventLabels.h" +#import "SRGAnalyticsEventLabels.h" #import "NSMutableDictionary+SRGAnalytics.h" #import "SRGAnalyticsLabels+Private.h" -@implementation SRGAnalyticsHiddenEventLabels +@implementation SRGAnalyticsEventLabels #pragma mark Getters and setters @@ -47,7 +47,7 @@ @implementation SRGAnalyticsHiddenEventLabels - (id)copyWithZone:(NSZone *)zone { - SRGAnalyticsHiddenEventLabels *labels = [super copyWithZone:zone]; + SRGAnalyticsEventLabels *labels = [super copyWithZone:zone]; labels.type = self.type; labels.value = self.value; labels.source = self.source; diff --git a/Sources/SRGAnalytics/SRGAnalyticsLabels+Private.h b/Sources/SRGAnalytics/SRGAnalyticsLabels+Private.h index b00f5320..0b800b1a 100644 --- a/Sources/SRGAnalytics/SRGAnalyticsLabels+Private.h +++ b/Sources/SRGAnalytics/SRGAnalyticsLabels+Private.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN @interface SRGAnalyticsLabels (Private) /** - * Dictionary containing the raw values which will be sent to TagCommander. + * Dictionary containing the raw values which will be sent to Commanders Act. */ @property (nonatomic, readonly) NSDictionary *labelsDictionary; diff --git a/Sources/SRGAnalytics/SRGAnalyticsNotifications.m b/Sources/SRGAnalytics/SRGAnalyticsNotifications.m index 5afb45d9..fc9478be 100644 --- a/Sources/SRGAnalytics/SRGAnalyticsNotifications.m +++ b/Sources/SRGAnalytics/SRGAnalyticsNotifications.m @@ -8,6 +8,8 @@ #import +@import TCCore; + static BOOL s_interceptorEnabled = NO; NSString * const SRGAnalyticsRequestNotification = @"SRGAnalyticsRequestNotification"; @@ -49,30 +51,6 @@ - (NSURLSessionDataTask *)srganalytics_swizzled_dataTaskWithRequest:(NSURLReques @end -@implementation NSURLConnection (SRGAnalyticsProxy) - -+ (void)srg_enableAnalyticsInterceptor -{ - method_exchangeImplementations(class_getClassMethod(self, @selector(sendSynchronousRequest:returningResponse:error:)), - class_getClassMethod(self, @selector(swizzled_sendSynchronousRequest:returningResponse:error:))); -} - -+ (NSData *)swizzled_sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse *__autoreleasing _Nullable *)response error:(NSError * _Nullable __autoreleasing *)error -{ - NSURL *URL = request.URL; - if ([URL.host containsString:@"tagcommander"]) { - // The POST body contains URL encoded parameters. Use NSURLComponents for simple extraction - NSURLComponents *URLComponents = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO]; - URLComponents.query = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]; - [NSNotificationCenter.defaultCenter postNotificationName:SRGAnalyticsRequestNotification - object:nil - userInfo:@{ SRGAnalyticsLabelsKey : SRGAnalyticsProxyLabelsFromURLComponents(URLComponents) }]; - } - return [self swizzled_sendSynchronousRequest:request returningResponse:response error:error]; -} - -@end - void SRGAnalyticsEnableRequestInterceptor(void) { if (s_interceptorEnabled) { @@ -80,7 +58,17 @@ void SRGAnalyticsEnableRequestInterceptor(void) } [NSURLSession srg_enableAnalyticsInterceptor]; - [NSURLConnection srg_enableAnalyticsInterceptor]; + + [NSNotificationCenter.defaultCenter addObserverForName:kTCNotification_HTTPRequest object:nil queue:nil usingBlock:^(NSNotification * _Nonnull notification) { + NSString *bodyString = notification.userInfo[kTCUserInfo_POSTData]; + NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *labelsDictionary = [NSJSONSerialization JSONObjectWithData:bodyData options:0 error:NULL]; + if (labelsDictionary) { + [NSNotificationCenter.defaultCenter postNotificationName:SRGAnalyticsRequestNotification + object:nil + userInfo:@{ SRGAnalyticsLabelsKey : labelsDictionary }]; + } + }]; s_interceptorEnabled = YES; } diff --git a/Sources/SRGAnalytics/SRGAnalyticsTracker+Private.h b/Sources/SRGAnalytics/SRGAnalyticsTracker+Private.h index aaa53b2a..37829911 100644 --- a/Sources/SRGAnalytics/SRGAnalyticsTracker+Private.h +++ b/Sources/SRGAnalytics/SRGAnalyticsTracker+Private.h @@ -14,12 +14,14 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, nullable) SRGAnalyticsLabels *dataSourceLabels; - (void)trackPageViewWithTitle:(NSString *)title + type:(NSString *)type levels:(nullable NSArray *)levels labels:(nullable SRGAnalyticsPageViewLabels *)labels fromPushNotification:(BOOL)fromPushNotification ignoreApplicationState:(BOOL)ignoreApplicationState; -- (void)trackTagCommanderEventWithLabels:(nullable NSDictionary *)labels; +- (void)sendCommandersActCustomEventWithName:(NSString *)name + labels:(nullable NSDictionary *)labels; @end diff --git a/Sources/SRGAnalytics/SRGAnalyticsTracker.m b/Sources/SRGAnalytics/SRGAnalyticsTracker.m index eb58197d..164222a8 100644 --- a/Sources/SRGAnalytics/SRGAnalyticsTracker.m +++ b/Sources/SRGAnalytics/SRGAnalyticsTracker.m @@ -16,7 +16,7 @@ @import ComScore; @import TCCore; -@import TCSDK; +@import TCServerSide_noIDFA; static NSString * s_unitTestingIdentifier = nil; @@ -43,11 +43,14 @@ @interface SRGAnalyticsTracker () @property (nonatomic, copy) SRGAnalyticsConfiguration *configuration; @property (nonatomic, weak) id dataSource; -@property (nonatomic) TagCommander *tagCommander; +@property (nonatomic) ServerSide *serverSide; @property (nonatomic) SCORStreamingAnalytics *streamSense; @property (nonatomic) SRGAnalyticsLabels *globalLabels; +@property (nonatomic, readonly) NSDictionary *defaultComScoreLabels; +@property (nonatomic, readonly) NSDictionary *defaultLabels; + @end @implementation SRGAnalyticsTracker @@ -85,7 +88,15 @@ - (void)startWithConfiguration:(SRGAnalyticsConfiguration *)configuration if (configuration.unitTesting) { SRGAnalyticsEnableRequestInterceptor(); } - + + [self startComScoreWithConfiguration:configuration]; + [self startCommandersActWithConfiguration:configuration]; + + [self sendApplicationList]; +} + +- (void)startComScoreWithConfiguration:(SRGAnalyticsConfiguration *)configuration +{ SCORPublisherConfiguration *publisherConfiguration = [SCORPublisherConfiguration publisherConfigurationWithBuilderBlock:^(SCORPublisherConfigurationBuilder *builder) { builder.publisherId = @"6036016"; builder.secureTransmissionEnabled = YES; @@ -96,17 +107,25 @@ - (void)startWithConfiguration:(SRGAnalyticsConfiguration *)configuration // Coding Document for Video Players, page 16 builder.httpRedirectCachingEnabled = NO; }]; - + SCORConfiguration *comScoreConfiguration = [SCORAnalytics configuration]; [comScoreConfiguration addClientWithConfiguration:publisherConfiguration]; - + comScoreConfiguration.applicationVersion = [NSBundle.mainBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; comScoreConfiguration.usagePropertiesAutoUpdateMode = SCORUsagePropertiesAutoUpdateModeForegroundAndBackground; comScoreConfiguration.preventAdSupportUsage = YES; - + [SCORAnalytics start]; - - [self sendApplicationList]; +} + +- (void)startCommandersActWithConfiguration:(SRGAnalyticsConfiguration *)configuration +{ + self.serverSide = [[ServerSide alloc] initWithSiteID:(int)configuration.site andSourceKey:configuration.sourceKey]; + [self.serverSide enableRunningInBackground]; + + [self.serverSide addPermanentData:@"app_library_version" withValue:SRGAnalyticsMarketingVersion()]; + [self.serverSide addPermanentData:@"navigation_app_site_name" withValue:configuration.siteName]; + [self.serverSide addPermanentData:@"navigation_device" withValue:[self device]]; } #pragma mark Labels @@ -194,56 +213,85 @@ - (NSString *)device #pragma mark General event tracking (internal use only) -- (void)trackTagCommanderEventWithLabels:(NSDictionary *)labels +- (void)sendCommandersActPageViewEventWithTitle:(NSString *)title + type:(NSString *)type + labels:(NSDictionary *)labels { - if (! self.tagCommander) { - SRGAnalyticsConfiguration *configuration = self.configuration; - NSAssert(configuration != nil, @"The tracker must be started"); - - self.tagCommander = [[TagCommander alloc] initWithSiteID:(int)configuration.site andContainerID:(int)configuration.container]; - [self.tagCommander enableRunningInBackground]; - [self.tagCommander addPermanentData:@"app_library_version" withValue:SRGAnalyticsMarketingVersion()]; - [self.tagCommander addPermanentData:@"navigation_app_site_name" withValue:configuration.siteName]; - [self.tagCommander addPermanentData:@"navigation_environment" withValue:configuration.environment]; - [self.tagCommander addPermanentData:@"navigation_device" withValue:[self device]]; + NSAssert(title.length != 0 && type.length != 0, @"A title and a type are required"); + + TCPageViewEvent *event = [[TCPageViewEvent alloc] initWithType:type]; + event.pageName = title; + [self.defaultLabels enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull value, BOOL * _Nonnull stop) { + [event addAdditionalProperty:key withStringValue:value]; + }]; + + [labels enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull value, BOOL * _Nonnull stop) { + [event addAdditionalProperty:key withStringValue:value]; + }]; + + if (self.configuration.unitTesting) { + [event addAdditionalProperty:@"srg_test_id" withStringValue:SRGAnalyticsUnitTestingIdentifier()]; } - - NSMutableDictionary *fullLabels = [self defaultLabels].mutableCopy; - [fullLabels addEntriesFromDictionary:labels]; - [fullLabels enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull object, BOOL * _Nonnull stop) { - [self.tagCommander addData:key withValue:object]; + + [self.serverSide execute:event]; +} + +- (void)sendCommandersActCustomEventWithName:(NSString *)name + labels:(NSDictionary *)labels +{ + NSAssert(name.length != 0, @"A name is required"); + + TCCustomEvent *event = [[TCCustomEvent alloc] initWithName:name]; + [self.defaultLabels enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull value, BOOL * _Nonnull stop) { + [event addAdditionalProperty:key withStringValue:value]; + }]; + + [labels enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull value, BOOL * _Nonnull stop) { + [event addAdditionalProperty:key withStringValue:value]; }]; - [self.tagCommander sendData]; + + if (self.configuration.unitTesting) { + [event addAdditionalProperty:@"srg_test_id" withStringValue:SRGAnalyticsUnitTestingIdentifier()]; + } + + [self.serverSide execute:event]; } #pragma mark Page view tracking -- (void)trackPageViewWithTitle:(NSString *)title levels:(NSArray *)levels +- (void)trackPageViewWithTitle:(NSString *)title + type:(NSString *)type + levels:(NSArray *)levels { - [self trackPageViewWithTitle:title levels:levels labels:nil fromPushNotification:NO]; + [self trackPageViewWithTitle:title type:type levels:levels labels:nil fromPushNotification:NO]; } - (void)trackPageViewWithTitle:(NSString *)title + type:(NSString *)type levels:(NSArray *)levels labels:(SRGAnalyticsPageViewLabels *)labels fromPushNotification:(BOOL)fromPushNotification { - [self trackPageViewWithTitle:title levels:levels labels:labels fromPushNotification:fromPushNotification ignoreApplicationState:NO]; + [self trackPageViewWithTitle:title type:type levels:levels labels:labels fromPushNotification:fromPushNotification ignoreApplicationState:NO]; } -- (void)uncheckedTrackPageViewWithTitle:(NSString *)title levels:(NSArray *)levels +- (void)uncheckedTrackPageViewWithTitle:(NSString *)title + type:(NSString *)type + levels:(NSArray *)levels { - [self uncheckedTrackPageViewWithTitle:title levels:levels labels:nil]; + [self uncheckedTrackPageViewWithTitle:title type:type levels:levels labels:nil]; } - (void)uncheckedTrackPageViewWithTitle:(NSString *)title + type:(NSString *)type levels:(NSArray *)levels labels:(SRGAnalyticsPageViewLabels *)labels { - [self trackPageViewWithTitle:title levels:levels labels:labels fromPushNotification:NO ignoreApplicationState:YES]; + [self trackPageViewWithTitle:title type:type levels:levels labels:labels fromPushNotification:NO ignoreApplicationState:YES]; } - (void)trackPageViewWithTitle:(NSString *)title + type:(NSString *)type levels:(NSArray *)levels labels:(SRGAnalyticsPageViewLabels *)labels fromPushNotification:(BOOL)fromPushNotification @@ -254,11 +302,11 @@ - (void)trackPageViewWithTitle:(NSString *)title return; } - if (title.length == 0 || (! ignoreApplicationState && UIApplication.sharedApplication.applicationState == UIApplicationStateBackground)) { + if (title.length == 0 || type.length == 0 || (! ignoreApplicationState && UIApplication.sharedApplication.applicationState == UIApplicationStateBackground)) { return; } - [self trackTagCommanderPageViewWithTitle:title levels:levels labels:labels fromPushNotification:fromPushNotification]; + [self trackCommandersActPageViewWithTitle:title type:type levels:levels labels:labels fromPushNotification:fromPushNotification]; [self trackComScorePageViewWithTitle:title levels:levels labels:labels fromPushNotification:fromPushNotification]; } @@ -269,7 +317,7 @@ - (void)trackComScorePageViewWithTitle:(NSString *)title { NSAssert(title.length != 0, @"A title is required"); - NSMutableDictionary *fullLabels = [self defaultComScoreLabels].mutableCopy; + NSMutableDictionary *fullLabels = self.defaultComScoreLabels.mutableCopy; [fullLabels srg_safelySetString:title forKey:@"srg_title"]; [fullLabels srg_safelySetString:@(fromPushNotification).stringValue forKey:@"srg_ap_push"]; @@ -306,57 +354,54 @@ - (void)trackComScorePageViewWithTitle:(NSString *)title } if (self.configuration.unitTesting) { - fullLabels[@"srg_test_id"] = SRGAnalyticsUnitTestingIdentifier(); + [fullLabels srg_safelySetString:SRGAnalyticsUnitTestingIdentifier() forKey:@"srg_test_id"]; } [SCORAnalytics notifyViewEventWithLabels:fullLabels.copy]; } -- (void)trackTagCommanderPageViewWithTitle:(NSString *)title - levels:(NSArray *)levels - labels:(SRGAnalyticsPageViewLabels *)labels - fromPushNotification:(BOOL)fromPushNotification +- (void)trackCommandersActPageViewWithTitle:(NSString *)title + type:(NSString *)type + levels:(NSArray *)levels + labels:(SRGAnalyticsPageViewLabels *)labels + fromPushNotification:(BOOL)fromPushNotification { - NSAssert(title.length != 0, @"A title is required"); - NSMutableDictionary *fullLabels = [NSMutableDictionary dictionary]; - [fullLabels srg_safelySetString:@"screen" forKey:@"event_id"]; [fullLabels srg_safelySetString:@"app" forKey:@"navigation_property_type"]; - [fullLabels srg_safelySetString:title forKey:@"content_title"]; [fullLabels srg_safelySetString:self.configuration.businessUnitIdentifier.uppercaseString forKey:@"navigation_bu_distributer"]; [fullLabels srg_safelySetString:fromPushNotification ? @"true" : @"false" forKey:@"accessed_after_push_notification"]; - + [levels enumerateObjectsUsingBlock:^(NSString * _Nonnull object, NSUInteger idx, BOOL * _Nonnull stop) { if (idx > 7) { *stop = YES; return; } - + NSString *levelKey = [NSString stringWithFormat:@"navigation_level_%@", @(idx + 1)]; [fullLabels srg_safelySetString:object forKey:levelKey]; }]; - + NSDictionary *labelsDictionary = [labels labelsDictionary]; if (labelsDictionary) { [fullLabels addEntriesFromDictionary:labelsDictionary]; } - + if (self.configuration.unitTesting) { - fullLabels[@"srg_test_id"] = SRGAnalyticsUnitTestingIdentifier(); + [fullLabels srg_safelySetString:SRGAnalyticsUnitTestingIdentifier() forKey:@"srg_test_id"]; } - - [self trackTagCommanderEventWithLabels:fullLabels.copy]; + + [self sendCommandersActPageViewEventWithTitle:title type:type labels:fullLabels.copy]; } -#pragma mark Hidden event tracking +#pragma mark Event tracking -- (void)trackHiddenEventWithName:(NSString *)name +- (void)trackEventWithName:(NSString *)name { - [self trackHiddenEventWithName:name labels:nil]; + [self trackEventWithName:name labels:nil]; } -- (void)trackHiddenEventWithName:(NSString *)name - labels:(SRGAnalyticsHiddenEventLabels *)labels +- (void)trackEventWithName:(NSString *)name + labels:(SRGAnalyticsEventLabels *)labels { if (! self.configuration) { SRGAnalyticsLogWarning(@"tracker", @"The tracker has not been started yet"); @@ -368,28 +413,25 @@ - (void)trackHiddenEventWithName:(NSString *)name return; } - [self trackTagCommanderHiddenEventWithName:name labels:labels]; + [self trackCommandersActEventWithName:name labels:labels]; } -- (void)trackTagCommanderHiddenEventWithName:(NSString *)name labels:(SRGAnalyticsHiddenEventLabels *)labels +- (void)trackCommandersActEventWithName:(NSString *)name labels:(SRGAnalyticsEventLabels *)labels { - NSAssert(name.length != 0, @"A name is required"); NSAssert(self.configuration != nil, @"The tracker must be started"); - + NSMutableDictionary *fullLabels = [NSMutableDictionary dictionary]; - [fullLabels srg_safelySetString:@"hidden_event" forKey:@"event_id"]; - [fullLabels srg_safelySetString:name forKey:@"event_name"]; NSDictionary *labelsDictionary = [labels labelsDictionary]; if (labelsDictionary) { [fullLabels addEntriesFromDictionary:labelsDictionary]; } - + if (self.configuration.unitTesting) { - fullLabels[@"srg_test_id"] = SRGAnalyticsUnitTestingIdentifier(); + [fullLabels srg_safelySetString:SRGAnalyticsUnitTestingIdentifier() forKey:@"srg_test_id"]; } - - [self trackTagCommanderEventWithLabels:fullLabels.copy]; + + [self sendCommandersActCustomEventWithName:name labels:fullLabels.copy]; } #pragma mark Application list measurement @@ -457,12 +499,12 @@ - (void)sendApplicationList NSArray *sortedInstalledApplications = [installedApplications.allObjects sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; - SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels = [[SRGAnalyticsEventLabels alloc] init]; labels.type = @"hidden"; labels.source = @"SRGAnalytics"; labels.value = [sortedInstalledApplications componentsJoinedByString:@";"]; - [self trackHiddenEventWithName:@"Installed Apps" labels:labels]; + [self trackEventWithName:@"Installed Apps" labels:labels]; }); }] resume]; } diff --git a/Sources/SRGAnalytics/UIViewController+SRGAnalytics.m b/Sources/SRGAnalytics/UIViewController+SRGAnalytics.m index d7dcb43d..b6cf97dc 100644 --- a/Sources/SRGAnalytics/UIViewController+SRGAnalytics.m +++ b/Sources/SRGAnalytics/UIViewController+SRGAnalytics.m @@ -91,7 +91,8 @@ - (void)srg_trackPageViewAutomatic:(BOOL)automatic recursive:(BOOL)recursive ign } NSString *title = [trackedSelf srg_pageViewTitle]; - + NSString *type = [trackedSelf srg_pageViewType]; + NSArray *levels = nil; if ([trackedSelf respondsToSelector:@selector(srg_pageViewLevels)]) { levels = [trackedSelf srg_pageViewLevels]; @@ -108,6 +109,7 @@ - (void)srg_trackPageViewAutomatic:(BOOL)automatic recursive:(BOOL)recursive ign } [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:title + type:type levels:levels labels:labels fromPushNotification:fromPushNotification diff --git a/Sources/SRGAnalytics/include/SRGAnalytics.h b/Sources/SRGAnalytics/include/SRGAnalytics.h index 4eae491c..92e37409 100644 --- a/Sources/SRGAnalytics/include/SRGAnalytics.h +++ b/Sources/SRGAnalytics/include/SRGAnalytics.h @@ -11,7 +11,7 @@ FOUNDATION_EXPORT NSString * SRGAnalyticsMarketingVersion(void); // Public headers. #import "SRGAnalyticsConfiguration.h" -#import "SRGAnalyticsHiddenEventLabels.h" +#import "SRGAnalyticsEventLabels.h" #import "SRGAnalyticsLabels.h" #import "SRGAnalyticsNotifications.h" #import "SRGAnalyticsPageViewLabels.h" diff --git a/Sources/SRGAnalytics/include/SRGAnalyticsConfiguration.h b/Sources/SRGAnalytics/include/SRGAnalyticsConfiguration.h index e0c3e91b..59e35aee 100644 --- a/Sources/SRGAnalytics/include/SRGAnalyticsConfiguration.h +++ b/Sources/SRGAnalytics/include/SRGAnalyticsConfiguration.h @@ -20,33 +20,9 @@ OBJC_EXPORT SRGAnalyticsBusinessUnitIdentifier const SRGAnalyticsBusinessUnitIde OBJC_EXPORT SRGAnalyticsBusinessUnitIdentifier const SRGAnalyticsBusinessUnitIdentifierSRG; OBJC_EXPORT SRGAnalyticsBusinessUnitIdentifier const SRGAnalyticsBusinessUnitIdentifierSWI; - -/** - * @name Analytics environment - */ -typedef NSString * SRGAnalyticsEnvironment NS_TYPED_ENUM; - -OBJC_EXPORT SRGAnalyticsEnvironment const SRGAnalyticsEnvironmentPreProduction; -OBJC_EXPORT SRGAnalyticsEnvironment const SRGAnalyticsEnvironmentProduction; - /** - * Anayltics environment mode. + * Analytics configuration. */ -typedef NS_ENUM(NSInteger, SRGAnalyticsEnvironmentMode) { - /** - * Automatic environment mode. The environment is determined from application bundle analysis. - */ - SRGAnalyticsEnvironmentModeAutomatic = 0, - /** - * Force pre-production analytics environment. - */ - SRGAnalyticsEnvironmentModePreProduction, - /** - * Force production analytics environment. - */ - SRGAnalyticsEnvironmentModeProduction -}; - @interface SRGAnalyticsConfiguration : NSObject /** @@ -55,11 +31,14 @@ typedef NS_ENUM(NSInteger, SRGAnalyticsEnvironmentMode) { * * @param businessUnitIdentifier The identifier of the business unit which measurements are made for. Usually the * business unit which publishes the application. - * @param container The TagCommander container identifier to which measurements will be sent. + * @param sourceKey The Commanders Act source key. * @param siteName The name of the site which measurements must be associated with. + * + * @discssion The various setup parameters to use must be obtained from the team responsible of measurements for + * your application. */ - (instancetype)initWithBusinessUnitIdentifier:(SRGAnalyticsBusinessUnitIdentifier)businessUnitIdentifier - container:(NSInteger)container + sourceKey:(NSString *)sourceKey siteName:(NSString *)siteName; /** @@ -77,46 +56,26 @@ typedef NS_ENUM(NSInteger, SRGAnalyticsEnvironmentMode) { */ @property (nonatomic, getter=isUnitTesting) BOOL unitTesting; -/** - * Analytics environment mode. Determines how the analytics environment (production / pre-production) is resolved. - * - * The default value `SRGAnalyticsEnvironmentModeAutomatic` is the recommended choice in almost all cases. It automatically - * determines from the application bundle whether it corresponds to an App Store Connect release or not, and sets the environment - * accordingly. - * - * You should use a forced mode only in very specific cases, e.g. if you distribute internal development builds via TestFlight. - * Otherwise stick with the default behavior. - * - * @discussion: A Distribution build to App Store Connect (App Store, TestFlight, App Store B2B) should use the production - * environment. In House, Ad Hoc and Development builds should use the pre-production environment. - */ -@property (nonatomic) SRGAnalyticsEnvironmentMode environmentMode; - /** * The SRG SSR business unit which measurements are associated with. */ @property (nonatomic, readonly, copy) SRGAnalyticsBusinessUnitIdentifier businessUnitIdentifier; /** - * The TagCommander site. + * The Commanders Act site. */ @property (nonatomic, readonly) NSInteger site; /** - * The TagCommander container identifier. + * The Commanders Act source key. */ -@property (nonatomic, readonly) NSInteger container; +@property (nonatomic, readonly, copy) NSString *sourceKey; /** - * The name of the site which TagCommander measurements must be associated with. By default `business_unit-app-test-v`. + * The name of the site which Commanders Act measurements must be associated with. By default `business_unit-app-test-v`. */ @property (nonatomic, readonly, copy) NSString *siteName; -/** - * The analytics environment. - */ -@property (nonatomic, readonly, copy) SRGAnalyticsEnvironment environment; - @end @interface SRGAnalyticsConfiguration (Unavailable) diff --git a/Sources/SRGAnalytics/include/SRGAnalyticsHiddenEventLabels.h b/Sources/SRGAnalytics/include/SRGAnalyticsEventLabels.h similarity index 71% rename from Sources/SRGAnalytics/include/SRGAnalyticsHiddenEventLabels.h rename to Sources/SRGAnalytics/include/SRGAnalyticsEventLabels.h index 9d3955cb..c1604918 100644 --- a/Sources/SRGAnalytics/include/SRGAnalyticsHiddenEventLabels.h +++ b/Sources/SRGAnalytics/include/SRGAnalyticsEventLabels.h @@ -9,11 +9,11 @@ NS_ASSUME_NONNULL_BEGIN /** - * Additional hidden event labels. Data associated with a hidden event is generic (type, values and source) and - * therefore flexible. Your measurement team should provide you precise guidelines about which information must - * be sent in hidden events, and in which fields. + * Additional event labels. Data associated with an event is generic (type, values and source) and therefore flexible. + * Your measurement team should provide you precise guidelines about which information must be sent in events, + * and in which fields. */ -@interface SRGAnalyticsHiddenEventLabels : SRGAnalyticsLabels +@interface SRGAnalyticsEventLabels : SRGAnalyticsLabels /** * The event type. diff --git a/Sources/SRGAnalytics/include/SRGAnalyticsLabels.h b/Sources/SRGAnalytics/include/SRGAnalyticsLabels.h index 1e265093..2e02e641 100644 --- a/Sources/SRGAnalytics/include/SRGAnalyticsLabels.h +++ b/Sources/SRGAnalytics/include/SRGAnalyticsLabels.h @@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN * Additional custom information, mapping variables to values. * * You should rarely need to provide custom information with measurements, as this requires the variable name to be - * declared on TagCommander portal first (otherwise the associated value will be discarded). + * declared on Commanders Act portal first (otherwise the associated value will be discarded). * * Custom information can be used to override official labels. You should use this ability sparingly, though. */ diff --git a/Sources/SRGAnalytics/include/SRGAnalyticsNotifications.h b/Sources/SRGAnalytics/include/SRGAnalyticsNotifications.h index 0175a408..c15f98a7 100644 --- a/Sources/SRGAnalytics/include/SRGAnalyticsNotifications.h +++ b/Sources/SRGAnalytics/include/SRGAnalyticsNotifications.h @@ -9,7 +9,7 @@ NS_ASSUME_NONNULL_BEGIN /** - * The following notifications can be used if you need to track when TagCommander and comScore requests are made, + * The following notifications can be used if you need to track when Commanders Act and comScore requests are made, * and which information will be sent to these services, for unit testing purposes. * * These notifications are only emitted when enabling the `unitTesting` tracker configuration flag, @see @@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN * Notifications may be received on background threads. */ -// Notification sent when TagCommander analytics are sent. +// Notification sent when Commanders Act analytics are sent. OBJC_EXPORT NSString * const SRGAnalyticsRequestNotification; // Information available for `SRGAnalyticsRequestNotification`. diff --git a/Sources/SRGAnalytics/include/SRGAnalyticsTracker.h b/Sources/SRGAnalytics/include/SRGAnalyticsTracker.h index ac746096..ea6b0748 100644 --- a/Sources/SRGAnalytics/include/SRGAnalyticsTracker.h +++ b/Sources/SRGAnalytics/include/SRGAnalyticsTracker.h @@ -5,7 +5,7 @@ // #import "SRGAnalyticsConfiguration.h" -#import "SRGAnalyticsHiddenEventLabels.h" +#import "SRGAnalyticsEventLabels.h" #import "SRGAnalyticsPageViewLabels.h" #import "SRGAnalyticsTrackerDataSource.h" @@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN /** * The analytics tracker is a singleton instance responsible of tracking usage of an application, sending measurements - * to TagCommander (internal analytics) and comScore (Mediapulse official audience measurements). The usage data is + * to Commanders Act (internal analytics) and comScore (Mediapulse official audience measurements). The usage data is * simply a collection of key-values (both strings), named labels, which can then be used by data analysts in studies * and reports. * @@ -26,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN * * The SRG Analytics library supports three kinds of measurements: * - View events: Appearance of views (page views), which makes it possible to track which content is seen by users. - * - Hidden events: Custom events which can be used for measuresement of application functionalities. + * - Events: Custom events which can be used for measuresement of application functionalities. * - Stream playback events: Measurements for audio and video consumption. * * For all kinds of measurements, required information must be provided through mandatory parameters, and optional @@ -51,8 +51,8 @@ NS_ASSUME_NONNULL_BEGIN * manual tracking via the `-[SRGAnalyticsTracker trackPageViewWithTitle:levels:labels:fromPushNotification:]` * method. * 3. When you need to track specific functionalities in your application (e.g. the use of some interface button - * or of some feature of your application), send a hidden event using one of the `-trackHiddenEvent...` methods - * available from `SRGAnalyticsTracker`. + * or of some feature of your application), send a event using one of the `-trackEvent...` methods available + * from `SRGAnalyticsTracker`. * 4. If you need to track media playback using SRG MediaPlayer, you must add the SRGAnalyticsMediaPlayer subframework * to your project (@see `SRGMediaPlayerController+SRGAnalyticsMediaPlayer.h` for more information). You are * still responsible of providing most metadata associated with playback (e.g. title or duration of what is @@ -72,7 +72,7 @@ NS_EXTENSION_UNAVAILABLE("SRG Analytics does not support application extensions" /** * Start the tracker. This is required to specify for which business unit you are tracking events, as well as to - * where they must be sent on the comScore and TagCommander services. Attempting to track view, hidden or stream + * where they must be sent on the comScore and Commanders Act services. Attempting to track view, stream or other * events without starting the tracker has no effect. * * @param configuration The configuration to use. This configuration is copied and cannot be changed afterwards. @@ -98,29 +98,29 @@ NS_EXTENSION_UNAVAILABLE("SRG Analytics does not support application extensions" @end /** - * @name Hidden event tracking + * @name Event tracking */ -@interface SRGAnalyticsTracker (HiddenEventTracking) +@interface SRGAnalyticsTracker (EventTracking) /** - * Send a hidden event with the specified name. + * Send a event with the specified name. * * @param name The event name. * * @discussion If the name is empty, no event will be sent. */ -- (void)trackHiddenEventWithName:(NSString *)name; +- (void)trackEventWithName:(NSString *)name; /** - * Send a hidden event with the specified name. + * Send a event with the specified name. * * @param name The event name. * @param labels Information to be sent along the event and which is meaningful for your application measurements. * * @discussion If the name is `nil`, no event will be sent. */ -- (void)trackHiddenEventWithName:(NSString *)name - labels:(nullable SRGAnalyticsHiddenEventLabels *)labels; +- (void)trackEventWithName:(NSString *)name + labels:(nullable SRGAnalyticsEventLabels *)labels; @end @@ -133,7 +133,8 @@ NS_EXTENSION_UNAVAILABLE("SRG Analytics does not support application extensions" /** * Track a page view (not associated with a push notification). Does nothing when the application is in the background. * - * @param title The page title. If the title is empty, no event will be sent. + * @param title The page title. If empty no event will be sent. + * @param type The page type (e.g. Article). If empty no event will be sent. * @param levels An array of levels in increasing order, describing the position of the view in the hierarchy. * * @discussion This method is primarily available for page view tracking not related to a view controller. If your page view @@ -141,12 +142,14 @@ NS_EXTENSION_UNAVAILABLE("SRG Analytics does not support application extensions" * to the `SRGAnalyticsViewTracking` protocol. */ - (void)trackPageViewWithTitle:(NSString *)title + type:(NSString *)type levels:(nullable NSArray *)levels; /** * Track a page view. Does nothing when the application is in the background. * - * @param title The page title. If the title is empty, no event will be sent. + * @param title The page title. If empty no event will be sent. + * @param type The page type (e.g. Article). If empty no event will be sent. * @param levels An array of levels in increasing order, describing the position of the view in the hierarchy. * @param labels Additional custom labels. * @param fromPushNotification `YES` iff the view is opened from a push notification. @@ -156,6 +159,7 @@ NS_EXTENSION_UNAVAILABLE("SRG Analytics does not support application extensions" * to the `SRGAnalyticsViewTracking` protocol. */ - (void)trackPageViewWithTitle:(NSString *)title + type:(NSString *)type levels:(nullable NSArray *)levels labels:(nullable SRGAnalyticsPageViewLabels *)labels fromPushNotification:(BOOL)fromPushNotification; @@ -176,20 +180,24 @@ NS_EXTENSION_UNAVAILABLE("SRG Analytics does not support application extensions" /** * Unchecked track a page view. The page view is emitted no matter the application state. * - * @param title The page title. If the title is empty, no event will be sent. + * @param title The page title. If empty no event will be sent. + * @param type The page type (e.g. Article). If empty no event will be sent. * @param levels An array of levels in increasing order, describing the position of the view in the hierarchy. */ - (void)uncheckedTrackPageViewWithTitle:(NSString *)title + type:(NSString *)type levels:(nullable NSArray *)levels; /** * Unchecked track a page view. The page view is emitted no matter the application state. * - * @param title The page title. If the title is empty, no event will be sent. + * @param title The page title. If empty no event will be sent. + * @param type The page type (e.g. Article). If empty no event will be sent. * @param levels An array of levels in increasing order, describing the position of the view in the hierarchy. * @param labels Additional custom labels. */ - (void)uncheckedTrackPageViewWithTitle:(NSString *)title + type:(NSString *)type levels:(nullable NSArray *)levels labels:(nullable SRGAnalyticsPageViewLabels *)labels; diff --git a/Sources/SRGAnalytics/include/UIViewController+SRGAnalytics.h b/Sources/SRGAnalytics/include/UIViewController+SRGAnalytics.h index 2d5c4303..d058eec3 100644 --- a/Sources/SRGAnalytics/include/UIViewController+SRGAnalytics.h +++ b/Sources/SRGAnalytics/include/UIViewController+SRGAnalytics.h @@ -12,8 +12,7 @@ NS_ASSUME_NONNULL_BEGIN /** * View controllers whose usage must be tracked should conform to the `SRGAnalyticsViewTracking` protocol, which - * describes the data to send with such events. The only method required by this protocol is `-srg_pageViewTitle`, - * which provides the name to be used for the view events. + * describes the data to send with such events. * * By default, if a view controller conforms to the `SRGAnalyticsViewTracking` protocol, a page view event will * automatically be sent when it is presented for the first time (i.e. when `-viewDidAppear:` is called for @@ -38,12 +37,15 @@ NS_ASSUME_NONNULL_BEGIN @protocol SRGAnalyticsViewTracking /** - * The page view title to use for view event measurement. - * - * @return The page view title. If this value is empty, no event will be sent. + * The page view title to use for view event measurement. If this value is empty, no event will be sent. */ @property (nonatomic, readonly, copy) NSString *srg_pageViewTitle; +/** + * The page view type (e.g. Article). If this value is empty, no event will be sent. + */ +@property (nonatomic, readonly, copy) NSString *srg_pageViewType; + @optional /** diff --git a/Sources/SRGAnalyticsMediaPlayer/SRGComScoreMediaPlayerTracker.m b/Sources/SRGAnalyticsMediaPlayer/SRGComScoreMediaPlayerTracker.m index f5ca91ca..362426a3 100644 --- a/Sources/SRGAnalyticsMediaPlayer/SRGComScoreMediaPlayerTracker.m +++ b/Sources/SRGAnalyticsMediaPlayer/SRGComScoreMediaPlayerTracker.m @@ -85,7 +85,7 @@ + (SCORStreamingAnalytics *)streamingAnalyticsForMediaPlayerController:(SRGMedia } if (SRGAnalyticsTracker.sharedTracker.configuration.unitTesting) { - customLabels[@"srg_test_id"] = SRGAnalyticsUnitTestingIdentifier(); + [customLabels srg_safelySetString:SRGAnalyticsUnitTestingIdentifier() forKey:@"srg_test_id"]; } [builder setCustomLabels:customLabels.copy]; diff --git a/Sources/SRGAnalyticsMediaPlayer/SRGMediaPlayerTracker.m b/Sources/SRGAnalyticsMediaPlayer/SRGMediaPlayerTracker.m index 259453de..129a822b 100644 --- a/Sources/SRGAnalyticsMediaPlayer/SRGMediaPlayerTracker.m +++ b/Sources/SRGAnalyticsMediaPlayer/SRGMediaPlayerTracker.m @@ -163,7 +163,7 @@ - (void)recordEvent:(MediaPlayerTrackerEvent)event { NSAssert(event.length != 0, @"An event is required"); - // Ensure a play is emitted before events requiring a session to be opened (the Tag Commander SDK does not open sessions + // Ensure a play is emitted before events requiring a session to be opened (the Commanders Act SDK does not open sessions // automatically) if ([self.lastEvent isEqualToString:MediaPlayerTrackerEventStop] && ([event isEqualToString:MediaPlayerTrackerEventPause] || [event isEqualToString:MediaPlayerTrackerEventSeek])) { [self recordEvent:MediaPlayerTrackerEventPlay withStreamType:streamType time:time timeshift:timeshift analyticsLabels:analyticsLabels userInfo:userInfo]; @@ -210,13 +210,9 @@ - (void)recordEvent:(MediaPlayerTrackerEvent)event NSMutableDictionary *labels = [NSMutableDictionary dictionary]; - [labels srg_safelySetString:SRGAnalyticsTracker.sharedTracker.configuration.environment forKey:@"media_embedding_environment"]; - [labels srg_safelySetString:self.mediaPlayerController.analyticsPlayerName forKey:@"media_player_display"]; [labels srg_safelySetString:self.mediaPlayerController.analyticsPlayerVersion forKey:@"media_player_version"]; - [labels srg_safelySetString:event forKey:@"event_id"]; - // Use current duration as media position for livestreams, raw position otherwise NSTimeInterval mediaPosition = SRGMediaAnalyticsIsLiveStreamType(streamType) ? [self updatedPlaybackDurationWithEvent:event] : SRGMediaAnalyticsCMTimeToMilliseconds(time); [labels srg_safelySetString:@(round(mediaPosition / 1000)).stringValue forKey:@"media_position"]; @@ -255,10 +251,10 @@ - (void)recordEvent:(MediaPlayerTrackerEvent)event [labels addEntriesFromDictionary:mainLabels.labelsDictionary]; if (SRGAnalyticsTracker.sharedTracker.configuration.unitTesting) { - labels[@"srg_test_id"] = self.unitTestingIdentifier; + [labels srg_safelySetString:self.unitTestingIdentifier forKey:@"srg_test_id"]; } - [SRGAnalyticsTracker.sharedTracker trackTagCommanderEventWithLabels:labels.copy]; + [SRGAnalyticsTracker.sharedTracker sendCommandersActCustomEventWithName:event labels:labels.copy]; } #pragma mark Heartbeats diff --git a/Sources/SRGAnalyticsSwiftUI/SRGAnalyticsPageViewTracking.swift b/Sources/SRGAnalyticsSwiftUI/SRGAnalyticsPageViewTracking.swift index ed165cd0..f0255e08 100644 --- a/Sources/SRGAnalyticsSwiftUI/SRGAnalyticsPageViewTracking.swift +++ b/Sources/SRGAnalyticsSwiftUI/SRGAnalyticsPageViewTracking.swift @@ -17,11 +17,12 @@ import SwiftUI @available(watchOS, unavailable) struct SRGPageTrackingView: UIViewControllerRepresentable { let title: String + let type: String let levels: [String]? let labels: SRGAnalyticsPageViewLabels? func makeUIViewController(context: Context) -> TrackerViewController { - return TrackerViewController(srg_pageViewTitle: title, srg_pageViewLevels: levels, srg_pageViewLabels: labels) + return TrackerViewController(srg_pageViewTitle: title, srg_pageViewType: type, srg_pageViewLevels: levels, srg_pageViewLabels: labels) } func updateUIViewController(_ uiViewController: TrackerViewController, context: Context) { @@ -33,11 +34,13 @@ struct SRGPageTrackingView: UIViewControllerRepresentable { */ class TrackerViewController: UIViewController, SRGAnalyticsViewTracking { let srg_pageViewTitle: String + let srg_pageViewType: String let srg_pageViewLevels: [String]? let srg_pageViewLabels: SRGAnalyticsPageViewLabels? - init(srg_pageViewTitle: String, srg_pageViewLevels: [String]?, srg_pageViewLabels: SRGAnalyticsPageViewLabels?) { + init(srg_pageViewTitle: String, srg_pageViewType: String, srg_pageViewLevels: [String]?, srg_pageViewLabels: SRGAnalyticsPageViewLabels?) { self.srg_pageViewTitle = srg_pageViewTitle + self.srg_pageViewType = srg_pageViewType self.srg_pageViewLevels = srg_pageViewLevels self.srg_pageViewLabels = srg_pageViewLabels super.init(nibName: nil, bundle: nil) @@ -45,6 +48,7 @@ struct SRGPageTrackingView: UIViewControllerRepresentable { required init?(coder: NSCoder) { self.srg_pageViewTitle = "" + self.srg_pageViewType = "" self.srg_pageViewLevels = nil self.srg_pageViewLabels = nil super.init(coder: coder) @@ -56,11 +60,11 @@ struct SRGPageTrackingView: UIViewControllerRepresentable { @available(watchOS, unavailable) public extension View { /** - * Mark a view as being tracked with the provided title, levels and labels. + * Mark a view as being tracked with the provided title, type, levels and labels. */ - func tracked(withTitle title: String, levels: [String]? = nil, labels: SRGAnalyticsPageViewLabels? = nil) -> some View { + func tracked(withTitle title: String, type: String, levels: [String]? = nil, labels: SRGAnalyticsPageViewLabels? = nil) -> some View { ZStack { - SRGPageTrackingView(title: title, levels: levels, labels: labels) + SRGPageTrackingView(title: title, type: type, levels: levels, labels: labels) self } } diff --git a/Tests/SRGAnalyticsIdentity-tests.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Tests/SRGAnalyticsIdentity-tests.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6d1306d2..8a5a8851 100644 --- a/Tests/SRGAnalyticsIdentity-tests.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Tests/SRGAnalyticsIdentity-tests.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -19,6 +19,15 @@ "version": "1.3.2-srg6" } }, + { + "package": "TagCommander SDK V5", + "repositoryURL": "https://github.com/CommandersAct/iOSV5.git", + "state": { + "branch": null, + "revision": "b76b700d92c35f02a3d977e7707ecf4df4732b35", + "version": "5.3.2" + } + }, { "package": "libextobjc", "repositoryURL": "https://github.com/SRGSSR/libextobjc.git", @@ -127,24 +136,6 @@ "version": "3.1.0" } }, - { - "package": "TCCore", - "repositoryURL": "https://github.com/SRGSSR/TCCore-xcframework-apple.git", - "state": { - "branch": null, - "revision": "eb686883e63af28174472a09eda97acf07179c88", - "version": "4.5.4-srg5" - } - }, - { - "package": "TCSDK", - "repositoryURL": "https://github.com/SRGSSR/TCSDK-xcframework-apple.git", - "state": { - "branch": null, - "revision": "c4becb0b250258b78cb46225af5e269da834db5a", - "version": "4.4.1-srg5" - } - }, { "package": "UICKeyChainStore", "repositoryURL": "https://github.com/kishikawakatsumi/UICKeyChainStore.git", diff --git a/Tests/SRGAnalyticsIdentityTests/IdentityTestCase.m b/Tests/SRGAnalyticsIdentityTests/IdentityTestCase.m index b9561ae2..7bd3a028 100644 --- a/Tests/SRGAnalyticsIdentityTests/IdentityTestCase.m +++ b/Tests/SRGAnalyticsIdentityTests/IdentityTestCase.m @@ -16,9 +16,9 @@ static SRGAnalyticsConfiguration *TestConfiguration(void) { - SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierRTS - container:10 - siteName:@"rts-app-test-v"]; + SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierSRG + sourceKey:@"39ae8f94-595c-4ca4-81f7-fb7748bd3f04" + siteName:@"srg-test-analytics-apple"]; configuration.unitTesting = YES; return configuration; } @@ -159,54 +159,54 @@ - (void)tearDown #pragma mark Tests -- (void)testHiddenEventWithStandardStartMethod +- (void)testEventWithStandardStartMethod { // This test requires a brand new analytics tracker SRGAnalyticsTracker *analyticsTracker = [SRGAnalyticsTracker performSelector:@selector(new)]; [analyticsTracker startWithConfiguration:TestConfiguration()]; - [self expectationForHiddenEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + [self expectationForEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { XCTAssertNil(labels[@"user_is_logged"]); XCTAssertNil(labels[@"user_id"]); return YES; }]; - [analyticsTracker trackHiddenEventWithName:@"Hidden event"]; + [analyticsTracker trackEventWithName:@"Event"]; [self waitForExpectationsWithTimeout:20. handler:nil]; } -- (void)testHiddenEventWithoutIdentityService +- (void)testEventWithoutIdentityService { [SRGAnalyticsTracker.sharedTracker startWithConfiguration:TestConfiguration() identityService:nil]; - [self expectationForHiddenEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + [self expectationForEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { XCTAssertEqualObjects(labels[@"user_is_logged"], @"false"); XCTAssertNil(labels[@"user_id"]); return YES; }]; - [SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@"Hidden event"]; + [SRGAnalyticsTracker.sharedTracker trackEventWithName:@"Event"]; [self waitForExpectationsWithTimeout:20. handler:nil]; } -- (void)testHiddenEventNotLogged +- (void)testEventNotLogged { [SRGAnalyticsTracker.sharedTracker startWithConfiguration:TestConfiguration() identityService:self.identityService]; - [self expectationForHiddenEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + [self expectationForEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { XCTAssertEqualObjects(labels[@"user_is_logged"], @"false"); XCTAssertNil(labels[@"user_id"]); return YES; }]; - [SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@"Hidden event"]; + [SRGAnalyticsTracker.sharedTracker trackEventWithName:@"Event"]; [self waitForExpectationsWithTimeout:20. handler:nil]; } -- (void)testHiddenEventJustLoggedWithoutAccountInformation +- (void)testEventJustLoggedWithoutAccountInformation { [SRGAnalyticsTracker.sharedTracker startWithConfiguration:TestConfiguration() identityService:self.identityService]; @@ -223,18 +223,18 @@ - (void)testHiddenEventJustLoggedWithoutAccountInformation [self waitForExpectationsWithTimeout:20. handler:nil]; - [self expectationForHiddenEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + [self expectationForEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { XCTAssertEqualObjects(labels[@"user_is_logged"], @"false"); XCTAssertNil(labels[@"user_id"]); return YES; }]; - [SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@"Hidden event"]; + [SRGAnalyticsTracker.sharedTracker trackEventWithName:@"Event"]; [self waitForExpectationsWithTimeout:20. handler:nil]; } -- (void)testHiddenEventLogged +- (void)testEventLogged { [SRGAnalyticsTracker.sharedTracker startWithConfiguration:TestConfiguration() identityService:self.identityService]; @@ -249,18 +249,18 @@ - (void)testHiddenEventLogged [self waitForExpectationsWithTimeout:20. handler:nil]; - [self expectationForHiddenEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + [self expectationForEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { XCTAssertEqualObjects(labels[@"user_is_logged"], @"true"); XCTAssertEqualObjects(labels[@"user_id"], TestUserId); return YES; }]; - [SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@"Hidden event"]; + [SRGAnalyticsTracker.sharedTracker trackEventWithName:@"Event"]; [self waitForExpectationsWithTimeout:20. handler:nil]; } -- (void)testHiddenEventAfterLogout +- (void)testEventAfterLogout { [SRGAnalyticsTracker.sharedTracker startWithConfiguration:TestConfiguration() identityService:self.identityService]; @@ -275,7 +275,7 @@ - (void)testHiddenEventAfterLogout [self waitForExpectationsWithTimeout:20. handler:nil]; - [self expectationForHiddenEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + [self expectationForEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { XCTAssertEqualObjects(labels[@"user_is_logged"], @"false"); XCTAssertNil(labels[@"user_id"]); return YES; @@ -283,7 +283,7 @@ - (void)testHiddenEventAfterLogout [self.identityService logout]; - [SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@"Hidden event"]; + [SRGAnalyticsTracker.sharedTracker trackEventWithName:@"Event"]; [self waitForExpectationsWithTimeout:20. handler:nil]; } @@ -310,12 +310,13 @@ - (void)testPageViewEventLogged }]; [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:@"Page view" + type:@"Type" levels:nil]; [self waitForExpectationsWithTimeout:20. handler:nil]; } -- (void)testHiddenPlaybackEventLogged +- (void)testPlaybackEventLogged { [SRGAnalyticsTracker.sharedTracker startWithConfiguration:TestConfiguration() identityService:self.identityService]; @@ -344,7 +345,7 @@ - (void)testHiddenPlaybackEventLogged [self waitForExpectationsWithTimeout:20. handler:nil]; } -- (void)testHiddenEventForTrackerStartedWithLoggedInUser +- (void)testEventForTrackerStartedWithLoggedInUser { [self expectationForSingleNotification:SRGIdentityServiceUserDidLoginNotification object:self.identityService handler:nil]; [self expectationForSingleNotification:SRGIdentityServiceDidUpdateAccountNotification object:self.identityService handler:nil]; @@ -360,20 +361,20 @@ - (void)testHiddenEventForTrackerStartedWithLoggedInUser SRGAnalyticsTracker *analyticsTracker = [SRGAnalyticsTracker performSelector:@selector(new)]; [analyticsTracker startWithConfiguration:TestConfiguration() identityService:self.identityService]; - [self expectationForHiddenEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + [self expectationForEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { XCTAssertEqualObjects(labels[@"user_is_logged"], @"true"); XCTAssertEqualObjects(labels[@"user_id"], TestUserId); return YES; }]; - [analyticsTracker trackHiddenEventWithName:@"Hidden event"]; + [analyticsTracker trackEventWithName:@"Event"]; [self waitForExpectationsWithTimeout:20. handler:nil]; } #if TARGET_OS_IOS -- (void)testHiddenEventAfterUnauthorizedCall +- (void)testEventAfterUnauthorizedCall { [SRGAnalyticsTracker.sharedTracker startWithConfiguration:TestConfiguration() identityService:self.identityService]; @@ -394,13 +395,13 @@ - (void)testHiddenEventAfterUnauthorizedCall [self waitForExpectationsWithTimeout:20. handler:nil]; - [self expectationForHiddenEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + [self expectationForEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { XCTAssertEqualObjects(labels[@"user_is_logged"], @"false"); XCTAssertNil(labels[@"user_id"]); return YES; }]; - [SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@"Hidden event"]; + [SRGAnalyticsTracker.sharedTracker trackEventWithName:@"Event"]; [self waitForExpectationsWithTimeout:20. handler:nil]; } diff --git a/Tests/SRGAnalyticsTests/ComScoreDataProviderTestCase.m b/Tests/SRGAnalyticsTests/ComScoreDataProviderTestCase.m index a943ad58..95cb2799 100644 --- a/Tests/SRGAnalyticsTests/ComScoreDataProviderTestCase.m +++ b/Tests/SRGAnalyticsTests/ComScoreDataProviderTestCase.m @@ -6,6 +6,8 @@ #import "XCTestCase+Tests.h" +#import "TrackerSingletonSetup.h" + @import SRGAnalyticsDataProvider; @import SRGDataProviderNetwork; @@ -24,6 +26,11 @@ @implementation ComScoreDataProviderTestCase #pragma mark Setup and teardown ++ (void)setUp +{ + SetupTestSingletonTracker(); +} + - (void)setUp { SRGAnalyticsRenewUnitTestingIdentifier(); diff --git a/Tests/SRGAnalyticsTests/ComScoreMediaPlayerTestCase.m b/Tests/SRGAnalyticsTests/ComScoreMediaPlayerTestCase.m index 22f9d4b9..161f46ec 100644 --- a/Tests/SRGAnalyticsTests/ComScoreMediaPlayerTestCase.m +++ b/Tests/SRGAnalyticsTests/ComScoreMediaPlayerTestCase.m @@ -6,6 +6,7 @@ #import "NSNotificationCenter+Tests.h" #import "Segment.h" +#import "TrackerSingletonSetup.h" #import "XCTestCase+Tests.h" @import SRGAnalyticsMediaPlayer; @@ -36,6 +37,11 @@ @implementation ComScoreMediaPlayerTestCase #pragma mark Setup and teardown ++ (void)setUp +{ + SetupTestSingletonTracker(); +} + - (void)setUp { SRGAnalyticsRenewUnitTestingIdentifier(); @@ -493,7 +499,7 @@ - (void)testCommonLabels XCTAssertEqualObjects(labels[@"c2"], @"6036016"); XCTAssertEqualObjects(labels[@"ns_ap_an"], @"xctest"); // Cannot sadly test mp_v with SPM and XCTest - XCTAssertEqualObjects(labels[@"mp_brand"], @"RTS"); + XCTAssertEqualObjects(labels[@"mp_brand"], @"SRG"); XCTAssertEqualObjects(labels[@"ns_st_ev"], @"play"); XCTAssertEqualObjects(labels[@"ns_st_mp"], @"SRGMediaPlayer"); XCTAssertEqualObjects(labels[@"ns_st_mv"], SRGMediaPlayerMarketingVersion()); diff --git a/Tests/SRGAnalyticsTests/ComScoreTrackerTestCase.m b/Tests/SRGAnalyticsTests/ComScoreTrackerTestCase.m index 7e5aba48..24277781 100644 --- a/Tests/SRGAnalyticsTests/ComScoreTrackerTestCase.m +++ b/Tests/SRGAnalyticsTests/ComScoreTrackerTestCase.m @@ -5,6 +5,7 @@ // #import "NSNotificationCenter+Tests.h" +#import "TrackerSingletonSetup.h" #import "XCTestCase+Tests.h" @interface ComScoreTrackerTestCase : XCTestCase @@ -15,6 +16,11 @@ @implementation ComScoreTrackerTestCase #pragma mark Setup and teardown ++ (void)setUp +{ + SetupTestSingletonTracker(); +} + - (void)setUp { SRGAnalyticsRenewUnitTestingIdentifier(); @@ -22,7 +28,7 @@ - (void)setUp #pragma mark Tests -- (void)testNoHiddenEvents +- (void)testNoEvents { id eventObserver = [NSNotificationCenter.defaultCenter addObserverForComScoreHiddenEventNotificationUsingBlock:^(NSString *event, NSDictionary *labels) { XCTFail(@"No event must be received"); @@ -30,7 +36,7 @@ - (void)testNoHiddenEvents [self expectationForElapsedTimeInterval:10. withHandler:nil]; - [SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@"Hidden event"]; + [SRGAnalyticsTracker.sharedTracker trackEventWithName:@"Event"]; [self waitForExpectationsWithTimeout:20. handler:^(NSError * _Nullable error) { [NSNotificationCenter.defaultCenter removeObserver:eventObserver]; diff --git a/Tests/SRGAnalyticsTests/ConfigurationTestCase.m b/Tests/SRGAnalyticsTests/ConfigurationTestCase.m index 8a395e9b..d2aed9e6 100644 --- a/Tests/SRGAnalyticsTests/ConfigurationTestCase.m +++ b/Tests/SRGAnalyticsTests/ConfigurationTestCase.m @@ -17,22 +17,20 @@ @implementation ConfigurationTestCase - (void)testCreation { SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierSRF - container:7 + sourceKey:@"39ae8f94-595c-4ca4-81f7-fb7748bd3f04" siteName:@"site-name"]; XCTAssertTrue(configuration.centralized); XCTAssertFalse(configuration.unitTesting); XCTAssertEqualObjects(configuration.businessUnitIdentifier, SRGAnalyticsBusinessUnitIdentifierSRF); XCTAssertEqual(configuration.site, 3666); - XCTAssertEqual(configuration.container, 7); + XCTAssertEqualObjects(configuration.sourceKey, @"39ae8f94-595c-4ca4-81f7-fb7748bd3f04"); XCTAssertEqualObjects(configuration.siteName, @"site-name"); - XCTAssertEqual(configuration.environmentMode, SRGAnalyticsEnvironmentModeAutomatic); - XCTAssertEqualObjects(configuration.environment, SRGAnalyticsEnvironmentPreProduction); } - (void)testBusinessUnitSpecificConfiguration { SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierSRF - container:7 + sourceKey:@"39ae8f94-595c-4ca4-81f7-fb7748bd3f04" siteName:@"site-name"]; configuration.centralized = NO; @@ -40,50 +38,14 @@ - (void)testBusinessUnitSpecificConfiguration XCTAssertFalse(configuration.unitTesting); XCTAssertEqualObjects(configuration.businessUnitIdentifier, SRGAnalyticsBusinessUnitIdentifierSRF); XCTAssertEqual(configuration.site, 3667); - XCTAssertEqual(configuration.container, 7); + XCTAssertEqualObjects(configuration.sourceKey, @"39ae8f94-595c-4ca4-81f7-fb7748bd3f04"); XCTAssertEqualObjects(configuration.siteName, @"site-name"); - XCTAssertEqual(configuration.environmentMode, SRGAnalyticsEnvironmentModeAutomatic); - XCTAssertEqualObjects(configuration.environment, SRGAnalyticsEnvironmentPreProduction); -} - -- (void)testEnvironmentModePreProduction -{ - SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierSRF - container:7 - siteName:@"site-name"]; - configuration.environmentMode = SRGAnalyticsEnvironmentModePreProduction; - - XCTAssertTrue(configuration.centralized); - XCTAssertFalse(configuration.unitTesting); - XCTAssertEqualObjects(configuration.businessUnitIdentifier, SRGAnalyticsBusinessUnitIdentifierSRF); - XCTAssertEqual(configuration.site, 3666); - XCTAssertEqual(configuration.container, 7); - XCTAssertEqualObjects(configuration.siteName, @"site-name"); - XCTAssertEqual(configuration.environmentMode, SRGAnalyticsEnvironmentModePreProduction); - XCTAssertEqualObjects(configuration.environment, SRGAnalyticsEnvironmentPreProduction); -} - -- (void)testEnvironmentModeProduction -{ - SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierSRF - container:7 - siteName:@"site-name"]; - configuration.environmentMode = SRGAnalyticsEnvironmentModeProduction; - - XCTAssertTrue(configuration.centralized); - XCTAssertFalse(configuration.unitTesting); - XCTAssertEqualObjects(configuration.businessUnitIdentifier, SRGAnalyticsBusinessUnitIdentifierSRF); - XCTAssertEqual(configuration.site, 3666); - XCTAssertEqual(configuration.container, 7); - XCTAssertEqualObjects(configuration.siteName, @"site-name"); - XCTAssertEqual(configuration.environmentMode, SRGAnalyticsEnvironmentModeProduction); - XCTAssertEqualObjects(configuration.environment, @"prod"); } - (void)testUnitTestingConfiguration { SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierSRF - container:7 + sourceKey:@"39ae8f94-595c-4ca4-81f7-fb7748bd3f04" siteName:@"site-name"]; configuration.unitTesting = YES; @@ -91,16 +53,14 @@ - (void)testUnitTestingConfiguration XCTAssertTrue(configuration.unitTesting); XCTAssertEqualObjects(configuration.businessUnitIdentifier, SRGAnalyticsBusinessUnitIdentifierSRF); XCTAssertEqual(configuration.site, 3666); - XCTAssertEqual(configuration.container, 7); + XCTAssertEqualObjects(configuration.sourceKey, @"39ae8f94-595c-4ca4-81f7-fb7748bd3f04"); XCTAssertEqualObjects(configuration.siteName, @"site-name"); - XCTAssertEqual(configuration.environmentMode, SRGAnalyticsEnvironmentModeAutomatic); - XCTAssertEqualObjects(configuration.environment, SRGAnalyticsEnvironmentPreProduction); } - (void)testCopy { SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierSRF - container:7 + sourceKey:@"39ae8f94-595c-4ca4-81f7-fb7748bd3f04" siteName:@"site-name"]; configuration.centralized = YES; configuration.unitTesting = YES; @@ -110,10 +70,8 @@ - (void)testCopy XCTAssertEqual(configuration.unitTesting, configurationCopy.unitTesting); XCTAssertEqualObjects(configuration.businessUnitIdentifier, configurationCopy.businessUnitIdentifier); XCTAssertEqual(configuration.site, configurationCopy.site); - XCTAssertEqual(configuration.container, configurationCopy.container); + XCTAssertEqualObjects(configuration.sourceKey, configurationCopy.sourceKey); XCTAssertEqualObjects(configuration.siteName, configurationCopy.siteName); - XCTAssertEqual(configuration.environmentMode, configurationCopy.environmentMode); - XCTAssertEqualObjects(configuration.environment, configurationCopy.environment); } @end diff --git a/Tests/SRGAnalyticsTests/DataProviderTestCase.m b/Tests/SRGAnalyticsTests/DataProviderTestCase.m index caad6adf..73975236 100644 --- a/Tests/SRGAnalyticsTests/DataProviderTestCase.m +++ b/Tests/SRGAnalyticsTests/DataProviderTestCase.m @@ -9,6 +9,7 @@ // Private header #import "SRGAnalyticsLabels+Private.h" #import "SRGResource+SRGAnalyticsDataProvider.h" +#import "TrackerSingletonSetup.h" @import libextobjc; @import SRGAnalyticsDataProvider; @@ -34,6 +35,11 @@ @implementation DataProviderTestCase #pragma mark Setup and teardown ++ (void)setUp +{ + SetupTestSingletonTracker(); +} + - (void)setUp { SRGAnalyticsRenewUnitTestingIdentifier(); @@ -54,11 +60,11 @@ - (void)testPrepareToPlayMediaComposition __block BOOL playReceived = NO; __block BOOL pauseReceived = NO; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - if ([labels[@"event_id"] isEqualToString:@"play"]) { + if ([event isEqualToString:@"play"]) { XCTAssertFalse(pauseReceived); playReceived = YES; } - else if ([labels[@"event_id"] isEqualToString:@"pause"]) { + else if ([event isEqualToString:@"pause"]) { pauseReceived = YES; } @@ -90,7 +96,7 @@ - (void)testPrepareToPlayMediaComposition XCTAssertEqual(self.mediaPlayerController.playbackState, SRGMediaPlayerPlaybackStatePaused); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_segment"], @"Archive footage of the man and his moods"); XCTAssertEqualObjects(labels[@"media_streaming_quality"], @"HD"); XCTAssertEqualObjects(labels[@"media_urn"], @"urn:swi:video:42297626"); @@ -195,7 +201,7 @@ - (void)testPlaySegmentInMediaComposition - (void)testPlayLivestreamInMediaComposition { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_segment"], @"Livestream"); XCTAssertEqualObjects(labels[@"media_urn"], @"urn:rts:video:8841634"); return YES; @@ -220,7 +226,7 @@ - (void)testPlayLivestreamInMediaComposition - (void)testPlay360InMediaComposition { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_urn"], @"urn:rts:video:8414077"); return YES; }]; @@ -840,7 +846,7 @@ - (void)testAudioAnalyticsLabels - (void)testPlayMediaCompositionWithSourceUid { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_urn"], @"urn:swi:video:42297626"); XCTAssertEqualObjects(labels[@"source_id"], @"SWI source unique id"); return YES; @@ -915,11 +921,11 @@ - (void)testSeekToSegmentInMediaCompositionWithSourceUid XCTAssertNotNil(segment); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - if (! [labels[@"event_id"] isEqualToString:@"play"]) { + if (! [event isEqualToString:@"play"]) { return NO; } - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_urn"], @"urn:srf:video:d5cdaf81-7df7-42d8-8c1a-ea31ed1913fc"); XCTAssertEqualObjects(labels[@"source_id"], @"SRF source unique id"); return YES; @@ -935,7 +941,7 @@ - (void)testSeekToSegmentInMediaCompositionWithSourceUid - (void)testSwitchChapterInMediaCompositionWithSourceUid { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_urn"], @"urn:srf:video:84043ead-6e5a-4a05-875c-c1aa2998aa43"); XCTAssertEqualObjects(labels[@"source_id"], @"SRF source unique id"); return YES; @@ -960,11 +966,11 @@ - (void)testSwitchChapterInMediaCompositionWithSourceUid XCTAssertNotNil(chapter1); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - if (! [labels[@"event_id"] isEqualToString:@"play"]) { + if (! [event isEqualToString:@"play"]) { return NO; } - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_urn"], @"urn:srf:video:802df764-3044-488e-aff0-fca3cdec85ff"); XCTAssertEqualObjects(labels[@"source_id"], @"Another SRF source unique id"); return YES; @@ -981,11 +987,11 @@ - (void)testSwitchChapterInMediaCompositionWithSourceUid XCTAssertNotNil(chapter2); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - if (! [labels[@"event_id"] isEqualToString:@"play"]) { + if (! [event isEqualToString:@"play"]) { return NO; } - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_urn"], @"urn:srf:video:6ca4aaed-cc8a-4568-be5a-773afd20bbcf"); XCTAssertNil(labels[@"source_id"]); return YES; @@ -999,7 +1005,7 @@ - (void)testSwitchChapterInMediaCompositionWithSourceUid - (void)testUpdateMediaCompositionWithSourceUid { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_urn"], @"urn:swi:video:42297626"); XCTAssertEqualObjects(labels[@"source_id"], @"SWI source unique id"); return YES; @@ -1029,7 +1035,7 @@ - (void)testUpdateMediaCompositionWithSourceUid [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"pause"); + XCTAssertEqualObjects(event, @"pause"); XCTAssertEqualObjects(labels[@"media_urn"], @"urn:swi:video:42297626"); XCTAssertEqualObjects(labels[@"source_id"], @"SWI source unique id"); return YES; diff --git a/Tests/SRGAnalyticsTests/HiddenEventLabelsTestCase.m b/Tests/SRGAnalyticsTests/EventLabelsTestCase.m similarity index 78% rename from Tests/SRGAnalyticsTests/HiddenEventLabelsTestCase.m rename to Tests/SRGAnalyticsTests/EventLabelsTestCase.m index e2dba7c9..dd9a92b4 100644 --- a/Tests/SRGAnalyticsTests/HiddenEventLabelsTestCase.m +++ b/Tests/SRGAnalyticsTests/EventLabelsTestCase.m @@ -8,24 +8,24 @@ #import "SRGAnalyticsLabels+Private.h" -@interface HiddenEventLabelsTestCase : XCTestCase +@interface EventLabelsTestCase : XCTestCase @end -@implementation HiddenEventLabelsTestCase +@implementation EventLabelsTestCase #pragma mark Tests - (void)testEmpty { - SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels = [[SRGAnalyticsEventLabels alloc] init]; XCTAssertNotNil(labels.labelsDictionary); XCTAssertEqual(labels.labelsDictionary.count, 0); } - (void)testNonEmpty { - SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels = [[SRGAnalyticsEventLabels alloc] init]; labels.type = @"type"; labels.value = @"value"; labels.source = @"source"; @@ -50,7 +50,7 @@ - (void)testNonEmpty - (void)testEquality { - SRGAnalyticsHiddenEventLabels *labels1 = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels1 = [[SRGAnalyticsEventLabels alloc] init]; labels1.type = @"type"; labels1.value = @"value"; labels1.source = @"source"; @@ -59,7 +59,7 @@ - (void)testEquality labels1.customInfo = @{ @"key" : @"value" }; XCTAssertEqualObjects(labels1, labels1); - SRGAnalyticsHiddenEventLabels *labels2 = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels2 = [[SRGAnalyticsEventLabels alloc] init]; labels2.type = @"type"; labels2.value = @"value"; labels2.source = @"source"; @@ -68,7 +68,7 @@ - (void)testEquality labels2.customInfo = @{ @"key" : @"value" }; XCTAssertEqualObjects(labels1, labels2); - SRGAnalyticsHiddenEventLabels *labels3 = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels3 = [[SRGAnalyticsEventLabels alloc] init]; labels3.type = @"other_type"; labels3.value = @"value"; labels3.source = @"source"; @@ -77,7 +77,7 @@ - (void)testEquality labels3.customInfo = @{ @"key" : @"value" }; XCTAssertNotEqualObjects(labels1, labels3); - SRGAnalyticsHiddenEventLabels *labels4 = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels4 = [[SRGAnalyticsEventLabels alloc] init]; labels4.type = @"type"; labels4.value = @"other_value"; labels4.source = @"source"; @@ -86,7 +86,7 @@ - (void)testEquality labels4.customInfo = @{ @"key" : @"value" }; XCTAssertNotEqualObjects(labels1, labels4); - SRGAnalyticsHiddenEventLabels *labels5 = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels5 = [[SRGAnalyticsEventLabels alloc] init]; labels5.type = @"type"; labels5.value = @"value"; labels5.source = @"other_source"; @@ -95,7 +95,7 @@ - (void)testEquality labels5.customInfo = @{ @"key" : @"value" }; XCTAssertNotEqualObjects(labels1, labels5); - SRGAnalyticsHiddenEventLabels *labels6 = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels6 = [[SRGAnalyticsEventLabels alloc] init]; labels6.type = @"type"; labels6.value = @"value"; labels6.extraValue1 = @"other_extra_value1"; @@ -104,7 +104,7 @@ - (void)testEquality labels6.customInfo = @{ @"key" : @"value" }; XCTAssertNotEqualObjects(labels1, labels6); - SRGAnalyticsHiddenEventLabels *labels7 = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels7 = [[SRGAnalyticsEventLabels alloc] init]; labels7.type = @"type"; labels7.value = @"value"; labels7.source = @"source"; @@ -116,7 +116,7 @@ - (void)testEquality - (void)testCopy { - SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels = [[SRGAnalyticsEventLabels alloc] init]; labels.type = @"type"; labels.value = @"value"; labels.source = @"source"; @@ -124,13 +124,13 @@ - (void)testCopy labels.extraValue2 = @"extra_value2"; labels.customInfo = @{ @"key" : @"value" }; - SRGAnalyticsHiddenEventLabels *labelsCopy = labels.copy; + SRGAnalyticsEventLabels *labelsCopy = labels.copy; XCTAssertEqualObjects(labels, labelsCopy); } - (void)testCustomInfoOverrides { - SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels = [[SRGAnalyticsEventLabels alloc] init]; labels.type = @"type"; labels.value = @"value"; labels.source = @"source"; diff --git a/Tests/SRGAnalyticsTests/MediaPlayerTestCase.m b/Tests/SRGAnalyticsTests/MediaPlayerTestCase.m index 34f6e54b..7e40132b 100644 --- a/Tests/SRGAnalyticsTests/MediaPlayerTestCase.m +++ b/Tests/SRGAnalyticsTests/MediaPlayerTestCase.m @@ -6,6 +6,7 @@ #import "NSNotificationCenter+Tests.h" #import "Segment.h" +#import "TrackerSingletonSetup.h" #import "XCTestCase+Tests.h" @import MediaAccessibility; @@ -51,6 +52,11 @@ @implementation MediaPlayerTestCase #pragma mark Setup and teardown ++ (void)setUp +{ + SetupTestSingletonTracker(); +} + - (void)setUp { SRGAnalyticsRenewUnitTestingIdentifier(); @@ -122,7 +128,7 @@ - (void)testPrepareToPlay [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); return YES; }]; @@ -131,7 +137,7 @@ - (void)testPrepareToPlay [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); return YES; }]; @@ -143,7 +149,7 @@ - (void)testPrepareToPlay - (void)testEntirePlayback { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); return YES; }]; @@ -156,14 +162,14 @@ - (void)testEntirePlayback __block BOOL playReceived = NO; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - if ([labels[@"event_id"] isEqualToString:@"seek"]) { + if ([event isEqualToString:@"seek"]) { XCTAssertFalse(seekReceived); XCTAssertFalse(playReceived); XCTAssertEqualObjects(labels[@"media_position"], @"0"); seekReceived = YES; } - else if ([labels[@"event_id"] isEqualToString:@"play"]) { + else if ([event isEqualToString:@"play"]) { XCTAssertFalse(playReceived); XCTAssertEqualObjects(labels[@"media_position"], @"1795"); @@ -178,7 +184,7 @@ - (void)testEntirePlayback [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"eof"); + XCTAssertEqualObjects(event, @"eof"); XCTAssertEqualObjects(labels[@"media_position"], @"1800"); return YES; }]; @@ -236,7 +242,7 @@ - (void)testReplay - (void)testPlayStop { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); return YES; }]; @@ -255,7 +261,7 @@ - (void)testPlayStop }]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_position"], @"1"); return YES; }]; @@ -268,7 +274,7 @@ - (void)testPlayStop - (void)testPlayReset { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); return YES; }]; @@ -287,7 +293,7 @@ - (void)testPlayReset }]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_position"], @"1"); return YES; }]; @@ -463,7 +469,7 @@ - (void)testPlayPausePlay - (void)testConsecutiveMedias { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"stream_name"], @"full1"); return YES; }]; @@ -476,7 +482,7 @@ - (void)testConsecutiveMedias [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"stream_name"], @"full1"); return YES; }]; @@ -489,7 +495,7 @@ - (void)testConsecutiveMedias [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"stream_name"], @"full2"); return YES; }]; @@ -497,7 +503,7 @@ - (void)testConsecutiveMedias [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"stream_name"], @"full2"); return YES; }]; @@ -542,9 +548,8 @@ - (void)testWithoutLabels - (void)testCommonLabels { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"navigation_app_site_name"], @"rts-app-test-v"); - XCTAssertEqualObjects(labels[@"navigation_environment"], @"preprod"); - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(labels[@"navigation_app_site_name"], @"srg-test-analytics-apple"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_player_display"], @"SRGMediaPlayer"); XCTAssertEqualObjects(labels[@"media_player_version"], SRGMediaPlayerMarketingVersion()); XCTAssertEqualObjects(labels[@"test_label"], @"test_value"); @@ -560,7 +565,7 @@ - (void)testCommonLabels - (void)testCommonLabelsOverride { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_player_display"], @"CustomPlayer"); XCTAssertEqualObjects(labels[@"media_player_version"], @"1.0"); return YES; @@ -574,7 +579,7 @@ - (void)testCommonLabelsOverride [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_player_display"], @"CustomPlayer"); XCTAssertEqualObjects(labels[@"media_player_version"], @"1.0"); return YES; @@ -585,7 +590,7 @@ - (void)testCommonLabelsOverride [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_player_display"], @"CustomPlayer"); XCTAssertEqualObjects(labels[@"media_player_version"], @"1.0"); return YES; @@ -596,7 +601,7 @@ - (void)testCommonLabelsOverride [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_player_display"], @"SRGMediaPlayer"); XCTAssertEqualObjects(labels[@"media_player_version"], SRGMediaPlayerMarketingVersion()); return YES; @@ -613,7 +618,7 @@ - (void)testCommonLabelsOverride - (void)testOnDemandPlayback { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); XCTAssertNil(labels[@"media_timeshift"]); return YES; @@ -624,7 +629,7 @@ - (void)testOnDemandPlayback [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); XCTAssertNil(labels[@"media_timeshift"]); return YES; @@ -638,7 +643,7 @@ - (void)testOnDemandPlayback - (void)testLivePlayback { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_timeshift"], @"0"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); return YES; @@ -658,7 +663,7 @@ - (void)testLivePlayback }]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"pause"); + XCTAssertEqualObjects(event, @"pause"); XCTAssertEqualObjects(labels[@"media_timeshift"], @"0"); XCTAssertEqualObjects(labels[@"media_position"], @"1"); return YES; @@ -678,7 +683,7 @@ - (void)testLivePlayback }]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_timeshift"], @"0"); XCTAssertEqualObjects(labels[@"media_position"], @"1"); return YES; @@ -692,7 +697,7 @@ - (void)testLivePlayback - (void)testDVRPlayback { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_timeshift"], @"0"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); return YES; @@ -715,7 +720,7 @@ - (void)testDVRPlayback __block BOOL playReceived = NO; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - if ([labels[@"event_id"] isEqualToString:@"seek"]) { + if ([event isEqualToString:@"seek"]) { XCTAssertFalse(seekReceived); XCTAssertFalse(playReceived); @@ -723,7 +728,7 @@ - (void)testDVRPlayback XCTAssertEqualObjects(labels[@"media_position"], @"1"); seekReceived = YES; } - else if ([labels[@"event_id"] isEqualToString:@"play"]) { + else if ([event isEqualToString:@"play"]) { XCTAssertFalse(playReceived); XCTAssertEqualObjects(labels[@"media_timeshift"], @"45"); @@ -748,7 +753,7 @@ - (void)testDVRPlayback }]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_timeshift"], @"44"); // Not 45 because of chunks XCTAssertEqualObjects(labels[@"media_position"], @"2"); return YES; @@ -762,7 +767,7 @@ - (void)testDVRPlayback - (void)testLiveStopLive { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_timeshift"], @"0"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); return YES; @@ -782,7 +787,7 @@ - (void)testLiveStopLive }]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_timeshift"], @"0"); XCTAssertEqualObjects(labels[@"media_position"], @"1"); return YES; @@ -793,7 +798,7 @@ - (void)testLiveStopLive [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_timeshift"], @"0"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); return YES; @@ -813,7 +818,7 @@ - (void)testLiveStopLive }]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_timeshift"], @"0"); XCTAssertEqualObjects(labels[@"media_position"], @"1"); return YES; @@ -827,7 +832,7 @@ - (void)testLiveStopLive - (void)testVolumeLabel { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_volume"], @"0"); return YES; }]; @@ -841,7 +846,7 @@ - (void)testVolumeLabel [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"pause"); + XCTAssertEqualObjects(event, @"pause"); XCTAssertNotNil(labels[@"media_volume"]); return YES; }]; @@ -855,7 +860,7 @@ - (void)testVolumeLabel - (void)testBandwidthLabel { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertNotEqualObjects(labels[@"media_bandwidth"], @"0"); return YES; }]; @@ -865,7 +870,7 @@ - (void)testBandwidthLabel [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertNil(labels[@"media_bandwidth"]); return YES; }]; @@ -875,36 +880,13 @@ - (void)testBandwidthLabel [self waitForExpectationsWithTimeout:20. handler:nil]; } -- (void)testEnvironment -{ - [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); - XCTAssertEqualObjects(labels[@"media_embedding_environment"], @"preprod"); - return YES; - }]; - - [self playURL:OnDemandTestURL() atPosition:nil withSegments:nil]; - - [self waitForExpectationsWithTimeout:20. handler:nil]; - - [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); - XCTAssertEqualObjects(labels[@"media_embedding_environment"], @"preprod"); - return YES; - }]; - - [self.mediaPlayerController reset]; - - [self waitForExpectationsWithTimeout:20. handler:nil]; -} - - (void)testSubtitles { MACaptionAppearanceSetDisplayType(kMACaptionAppearanceDomainUser, kMACaptionAppearanceDisplayTypeAlwaysOn); MACaptionAppearanceAddSelectedLanguage(kMACaptionAppearanceDomainUser, (__bridge CFStringRef _Nonnull)@"en"); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_subtitles_on"], @"true"); XCTAssertEqualObjects(labels[@"media_subtitle_selection"], @"EN"); return YES; @@ -915,7 +897,7 @@ - (void)testSubtitles [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_subtitles_on"], @"true"); XCTAssertEqualObjects(labels[@"media_subtitle_selection"], @"EN"); return YES; @@ -932,7 +914,7 @@ - (void)testSubtitlesDuringEntirePlayback MACaptionAppearanceAddSelectedLanguage(kMACaptionAppearanceDomainUser, (__bridge CFStringRef _Nonnull)@"en"); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_subtitles_on"], @"true"); XCTAssertEqualObjects(labels[@"media_subtitle_selection"], @"EN"); return YES; @@ -946,7 +928,7 @@ - (void)testSubtitlesDuringEntirePlayback __block BOOL playReceived = NO; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - if ([labels[@"event_id"] isEqualToString:@"seek"]) { + if ([event isEqualToString:@"seek"]) { XCTAssertFalse(seekReceived); XCTAssertFalse(playReceived); @@ -954,7 +936,7 @@ - (void)testSubtitlesDuringEntirePlayback XCTAssertEqualObjects(labels[@"media_subtitle_selection"], @"EN"); seekReceived = YES; } - else if ([labels[@"event_id"] isEqualToString:@"play"]) { + else if ([event isEqualToString:@"play"]) { XCTAssertFalse(playReceived); XCTAssertEqualObjects(labels[@"media_subtitles_on"], @"true"); @@ -970,7 +952,7 @@ - (void)testSubtitlesDuringEntirePlayback [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"eof"); + XCTAssertEqualObjects(event, @"eof"); XCTAssertEqualObjects(labels[@"media_subtitles_on"], @"true"); XCTAssertEqualObjects(labels[@"media_subtitle_selection"], @"EN"); return YES; @@ -984,7 +966,7 @@ - (void)testNoSubtitles MACaptionAppearanceSetDisplayType(kMACaptionAppearanceDomainUser, kMACaptionAppearanceDisplayTypeAutomatic); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_subtitles_on"], @"false"); XCTAssertNil(labels[@"media_subtitle_selection"]); return YES; @@ -995,7 +977,7 @@ - (void)testNoSubtitles [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_subtitles_on"], @"false"); XCTAssertNil(labels[@"media_subtitle_selection"]); return YES; @@ -1011,7 +993,7 @@ - (void)testSubtitlesForAudioContent MACaptionAppearanceSetDisplayType(kMACaptionAppearanceDomainUser, kMACaptionAppearanceDisplayTypeAutomatic); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_subtitles_on"], @"false"); XCTAssertNil(labels[@"media_subtitle_selection"]); return YES; @@ -1022,7 +1004,7 @@ - (void)testSubtitlesForAudioContent [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_subtitles_on"], @"false"); XCTAssertNil(labels[@"media_subtitle_selection"]); return YES; @@ -1036,7 +1018,7 @@ - (void)testSubtitlesForAudioContent - (void)testDefaultAudioTrack { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_audio_track"], @"EN"); return YES; }]; @@ -1046,7 +1028,7 @@ - (void)testDefaultAudioTrack [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_audio_track"], @"EN"); return YES; }]; @@ -1059,7 +1041,7 @@ - (void)testDefaultAudioTrack - (void)testNoAudioTrackInformation { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_audio_track"], @"UND"); return YES; }]; @@ -1069,7 +1051,7 @@ - (void)testNoAudioTrackInformation [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_audio_track"], @"UND"); return YES; }]; @@ -1082,7 +1064,7 @@ - (void)testNoAudioTrackInformation - (void)testNoAudioTrack { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertNil(labels[@"media_audio_track"]); return YES; }]; @@ -1092,7 +1074,7 @@ - (void)testNoAudioTrack [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertNil(labels[@"media_audio_track"]); return YES; }]; @@ -1105,7 +1087,7 @@ - (void)testNoAudioTrack - (void)testAudioTrackForAudioContent { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertNil(labels[@"media_audio_track"]); return YES; }]; @@ -1115,7 +1097,7 @@ - (void)testAudioTrackForAudioContent [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertNil(labels[@"media_audio_track"]); return YES; }]; @@ -1128,7 +1110,7 @@ - (void)testAudioTrackForAudioContent - (void)testSelectedAudioTrack { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_audio_track"], @"FR"); return YES; }]; @@ -1145,7 +1127,7 @@ - (void)testSelectedAudioTrack [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_audio_track"], @"FR"); return YES; }]; @@ -1158,7 +1140,7 @@ - (void)testSelectedAudioTrack - (void)testSelectedAudioTrackDuringEntirePlayback { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_audio_track"], @"DE"); return YES; }]; @@ -1178,14 +1160,14 @@ - (void)testSelectedAudioTrackDuringEntirePlayback __block BOOL playReceived = NO; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - if ([labels[@"event_id"] isEqualToString:@"seek"]) { + if ([event isEqualToString:@"seek"]) { XCTAssertFalse(seekReceived); XCTAssertFalse(playReceived); XCTAssertEqualObjects(labels[@"media_audio_track"], @"DE"); seekReceived = YES; } - else if ([labels[@"event_id"] isEqualToString:@"play"]) { + else if ([event isEqualToString:@"play"]) { XCTAssertFalse(playReceived); XCTAssertEqualObjects(labels[@"media_audio_track"], @"DE"); @@ -1200,7 +1182,7 @@ - (void)testSelectedAudioTrackDuringEntirePlayback [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"eof"); + XCTAssertEqualObjects(event, @"eof"); XCTAssertEqualObjects(labels[@"media_audio_track"], @"DE"); return YES; }]; @@ -1211,7 +1193,7 @@ - (void)testSelectedAudioTrackDuringEntirePlayback - (void)testNonSelectedSegmentPlayback { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); return YES; }]; @@ -1231,7 +1213,7 @@ - (void)testNonSelectedSegmentPlayback }]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"pause"); + XCTAssertEqualObjects(event, @"pause"); return YES; }]; @@ -1240,7 +1222,7 @@ - (void)testNonSelectedSegmentPlayback [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); return YES; }]; @@ -1294,7 +1276,7 @@ - (void)testSelectedSegmentPlayback [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"pause"); + XCTAssertEqualObjects(event, @"pause"); XCTAssertEqualObjects(labels[@"media_position"], @"2"); return YES; }]; @@ -1304,7 +1286,7 @@ - (void)testSelectedSegmentPlayback [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"2"); return YES; }]; @@ -1396,7 +1378,7 @@ - (void)testPrepareInitialSegmentSelectionAndPlayAndReset [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_position"], @"50"); return YES; }]; @@ -1409,7 +1391,7 @@ - (void)testPrepareInitialSegmentSelectionAndPlayAndReset - (void)testSegmentSelectionAfterStartOnFullLength { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); return YES; }]; @@ -1519,7 +1501,7 @@ - (void)testSegmentSelectionWhilePlayingSelectedSegment - (void)testSegmentSelectionWhilePlayingNonSelectedSegment { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"52"); return YES; }]; @@ -1760,7 +1742,7 @@ - (void)testSelectedSegmentAtStreamEnd XCTAssertEqualObjects(self.mediaPlayerController.selectedSegment, segment); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"eof"); + XCTAssertEqualObjects(event, @"eof"); XCTAssertEqualObjects(labels[@"media_position"], @"1800"); return YES; }]; @@ -1792,7 +1774,7 @@ - (void)testResetWhilePlayingSegment }]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_position"], @"51"); return YES; }]; @@ -1805,7 +1787,7 @@ - (void)testResetWhilePlayingSegment - (void)testBlockedSegmentSelection { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); return YES; }]; @@ -1846,7 +1828,7 @@ - (void)testBlockedSegmentSelection - (void)testSeekIntoBlockedSegment { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); return YES; }]; @@ -1927,7 +1909,7 @@ - (void)testPlayStartingWithBlockedSegment - (void)testBlockedSegmentPlayback { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); return YES; }]; @@ -2038,7 +2020,7 @@ - (void)testDisableTrackingWhilePlayingSegment [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_position"], @"2"); return YES; }]; @@ -2117,7 +2099,7 @@ - (void)testDisableTrackingWhilePausedInSegment [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"pause"); + XCTAssertEqualObjects(event, @"pause"); XCTAssertEqualObjects(labels[@"media_position"], @"2"); return YES; }]; @@ -2127,7 +2109,7 @@ - (void)testDisableTrackingWhilePausedInSegment [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"stop"); + XCTAssertEqualObjects(event, @"stop"); XCTAssertEqualObjects(labels[@"media_position"], @"2"); return YES; }]; @@ -2222,7 +2204,7 @@ - (void)testEnableTrackingWhilePlaying }]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); return YES; }]; @@ -2251,7 +2233,7 @@ - (void)testEnableTrackingWhilePlayingSegment }]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"2"); return YES; }]; @@ -2434,7 +2416,7 @@ - (void)testEnableTrackingTwiceWhilePlaying - (void)testOnDemandHeartbeatPlayPausePlay { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); return YES; }]; @@ -2443,7 +2425,7 @@ - (void)testOnDemandHeartbeatPlayPausePlay [self waitForExpectationsWithTimeout:20. handler:nil]; __block NSInteger heartbeatCount = 0; - id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { ++heartbeatCount; } @@ -2460,7 +2442,7 @@ - (void)testOnDemandHeartbeatPlayPausePlay XCTAssertEqual(heartbeatCount, 2); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"pause"); + XCTAssertEqualObjects(event, @"pause"); return YES; }]; @@ -2469,7 +2451,7 @@ - (void)testOnDemandHeartbeatPlayPausePlay [self waitForExpectationsWithTimeout:20. handler:nil]; heartbeatCount = 0; - heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { ++heartbeatCount; } @@ -2486,7 +2468,7 @@ - (void)testOnDemandHeartbeatPlayPausePlay XCTAssertEqual(heartbeatCount, 0); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); return YES; }]; @@ -2495,7 +2477,7 @@ - (void)testOnDemandHeartbeatPlayPausePlay [self waitForExpectationsWithTimeout:20. handler:nil]; heartbeatCount = 0; - heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { ++heartbeatCount; } @@ -2515,7 +2497,7 @@ - (void)testOnDemandHeartbeatPlayPausePlay - (void)testLivestreamHeartbeatPlay { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_position"], @"0"); XCTAssertEqualObjects(labels[@"media_timeshift"], @"0"); return YES; @@ -2527,7 +2509,7 @@ - (void)testLivestreamHeartbeatPlay __block NSInteger heartbeatCount = 0; __block NSInteger liveHeartbeatCount = 0; - id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { XCTAssertTrue(([labels[@"media_position"] integerValue] % 3) == 0); XCTAssertEqualObjects(labels[@"media_timeshift"], @"0"); @@ -2564,7 +2546,7 @@ - (void)testHeartbeatWithInitialSegmentSelectionAndPlayback self.mediaPlayerController.segments = @[updatedSegment]; __block NSInteger heartbeatCount = 0; - id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { ++heartbeatCount; } @@ -2589,7 +2571,7 @@ - (void)testHeartbeatWithSegmentSelectionAfterStartOnFullLength [self waitForExpectationsWithTimeout:20. handler:nil]; - id eventObserver = [NSNotificationCenter.defaultCenter addObserverForPlayerEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id eventObserver = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { XCTFail(@"No event must be received when playing"); }]; @@ -2632,7 +2614,7 @@ - (void)testHeartbeatWithSegmentSelectionAfterStartOnFullLength self.mediaPlayerController.segments = @[updatedSegment]; __block NSInteger heartbeatCount = 0; - id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { ++heartbeatCount; } @@ -2649,7 +2631,7 @@ - (void)testHeartbeatWithSegmentSelectionAfterStartOnFullLength - (void)testDVRLiveHeartbeats { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); return YES; }]; @@ -2659,7 +2641,7 @@ - (void)testDVRLiveHeartbeats __block NSInteger heartbeatCount = 0; __block NSInteger liveHeartbeatCount = 0; - id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { ++heartbeatCount; } @@ -2680,7 +2662,7 @@ - (void)testDVRLiveHeartbeats - (void)testDVRTimeshiftHeartbeats { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); return YES; }]; @@ -2689,7 +2671,7 @@ - (void)testDVRTimeshiftHeartbeats [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - return [labels[@"event_id"] isEqualToString:@"play"]; + return [event isEqualToString:@"play"]; }]; CMTime seekTime = CMTimeSubtract(CMTimeRangeGetEnd(self.mediaPlayerController.timeRange), CMTimeMakeWithSeconds(60., NSEC_PER_SEC)); @@ -2699,7 +2681,7 @@ - (void)testDVRTimeshiftHeartbeats __block NSInteger heartbeatCount = 0; __block NSInteger liveHeartbeatCount = 0; - id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id heartbeatEventObserver = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { ++heartbeatCount; } @@ -2720,7 +2702,7 @@ - (void)testDVRTimeshiftHeartbeats - (void)testHeartbeatAfterDisablingTracking { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); return YES; }]; @@ -2730,7 +2712,7 @@ - (void)testHeartbeatAfterDisablingTracking __block NSInteger heartbeatCount1 = 0; __block NSInteger liveHeartbeatCount1 = 0; - id heartbeatEventObserver1 = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id heartbeatEventObserver1 = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { ++heartbeatCount1; } @@ -2751,7 +2733,7 @@ - (void)testHeartbeatAfterDisablingTracking __block NSInteger heartbeatCount2 = 0; __block NSInteger liveHeartbeatCount2 = 0; - id heartbeatEventObserver2 = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id heartbeatEventObserver2 = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { ++heartbeatCount2; } @@ -2788,7 +2770,7 @@ - (void)testHeartbeatAfterEnablingTracking __block NSInteger heartbeatCount1 = 0; __block NSInteger liveHeartbeatCount1 = 0; - id heartbeatEventObserver1 = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id heartbeatEventObserver1 = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { ++heartbeatCount1; } @@ -2806,7 +2788,7 @@ - (void)testHeartbeatAfterEnablingTracking XCTAssertEqual(liveHeartbeatCount1, 0); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); return YES; }]; @@ -2815,7 +2797,7 @@ - (void)testHeartbeatAfterEnablingTracking __block NSInteger heartbeatCount2 = 0; __block NSInteger liveHeartbeatCount2 = 0; - id heartbeatEventObserver2 = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id heartbeatEventObserver2 = [NSNotificationCenter.defaultCenter addObserverForPlayerHeartbeatNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { if ([event isEqualToString:@"pos"]) { ++heartbeatCount2; } @@ -2839,7 +2821,7 @@ - (void)testMetadata XCTAssertNil(self.mediaPlayerController.analyticsLabels); [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - return [labels[@"event_id"] isEqualToString:@"play"]; + return [event isEqualToString:@"play"]; }]; SRGAnalyticsStreamLabels *labels = [[SRGAnalyticsStreamLabels alloc] init]; @@ -2855,7 +2837,7 @@ - (void)testMetadata - (void)testAnalyticsLabelsUpdates { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - if (! [labels[@"event_id"] isEqualToString:@"play"]) { + if (! [event isEqualToString:@"play"]) { return NO; } @@ -2870,7 +2852,7 @@ - (void)testAnalyticsLabelsUpdates [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { - if (! [labels[@"event_id"] isEqualToString:@"pause"]) { + if (! [event isEqualToString:@"pause"]) { return NO; } @@ -2891,7 +2873,7 @@ - (void)testAnalyticsLabelsUpdates - (void)testAnalyticsLabelsIndirectChangeResilience { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - if (! [labels[@"event_id"] isEqualToString:@"play"]) { + if (! [event isEqualToString:@"play"]) { return NO; } @@ -2906,7 +2888,7 @@ - (void)testAnalyticsLabelsIndirectChangeResilience [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { - if (! [labels[@"event_id"] isEqualToString:@"pause"]) { + if (! [event isEqualToString:@"pause"]) { return NO; } @@ -2925,7 +2907,7 @@ - (void)testAnalyticsLabelsIndirectChangeResilience - (void)testPlaybackRateAtStart { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_playback_rate"], @"0.5"); return YES; }]; @@ -2939,7 +2921,7 @@ - (void)testPlaybackRateAtStart - (void)testPlaybackRateChange { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_playback_rate"], @"1"); return YES; }]; @@ -2949,7 +2931,7 @@ - (void)testPlaybackRateChange [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"pause"); + XCTAssertEqualObjects(event, @"pause"); XCTAssertEqualObjects(labels[@"media_playback_rate"], @"0.5"); return YES; }]; @@ -2963,7 +2945,7 @@ - (void)testPlaybackRateChange - (void)testPlaybackRateAfterRestart { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_playback_rate"], @"0.5"); return YES; }]; @@ -2977,11 +2959,11 @@ - (void)testPlaybackRateAfterRestart __block BOOL playReceived = NO; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - if ([labels[@"event_id"] isEqualToString:@"stop"]) { + if ([event isEqualToString:@"stop"]) { XCTAssertFalse(playReceived); stopReceived = YES; } - else if ([labels[@"event_id"] isEqualToString:@"play"]) { + else if ([event isEqualToString:@"play"]) { playReceived = YES; } XCTAssertEqualObjects(labels[@"media_playback_rate"], @"0.5"); @@ -2997,7 +2979,7 @@ - (void)testPlaybackRateAfterRestart - (void)testPlaybackRateAfterReplay { [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_playback_rate"], @"0.5"); return YES; }]; @@ -3009,7 +2991,7 @@ - (void)testPlaybackRateAfterReplay [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { XCTAssertEqualObjects(labels[@"media_playback_rate"], @"0.5"); - return [labels[@"event_id"] isEqualToString:@"eof"]; + return [event isEqualToString:@"eof"]; }]; CMTime seekTime = CMTimeSubtract(CMTimeRangeGetEnd(self.mediaPlayerController.timeRange), CMTimeMakeWithSeconds(2., NSEC_PER_SEC)); @@ -3018,7 +3000,7 @@ - (void)testPlaybackRateAfterReplay [self waitForExpectationsWithTimeout:20. handler:nil]; [self expectationForPlayerEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"play"); + XCTAssertEqualObjects(event, @"play"); XCTAssertEqualObjects(labels[@"media_playback_rate"], @"0.5"); return YES; }]; diff --git a/Tests/SRGAnalyticsTests/MediaTestCase.m b/Tests/SRGAnalyticsTests/MediaTestCase.m index 839dab70..b9fe3e65 100644 --- a/Tests/SRGAnalyticsTests/MediaTestCase.m +++ b/Tests/SRGAnalyticsTests/MediaTestCase.m @@ -41,12 +41,12 @@ - (void)playMediaWithURN:(NSString *)URN - (void)testTokenProtectedOnDemandVideoRSI { - [self playMediaWithURN:@"urn:rsi:video:11498675"]; + [self playMediaWithURN:@"urn:rsi:video:1874940"]; } - (void)testUnprotectedOnDemandAudioRSI { - [self playMediaWithURN:@"urn:rsi:audio:16016821"]; + [self playMediaWithURN:@"urn:rsi:video:1867394"]; } - (void)testDVRAudioLivestreamRSI diff --git a/Tests/SRGAnalyticsTests/NSNotificationCenter+Tests.h b/Tests/SRGAnalyticsTests/NSNotificationCenter+Tests.h index a88c8e01..d609cf1f 100644 --- a/Tests/SRGAnalyticsTests/NSNotificationCenter+Tests.h +++ b/Tests/SRGAnalyticsTests/NSNotificationCenter+Tests.h @@ -10,8 +10,10 @@ NS_ASSUME_NONNULL_BEGIN @interface NSNotificationCenter (Tests) -- (id)addObserverForHiddenEventNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block; +- (id)addObserverForEventNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block; +- (id)addObserverForPageViewNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block; - (id)addObserverForPlayerEventNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block; +- (id)addObserverForPlayerHeartbeatNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block; - (id)addObserverForComScoreHiddenEventNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block; - (id)addObserverForComScorePlayerEventNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block; diff --git a/Tests/SRGAnalyticsTests/NSNotificationCenter+Tests.m b/Tests/SRGAnalyticsTests/NSNotificationCenter+Tests.m index 4ad0504b..82bd4301 100644 --- a/Tests/SRGAnalyticsTests/NSNotificationCenter+Tests.m +++ b/Tests/SRGAnalyticsTests/NSNotificationCenter+Tests.m @@ -10,7 +10,7 @@ @implementation NSNotificationCenter (Tests) -- (id)addObserverForHiddenEventNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block +- (id)addObserverForEventNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block { NSString *expectedTestingIdentifier = SRGAnalyticsUnitTestingIdentifier(); return [self addObserverForName:SRGAnalyticsRequestNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull notification) { @@ -21,14 +21,19 @@ @implementation NSNotificationCenter (Tests) return; } - NSString *event = labels[@"event_id"]; - if ([event isEqualToString:@"screen"]) { + static dispatch_once_t s_onceToken; + static NSArray *s_nonEvents; + dispatch_once(&s_onceToken, ^{ + s_nonEvents = @[@"play", @"pause", @"seek", @"stop", @"eof", @"segment", @"pos", @"uptime", @"page_view"]; + }); + + NSString *event = labels[@"event_name"]; + if ([s_nonEvents containsObject:event]) { return; } // Discard app overlap measurements - NSString *name = labels[@"event_name"]; - if ([name isEqualToString:@"Installed Apps"]) { + if ([event isEqualToString:@"Installed Apps"]) { return; } @@ -36,21 +41,75 @@ @implementation NSNotificationCenter (Tests) }]; } +- (id)addObserverForPageViewNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block +{ + NSString *expectedTestingIdentifier = SRGAnalyticsUnitTestingIdentifier(); + return [self addObserverForName:SRGAnalyticsRequestNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull notification) { + NSDictionary *labels = notification.userInfo[SRGAnalyticsLabelsKey]; + + NSString *unitTestingIdentifier = labels[@"srg_test_id"]; + if (! [unitTestingIdentifier isEqualToString:expectedTestingIdentifier]) { + return; + } + + NSString *event = labels[@"event_name"]; + if (! [event isEqualToString:@"page_view"]) { + return; + } + + block(event, labels); + }]; +} + - (id)addObserverForPlayerEventNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block { - return [self addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + NSString *expectedTestingIdentifier = SRGAnalyticsUnitTestingIdentifier(); + return [self addObserverForName:SRGAnalyticsRequestNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull notification) { + NSDictionary *labels = notification.userInfo[SRGAnalyticsLabelsKey]; + + NSString *unitTestingIdentifier = labels[@"srg_test_id"]; + if (! [unitTestingIdentifier isEqualToString:expectedTestingIdentifier]) { + return; + } + static dispatch_once_t s_onceToken; static NSArray *s_playerEvents; dispatch_once(&s_onceToken, ^{ - s_playerEvents = @[@"play", @"pause", @"seek", @"stop", @"eof"]; + s_playerEvents = @[@"play", @"pause", @"seek", @"stop", @"eof", @"segment"]; }); + + NSString *event = labels[@"event_name"]; + if (! [s_playerEvents containsObject:event]) { + return; + } + + block(event, labels); + }]; +} + +- (id)addObserverForPlayerHeartbeatNotificationUsingBlock:(void (^)(NSString *event, NSDictionary *labels))block +{ + NSString *expectedTestingIdentifier = SRGAnalyticsUnitTestingIdentifier(); + return [self addObserverForName:SRGAnalyticsRequestNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull notification) { + NSDictionary *labels = notification.userInfo[SRGAnalyticsLabelsKey]; - if ([s_playerEvents containsObject:event]) { - block(event, labels); + NSString *unitTestingIdentifier = labels[@"srg_test_id"]; + if (! [unitTestingIdentifier isEqualToString:expectedTestingIdentifier]) { + return; } - else { + + static dispatch_once_t s_onceToken; + static NSArray *s_heartbeatEvents; + dispatch_once(&s_onceToken, ^{ + s_heartbeatEvents = @[@"pos", @"uptime"]; + }); + + NSString *event = labels[@"event_name"]; + if (! [s_heartbeatEvents containsObject:event]) { return; } + + block(event, labels); }]; } @@ -95,12 +154,11 @@ @implementation NSNotificationCenter (Tests) s_playerEvents = @[@"play", @"pause", @"end"]; }); - if ([s_playerEvents containsObject:event]) { - block(event, labels); - } - else { + if (! [s_playerEvents containsObject:event]) { return; } + + block(event, labels); }]; } diff --git a/Tests/SRGAnalyticsTests/TrackerSingletonSetup.h b/Tests/SRGAnalyticsTests/TrackerSingletonSetup.h new file mode 100644 index 00000000..a8264b75 --- /dev/null +++ b/Tests/SRGAnalyticsTests/TrackerSingletonSetup.h @@ -0,0 +1,13 @@ +// +// Copyright (c) SRG SSR. All rights reserved. +// +// License information is available from the LICENSE file. +// + +@import Foundation; + +NS_ASSUME_NONNULL_BEGIN + +OBJC_EXPORT void SetupTestSingletonTracker(void); + +NS_ASSUME_NONNULL_END diff --git a/Tests/SRGAnalyticsTests/TrackerSingletonSetup.m b/Tests/SRGAnalyticsTests/TrackerSingletonSetup.m index e00b543c..3095fd05 100644 --- a/Tests/SRGAnalyticsTests/TrackerSingletonSetup.m +++ b/Tests/SRGAnalyticsTests/TrackerSingletonSetup.m @@ -35,12 +35,11 @@ - (SRGAnalyticsLabels *)srg_globalLabels return dataSource; } -// The singleton can be only setup once. Do not perform in a test case setup -__attribute__((constructor)) static void SetupTestSingletonTracker(void) +void SetupTestSingletonTracker(void) { - SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierRTS - container:10 - siteName:@"rts-app-test-v"]; + SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierSRG + sourceKey:@"39ae8f94-595c-4ca4-81f7-fb7748bd3f04" + siteName:@"srg-test-analytics-apple"]; configuration.unitTesting = YES; [SRGAnalyticsTracker.sharedTracker startWithConfiguration:configuration dataSource:dataSource()]; diff --git a/Tests/SRGAnalyticsTests/TrackerTestCase.m b/Tests/SRGAnalyticsTests/TrackerTestCase.m index e89a7576..34926996 100644 --- a/Tests/SRGAnalyticsTests/TrackerTestCase.m +++ b/Tests/SRGAnalyticsTests/TrackerTestCase.m @@ -5,6 +5,7 @@ // #import "NSNotificationCenter+Tests.h" +#import "TrackerSingletonSetup.h" #import "XCTestCase+Tests.h" @interface TrackerTestCase : XCTestCase @@ -15,6 +16,11 @@ @implementation TrackerTestCase #pragma mark Setup and teardown ++ (void)setUp +{ + SetupTestSingletonTracker(); +} + - (void)setUp { SRGAnalyticsRenewUnitTestingIdentifier(); @@ -27,38 +33,47 @@ - (void)testNoHiddenAdSupportFramework XCTAssertNil(NSClassFromString(@"ASIdentifierManager")); } -- (void)testCommonLabels +- (void)testCommonLabelsForEvent { - [self expectationForHiddenEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"navigation_app_site_name"], @"rts-app-test-v"); - XCTAssertEqualObjects(labels[@"navigation_environment"], @"preprod"); + [self expectationForEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + XCTAssertEqualObjects(labels[@"navigation_app_site_name"], @"srg-test-analytics-apple"); XCTAssertEqualObjects(labels[@"consent_services"], @"service1,service2,service3"); return YES; }]; - [SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@"Hidden event"]; + [SRGAnalyticsTracker.sharedTracker trackEventWithName:@"Event"]; [self waitForExpectationsWithTimeout:20. handler:nil]; } -- (void)testHiddenEvent +- (void)testCommonLabelsForPageView +{ + [self expectationForPageViewEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + XCTAssertEqualObjects(labels[@"navigation_app_site_name"], @"srg-test-analytics-apple"); + return YES; + }]; + + [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:@"Page view" type:@"Type" levels:nil]; + + [self waitForExpectationsWithTimeout:20. handler:nil]; +} + +- (void)testEvent { - [self expectationForHiddenEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"hidden_event"); - XCTAssertEqualObjects(labels[@"event_name"], @"Hidden event"); + [self expectationForEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + XCTAssertEqualObjects(event, @"Event"); return YES; }]; - [SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@"Hidden event"]; + [SRGAnalyticsTracker.sharedTracker trackEventWithName:@"Event"]; [self waitForExpectationsWithTimeout:20. handler:nil]; } -- (void)testHiddenEventWithLabels +- (void)testEventWithLabels { - [self expectationForHiddenEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { - XCTAssertEqualObjects(labels[@"event_id"], @"hidden_event"); - XCTAssertEqualObjects(labels[@"event_name"], @"Hidden event"); + [self expectationForEventNotificationWithHandler:^BOOL(NSString *event, NSDictionary *labels) { + XCTAssertEqualObjects(event, @"Event"); XCTAssertEqualObjects(labels[@"event_type"], @"toggle"); XCTAssertEqualObjects(labels[@"event_source"], @"favorite_list"); XCTAssertEqualObjects(labels[@"event_value"], @"true"); @@ -66,30 +81,166 @@ - (void)testHiddenEventWithLabels return YES; }]; - SRGAnalyticsHiddenEventLabels *labels = [[SRGAnalyticsHiddenEventLabels alloc] init]; + SRGAnalyticsEventLabels *labels = [[SRGAnalyticsEventLabels alloc] init]; labels.type = @"toggle"; labels.source = @"favorite_list"; labels.value = @"true"; labels.customInfo = @{ @"custom_label" : @"custom_value" }; - [SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@"Hidden event" + [SRGAnalyticsTracker.sharedTracker trackEventWithName:@"Event" labels:labels]; [self waitForExpectationsWithTimeout:20. handler:nil]; } -- (void)testHiddenEventWithEmptyTitle +- (void)testEventWithEmptyTitle { - id eventObserver = [NSNotificationCenter.defaultCenter addObserverForHiddenEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + id eventObserver = [NSNotificationCenter.defaultCenter addObserverForEventNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { XCTFail(@"Events with missing title must not be sent"); }]; [self expectationForElapsedTimeInterval:5. withHandler:nil]; - [SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@""]; + [SRGAnalyticsTracker.sharedTracker trackEventWithName:@""]; [self waitForExpectationsWithTimeout:20. handler:^(NSError * _Nullable error) { [NSNotificationCenter.defaultCenter removeObserver:eventObserver]; }]; } +- (void)testPageViewEvent +{ + [self expectationForPageViewEventNotificationWithHandler:^BOOL(NSString * event, NSDictionary * labels) { + XCTAssertEqualObjects(event, @"page_view"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"page_type"], @"Type"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"page_name"], @"Page view"); // Commanders Act SDK property + XCTAssertNotNil(labels[@"accessed_after_push_notification"]); + XCTAssertFalse([labels[@"accessed_after_push_notification"] boolValue]); + XCTAssertEqualObjects(labels[@"navigation_property_type"], @"app"); + XCTAssertEqualObjects(labels[@"navigation_bu_distributer"], @"SRG"); + return YES; + }]; + + [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:@"Page view" type:@"Type" levels:nil]; + + [self waitForExpectationsWithTimeout:20. handler:nil]; +} + +- (void)testPageViewEventWithLevels +{ + [self expectationForPageViewEventNotificationWithHandler:^BOOL(NSString * event, NSDictionary * labels) { + XCTAssertEqualObjects(event, @"page_view"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"page_type"], @"Type"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"page_name"], @"Page view"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"navigation_level_1"], @"level 1"); + XCTAssertEqualObjects(labels[@"navigation_level_2"], @"level 2"); + XCTAssertEqualObjects(labels[@"navigation_level_3"], @"level 3"); + XCTAssertEqualObjects(labels[@"navigation_level_4"], @"level 4"); + XCTAssertEqualObjects(labels[@"navigation_level_5"], @"level 5"); + XCTAssertEqualObjects(labels[@"navigation_level_6"], @"level 6"); + XCTAssertEqualObjects(labels[@"navigation_level_7"], @"level 7"); + XCTAssertEqualObjects(labels[@"navigation_level_8"], @"level 8"); + XCTAssertNil(labels[@"navigation_level_9"]); + return YES; + }]; + + NSArray *levels = @[ @"level 1", @"level 2", @"level 3", @"level 4", @"level 5", @"level 6", @"level 7", @"level 8", @"level 9" ]; + + [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:@"Page view" type:@"Type" levels:levels]; + + [self waitForExpectationsWithTimeout:20. handler:nil]; +} + +- (void)testPageViewEventWithLabels +{ + [self expectationForPageViewEventNotificationWithHandler:^BOOL(NSString * event, NSDictionary * labels) { + XCTAssertEqualObjects(event, @"page_view"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"page_type"], @"Type"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"page_name"], @"Page view"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"custom_label"], @"custom_value"); + return YES; + }]; + + SRGAnalyticsPageViewLabels *labels = [[SRGAnalyticsPageViewLabels alloc] init]; + labels.customInfo = @{ @"custom_label" : @"custom_value" }; + + [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:@"Page view" type:@"Type" levels:nil labels:labels fromPushNotification:NO]; + + [self waitForExpectationsWithTimeout:20. handler:nil]; +} + +- (void)testPageViewEventWithLevelsAndLabels +{ + [self expectationForPageViewEventNotificationWithHandler:^BOOL(NSString * event, NSDictionary * labels) { + XCTAssertEqualObjects(event, @"page_view"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"page_type"], @"Type"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"page_name"], @"Page view"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"navigation_level_1"], @"level 1"); + XCTAssertEqualObjects(labels[@"navigation_level_2"], @"level 2"); + XCTAssertEqualObjects(labels[@"navigation_level_3"], @"level 3"); + XCTAssertEqualObjects(labels[@"navigation_level_4"], @"level 4"); + XCTAssertEqualObjects(labels[@"navigation_level_5"], @"level 5"); + XCTAssertEqualObjects(labels[@"navigation_level_6"], @"level 6"); + XCTAssertEqualObjects(labels[@"navigation_level_7"], @"level 7"); + XCTAssertEqualObjects(labels[@"navigation_level_8"], @"level 8"); + XCTAssertNil(labels[@"navigation_level_9"]); + XCTAssertEqualObjects(labels[@"custom_label"], @"custom_value"); + return YES; + }]; + + NSArray *levels = @[ @"level 1", @"level 2", @"level 3", @"level 4", @"level 5", @"level 6", @"level 7", @"level 8", @"level 9" ]; + + SRGAnalyticsPageViewLabels *labels = [[SRGAnalyticsPageViewLabels alloc] init]; + labels.customInfo = @{ @"custom_label" : @"custom_value" }; + + [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:@"Page view" type:@"Type" levels:levels labels:labels fromPushNotification:NO]; + + [self waitForExpectationsWithTimeout:20. handler:nil]; +} + +- (void)testPageViewEventWithEmptyTitle +{ + id eventObserver = [NSNotificationCenter.defaultCenter addObserverForPageViewNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + XCTFail(@"Page views with missing title must not be sent"); + }]; + + [self expectationForElapsedTimeInterval:5. withHandler:nil]; + + [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:@"" type:@"Type" levels:nil]; + + [self waitForExpectationsWithTimeout:20. handler:^(NSError * _Nullable error) { + [NSNotificationCenter.defaultCenter removeObserver:eventObserver]; + }]; +} + +- (void)testPageViewEventWithEmptyType +{ + id eventObserver = [NSNotificationCenter.defaultCenter addObserverForPageViewNotificationUsingBlock:^(NSString * _Nonnull event, NSDictionary * _Nonnull labels) { + XCTFail(@"Page views with missing type must not be sent"); + }]; + + [self expectationForElapsedTimeInterval:5. withHandler:nil]; + + [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:@"Title" type:@"" levels:nil]; + + [self waitForExpectationsWithTimeout:20. handler:^(NSError * _Nullable error) { + [NSNotificationCenter.defaultCenter removeObserver:eventObserver]; + }]; +} + +- (void)testPageViewEventFromPushNotification +{ + [self expectationForPageViewEventNotificationWithHandler:^BOOL(NSString * event, NSDictionary * labels) { + XCTAssertEqualObjects(event, @"page_view"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"page_type"], @"Type"); // Commanders Act SDK property + XCTAssertEqualObjects(labels[@"page_name"], @"Page view"); // Commanders Act SDK property + XCTAssertNotNil(labels[@"accessed_after_push_notification"]); + XCTAssertTrue([labels[@"accessed_after_push_notification"] boolValue]); + return YES; + }]; + + [SRGAnalyticsTracker.sharedTracker trackPageViewWithTitle:@"Page view" type:@"Type" levels:nil labels:nil fromPushNotification:YES]; + + [self waitForExpectationsWithTimeout:20. handler:nil]; +} + @end diff --git a/Tests/SRGAnalyticsTests/XCTestCase+Tests.h b/Tests/SRGAnalyticsTests/XCTestCase+Tests.h index ff8f20de..b5206445 100644 --- a/Tests/SRGAnalyticsTests/XCTestCase+Tests.h +++ b/Tests/SRGAnalyticsTests/XCTestCase+Tests.h @@ -25,12 +25,12 @@ typedef BOOL (^EventExpectationHandler)(NSString *event, NSDictionary *labels); - (XCTestExpectation *)expectationForPageViewEventNotificationWithHandler:(EventExpectationHandler)handler; /** - * Expectation for general hidden event notifications. + * Expectation for general event notifications. */ -- (XCTestExpectation *)expectationForHiddenEventNotificationWithHandler:(EventExpectationHandler)handler; +- (XCTestExpectation *)expectationForEventNotificationWithHandler:(EventExpectationHandler)handler; /** - * Expectation for playback-related hidden event notifications. + * Expectation for playback-related event notifications. */ - (XCTestExpectation *)expectationForPlayerEventNotificationWithHandler:(EventExpectationHandler)handler; diff --git a/Tests/SRGAnalyticsTests/XCTestCase+Tests.m b/Tests/SRGAnalyticsTests/XCTestCase+Tests.m index b0613a35..88969f2d 100644 --- a/Tests/SRGAnalyticsTests/XCTestCase+Tests.m +++ b/Tests/SRGAnalyticsTests/XCTestCase+Tests.m @@ -6,13 +6,6 @@ #import "XCTestCase+Tests.h" -static __attribute__((constructor)) void AnalyticsTestCaseInit(void) -{ - NSString *contentProtectionFrameworkPath = [NSBundle.mainBundle pathForResource:@"SRGContentProtection" ofType:@"framework" inDirectory:@"Frameworks"]; - NSBundle *contentProtectionFramework = [NSBundle bundleWithPath:contentProtectionFrameworkPath]; - [contentProtectionFramework loadAndReturnError:NULL]; -} - @implementation XCTestCase (Tests) #pragma mark Helpers @@ -53,17 +46,16 @@ - (XCTestExpectation *)expectationForPageViewEventNotificationWithHandler:(Event return NO; } - NSString *event = labels[@"event_id"]; - if ([event isEqualToString:@"screen"]) { - return handler(event, labels); - } - else { + NSString *event = labels[@"event_name"]; + if (! [event isEqualToString:@"page_view"]) { return NO; } + + return handler(event, labels); }]; } -- (XCTestExpectation *)expectationForHiddenEventNotificationWithHandler:(EventExpectationHandler)handler +- (XCTestExpectation *)expectationForEventNotificationWithHandler:(EventExpectationHandler)handler { NSString *expectedTestingIdentifier = SRGAnalyticsUnitTestingIdentifier(); return [self expectationForSingleNotification:SRGAnalyticsRequestNotification object:nil handler:^BOOL(NSNotification * _Nonnull notification) { @@ -74,13 +66,19 @@ - (XCTestExpectation *)expectationForHiddenEventNotificationWithHandler:(EventEx return NO; } - NSString *event = labels[@"event_id"]; - if ([event isEqualToString:@"screen"]) { + static dispatch_once_t s_onceToken; + static NSArray *s_nonEvents; + dispatch_once(&s_onceToken, ^{ + s_nonEvents = @[@"play", @"pause", @"seek", @"stop", @"eof", @"segment", @"pos", @"uptime", @"page_view"]; + }); + + NSString *event = labels[@"event_name"]; + if ([s_nonEvents containsObject:event]) { return NO; } // Discard app overlap measurements - NSString *name = labels[@"event_name"]; + NSString *name = labels[@"event_title"]; if ([name isEqualToString:@"Installed Apps"]) { return NO; } @@ -106,13 +104,12 @@ - (XCTestExpectation *)expectationForPlayerEventNotificationWithHandler:(EventEx s_playerEvents = @[@"play", @"pause", @"seek", @"stop", @"eof", @"segment"]; }); - NSString *event = labels[@"event_id"]; - if ([s_playerEvents containsObject:event]) { - return handler(event, labels); - } - else { + NSString *event = labels[@"event_name"]; + if (! [s_playerEvents containsObject:event]) { return NO; } + + return handler(event, labels); }]; } @@ -157,12 +154,11 @@ - (XCTestExpectation *)expectationForComScorePlayerEventNotificationWithHandler: s_playerEvents = @[ @"play", @"pause", @"end", @"playrt" ]; }); - if ([s_playerEvents containsObject:event]) { - return handler(event, labels); - } - else { + if (! [s_playerEvents containsObject:event]) { return NO; } + + return handler(event, labels); }]; } @@ -177,8 +173,8 @@ - (XCTestExpectation *)expectationForViewEventNotificationWithHandler:(EventExpe return NO; } - NSString *event = labels[@"event_id"]; - if (! [event isEqualToString:@"screen"]) { + NSString *event = labels[@"event_name"]; + if (! [event isEqualToString:@"page_view"]) { return NO; } diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index c74d390e..67f7d516 100644 --- a/docs/GETTING_STARTED.md +++ b/docs/GETTING_STARTED.md @@ -18,7 +18,7 @@ Before measurements can be collected, the tracker singleton responsible of all a // ... SRGAnalyticsConfiguration *configuration = [[SRGAnalyticsConfiguration alloc] initWithBusinessUnitIdentifier:SRGAnalyticsBusinessUnitIdentifierSRF - container:3 + sourceKey:@"00000000-0000-0000-0000-000000000000" siteName:@"srf-app-site"]; [SRGAnalyticsTracker.sharedTracker startWithConfiguration:configuration]; @@ -91,7 +91,7 @@ View controllers represent the units of screen interaction in an application, th ### View controller tracking -View controller measurement is an opt-in, in other words no view controller is tracked by default. For a view controller to be tracked the recommended approach is to have it conform to the `SRGAnalyticsViewTracking` protocol. This protocol requires a single method to be implemented, returning the page view title to be used for measurements. By default, once a view controller implements the `SRGAnalyticsViewTracking` protocol, it automatically generates a page view when it first appears on screen and when the application wakes up from background with the view controller displayed. +View controller measurement is an opt-in, in other words no view controller is tracked by default. For a view controller to be tracked the recommended approach is to have it conform to the `SRGAnalyticsViewTracking` protocol. This protocol requires two methods to be implemented, returning the page view title and the page view type to be used for measurements. By default, once a view controller implements the `SRGAnalyticsViewTracking` protocol, it automatically generates a page view when it first appears on screen and when the application wakes up from background with the view controller displayed. The `SRGAnalyticsViewTracking` protocol supplies optional methods to specify other custom measurement information (labels). If the required information is not available when the view controller appears you can disable automatic tracking by implementing the optional `-srg_isTrackedAutomatically` protocol method, returning `NO`. You are then responsible of calling `-trackPageView` on the view controller when the data required by the page view is available, as well as when the application returns from background. @@ -107,7 +107,7 @@ If a view can be opened from a push notification, you must implement the `-srg_o #### Remark -If your application needs to track views instead of view controllers, you can still perform tracking using the `-[SRGAnalyticsTracker trackPageViewWithTitle:levels:labels:fromPushNotification:]` method. +If your application needs to track views instead of view controllers, you can still perform tracking using the `-[SRGAnalyticsTracker trackPageViewWithTitle:type:levels:labels:fromPushNotification:]` method. ### Example @@ -130,6 +130,11 @@ and implement the methods you need to supply measurement information: return @"home"; } +- (NSString *)srg_pageViewType +{ + return @"landing_page"; +} + - (SRGAnalyticsPageViewLabels *)srg_pageViewLabels { SRGAnalyticsPageViewLabels *labels = [[SRGAnalyticsPageViewLabels alloc] init]; @@ -144,7 +149,7 @@ and implement the methods you need to supply measurement information: When the view is opened for the first time, or if the view is visible on screen when waking up the application, this information will be automatically sent. -Note that the labels might differ depending on the service they are sent to. Be sure to apply the conventions required for measurements of your application. Moreover, custom information requires the corresponding variables to be defined for TagCommander first (unlike comScore information which can be freely defined). +Note that the labels might differ depending on the service they are sent to. Be sure to apply the conventions required for measurements of your application. Moreover, custom information requires the corresponding variables to be defined for Commanders Act first (unlike comScore information which can be freely defined). ## Measuring page views (SwiftUI) @@ -155,7 +160,7 @@ struct ContentView: View { var body: some View { VStack { // ... - }.tracked(withTitle: "home") + }.tracked(withTitle: "home", type: "landing_page") } } ``` @@ -216,10 +221,10 @@ In some special cases like CarPlay, though, your application might display a sec ## Measuring application functionalities -To measure any kind of application functionality, you typically use hidden events. Those can be emitted by calling the corresponding methods on the tracker singleton itself. For example, you could send the following event when the user taps on a player full-screen button within your application: +To measure any kind of application functionality, you typically use events. Those can be emitted by calling the corresponding methods on the tracker singleton itself. For example, you could send the following event when the user taps on a player full-screen button within your application: ```objective-c -[SRGAnalyticsTracker.sharedTracker trackHiddenEventWithName:@"full-screen"]; +[SRGAnalyticsTracker.sharedTracker trackEventWithName:@"full-screen"]; ``` Custom labels can also be used to send any additional measurement information you could need. diff --git a/docs/README.md b/docs/README.md index 955ffcaa..a44f6770 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,12 +6,12 @@ The SRG Analytics library makes it easy to add usage tracking information to your iOS and tvOS applications, following the SRG SSR standards. -Measurements are based on events emitted by the application and sent to TagCommander (for internal analytics purposes) as well as Mediapulse (for official audience measurements, via comScore). +Measurements are based on events emitted by the application and sent to Commanders Act (for internal analytics purposes) as well as Mediapulse (for official audience measurements, via comScore). The SRG Analytics library supports three kinds of measurements: * View events: Appearance of views (page views), which makes it possible to track which content is seen by users. - * Hidden events: Custom events which can be used for measurement of application functionalities. + * Events: Custom events which can be used for measurement of application functionalities. * Stream playback events: Audio and video consumption measurements for application using our [SRG Media Player](https://github.com/SRGSSR/srgmediaplayer-apple). Additional playback information (title, duration, etc.) must be supplied externally. For application using our [SRG Data Provider](https://github.com/SRGSSR/srgdataprovider-apple) library, though, this process is entirely automated. * Integration with our [SRG Identity](https://github.com/SRGSSR/srgidentity-apple) library. @@ -31,7 +31,7 @@ The library must be integrated using [Swift Package Manager](https://swift.org/p The library is made of serveral smaller libraries. Which ones your project must link against depends on your needs: -- If you only need basic view and hidden event tracking, just link against `SRGAnalytics`. If you need to track SwiftUI views link against `SRGAnalyticsSwiftUI` as well. +- If you only need basic view and event tracking, just link against `SRGAnalytics`. If you need to track SwiftUI views link against `SRGAnalyticsSwiftUI` as well. - If you need [SRG Media Player](https://github.com/SRGSSR/srgmediaplayer-apple) media playback tracking, also link against `SRGAnalyticsMediaPlayer`. - If you need SRG standard media playback tracking with associated media metadata retrieved by [SRG Data Provider](https://github.com/SRGSSR/srgdataprovider-apple), also link against `SRGAnalyticsDataProvider`. This library provides several playback helpers you should use to ensure that context information is complete when playing a media. - If you are using [SRG Identity](https://github.com/SRGSSR/srgidentity-apple) in your project, also link against `SRGAnalyticsIdentity`.