From fa01420380dacc969ee192f78ed0a586db99f513 Mon Sep 17 00:00:00 2001 From: runner Date: Thu, 28 Sep 2023 00:55:29 +0000 Subject: [PATCH] Release 4.9.0 --- .../Ads/Api/UADSApiGMAScar/UADSApiGMAScar.m | 28 ++- .../UADSBannerLoadModuleDelegateWrapper.m | 20 +- .../Private/Banners/Api/UADSApiBanner.m | 63 +++++ .../Banners/GMAScar/UADSGADBannerWrapper.h | 19 ++ .../Banners/GMAScar/UADSGADBannerWrapper.m | 69 ++++++ .../UADSConfigurationCRUDBase.m | 27 --- .../UADSConfigurationExperiments.h | 23 +- .../UADSConfigurationExperiments.m | 4 + ...eaderBiddingTokenReaderSCARSignalsConfig.h | 1 - ...eaderBiddingTokenReaderSCARSignalsConfig.m | 5 - ...SHeaderBiddingTokenReaderWithSCARSignals.m | 4 +- ...TokenReaderWithSCARSignalsHybridStrategy.h | 10 - ...TokenReaderWithSCARSignalsHybridStrategy.m | 49 ---- ...ngTokenReaderWithSCARSignalsLazyStrategy.h | 10 - ...ngTokenReaderWithSCARSignalsLazyStrategy.m | 26 --- .../UADSSCARHBConfigurationReader.h | 4 - .../UADSSCARHBStrategyType.h | 11 - ...CARHeaderBiddingFetchSendStrategyFactory.h | 12 - ...CARHeaderBiddingFetchSendStrategyFactory.m | 27 --- .../UADSSCARHeaderBiddingStrategyFactory.h | 16 -- .../UADSSCARRawSignalsReader.m | 28 ++- .../UADSSCARSignalIdentifiers.h | 2 + .../UADSSCARWebRequestSignalSender.m | 3 +- .../UADSHeaderBiddingTokenReaderBase.m | 4 +- .../Core/Properties/USRVSdkProperties.m | 4 +- .../Metrics/Events/Load/UADSLoadMetric.m | 4 +- .../Banner/GMABannerAdLoader.h | 12 + .../Banner/GMABannerAdLoader.m | 46 ++++ .../GMAAdLoaderStrategy/GMAAdLoaderStrategy.h | 2 +- .../GMAAdLoaderStrategy/GMAAdLoaderStrategy.m | 24 +- .../GMAAdMetaData/GMAAdMetaData.h | 6 + .../GMAScar/GMAAdLoaders/GMALoaderBase.h | 6 +- .../GMAScar/GMAAdLoaders/GMALoaderBase.m | 4 + .../GMABannerViewDelegateProxy.h | 32 +++ .../GMABannerViewDelegateProxy.m | 58 +++++ .../GMAScar/GMABridges/GADAdSizeBridge.h | 7 + .../GMAScar/GMABridges/GADBannerViewBridge.h | 20 ++ .../GMAScar/GMABridges/GADBannerViewBridge.m | 51 +++++ .../GMAScar/GMABridges/GADQueryInfoBridge.h | 1 + .../GMADelegatesFactory/GMADelegatesFactory.h | 4 +- .../GMADelegatesFactory/GMADelegatesFactory.m | 7 + .../GMASCARSignalsReader.h | 6 +- .../GMASCARSignalsReader.m | 59 ++--- .../GMASCARSignalsReaderDecorator.h | 6 +- .../GMASCARSignalsReaderDecorator.m | 9 +- .../GMAWebViewEvent/GMABannerWebViewEvent.h | 19 ++ .../GMAWebViewEvent/GMABannerWebViewEvent.m | 55 +++++ .../GMAScar/GMAWebViewEvent/GMAWebViewEvent.h | 2 + SourceCode/Private/GMAScar/UADSGMAScar.h | 9 +- SourceCode/Private/GMAScar/UADSGMAScar.m | 17 +- .../GMAScar/UADSScarSignalParameters.h | 16 ++ .../GMAScar/UADSScarSignalParameters.m | 20 ++ .../NSEnumWrapper/GADAdSizeStructBox.h | 8 + .../NSEnumWrapper/GADAdSizeStructBox.m | 13 ++ .../NSEnumWrapper/NSPrimitivesBox.h | 2 + .../NSEnumWrapper/NSPrimitivesBox.m | 8 + .../NSInvocation/NSInvocation+Convenience.m | 9 +- .../UIView/UIView+ParentViewController.h | 7 + .../UIView/UIView+ParentViewController.m | 14 ++ .../Tools/Categories/UIView/UIView+Subview.h | 11 + .../Tools/Categories/UIView/UIView+Subview.m | 40 ++++ SourceCode/Public/Banners/UADSBannerView.m | 1 + .../Token/HeaderBiddingTokenReader.swift | 4 +- .../GMAAdLoaderStrategyTests.m | 32 ++- .../Mocks/GMASCARSignalServiceMock.h | 15 ++ .../Mocks/GMASCARSignalServiceMock.m | 26 +++ ...UADSSCARHeaderBiddingStrategyFactoryMock.h | 10 - ...UADSSCARHeaderBiddingStrategyFactoryMock.m | 9 - ...nReaderWithSCARSignalsEagerStrategyTests.m | 3 +- ...ReaderWithSCARSignalsHybridStrategyTests.m | 140 ------------ ...enReaderWithSCARSignalsLazyStrategyTests.m | 134 ----------- ...aderBiddingFetchSendStrategyFactoryTests.m | 133 ----------- .../UADSSCARWebRequestSignalSenderTests.m | 58 ++++- .../UADSSCARRawSignalsReaderTests.m | 80 +++++++ ...ADSAsyncTokenWithPrivacyIntegrationTests.m | 2 +- ...ADSHeaderBiddingTokenIntegrationTestCase.m | 4 +- .../GMABannerViewDelegateProxyTests.m | 93 ++++++++ .../GMABaseAdDelegateProxyTests.h | 19 ++ .../GMABaseAdDelegateProxyTests.m | 65 ++++++ .../GMAInterstitialAdDelegateProxyTests.m | 65 +----- .../GMARewardedAdDelegateProxyTests.m | 56 +---- .../GMASCARSignalsReaderDecoratorTests.m | 15 +- .../Mocks/GMASCARSignalsReaderMock.m | 10 +- .../GMAScarSignalsReaderTests.m | 215 +++++++++--------- .../Mocks/GMASignalServiceMock.m | 19 +- .../Mocks/GMAQueryInfoReaderMock.m | 13 ++ .../UADSGMAScarNoGMATests/UADSNoGMAApiTests.m | 5 +- .../Mocks/UADSConfigurationReaderMock.h | 1 - .../Mocks/UADSConfigurationReaderMock.m | 7 - .../Network/Responses/ConfigResponseMock.json | 3 - .../HeaderBiddingTokenReaderTestsCase.swift | 7 - .../UADTestsTools/GMATestCommonConstants.h | 1 + .../GMATestsHelper/GMATestsHelper.h | 8 +- .../GMATestsHelper/GMATestsHelper.m | 12 +- .../UADSGMAScar+Sync/UADSGMAScar+SyncGetter.m | 11 +- UnityAds.podspec | 4 +- 96 files changed, 1340 insertions(+), 1023 deletions(-) create mode 100644 SourceCode/Private/Banners/GMAScar/UADSGADBannerWrapper.h create mode 100644 SourceCode/Private/Banners/GMAScar/UADSGADBannerWrapper.m delete mode 100644 SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.h delete mode 100644 SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.m delete mode 100644 SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.h delete mode 100644 SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.m delete mode 100644 SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHBStrategyType.h delete mode 100644 SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingFetchSendStrategyFactory.h delete mode 100644 SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingFetchSendStrategyFactory.m delete mode 100644 SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingStrategyFactory.h create mode 100644 SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/Banner/GMABannerAdLoader.h create mode 100644 SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/Banner/GMABannerAdLoader.m create mode 100644 SourceCode/Private/GMAScar/GMABridges/BannerDelegateProxy/GMABannerViewDelegateProxy.h create mode 100644 SourceCode/Private/GMAScar/GMABridges/BannerDelegateProxy/GMABannerViewDelegateProxy.m create mode 100644 SourceCode/Private/GMAScar/GMABridges/GADAdSizeBridge.h create mode 100644 SourceCode/Private/GMAScar/GMABridges/GADBannerViewBridge.h create mode 100644 SourceCode/Private/GMAScar/GMABridges/GADBannerViewBridge.m create mode 100644 SourceCode/Private/GMAScar/GMAWebViewEvent/GMABannerWebViewEvent.h create mode 100644 SourceCode/Private/GMAScar/GMAWebViewEvent/GMABannerWebViewEvent.m create mode 100644 SourceCode/Private/GMAScar/UADSScarSignalParameters.h create mode 100644 SourceCode/Private/GMAScar/UADSScarSignalParameters.m create mode 100644 SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/GADAdSizeStructBox.h create mode 100644 SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/GADAdSizeStructBox.m create mode 100644 SourceCode/Private/Tools/Categories/UIView/UIView+ParentViewController.h create mode 100644 SourceCode/Private/Tools/Categories/UIView/UIView+ParentViewController.m create mode 100644 SourceCode/Private/Tools/Categories/UIView/UIView+Subview.h create mode 100644 SourceCode/Private/Tools/Categories/UIView/UIView+Subview.m create mode 100644 Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/GMASCARSignalServiceMock.h create mode 100644 Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/GMASCARSignalServiceMock.m delete mode 100644 Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/UADSSCARHeaderBiddingStrategyFactoryMock.h delete mode 100644 Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/UADSSCARHeaderBiddingStrategyFactoryMock.m delete mode 100644 Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategyTests.m delete mode 100644 Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategyTests.m delete mode 100644 Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSSCARHeaderBiddingFetchSendStrategyFactoryTests.m create mode 100644 Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/UADSSCARRawSignalsReaderTests.m create mode 100644 Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABannerViewDelegateProxy/GMABannerViewDelegateProxyTests.m create mode 100644 Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABaseAdDelegateProxyTests.h create mode 100644 Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABaseAdDelegateProxyTests.m rename Tests/UnityAdsTests/GMAInfo/{ => DelegateProxyTests}/GMAInterstitialAdDelegateProxy/GMAInterstitialAdDelegateProxyTests.m (85%) rename Tests/UnityAdsTests/GMAInfo/{ => DelegateProxyTests}/GMARewardedAdDelegateProxy/GMARewardedAdDelegateProxyTests.m (85%) diff --git a/SourceCode/Private/Ads/Api/UADSApiGMAScar/UADSApiGMAScar.m b/SourceCode/Private/Ads/Api/UADSApiGMAScar/UADSApiGMAScar.m index b8ef2380..adaf8b7f 100644 --- a/SourceCode/Private/Ads/Api/UADSApiGMAScar/UADSApiGMAScar.m +++ b/SourceCode/Private/Ads/Api/UADSApiGMAScar/UADSApiGMAScar.m @@ -35,9 +35,9 @@ + (void)WebViewExposed_isAvailable: (USRVWebViewCallback *)callback { [callback invoke: [NSNumber numberWithBool: present], nil]; } -+ (void)WebViewExposed_getSCARSignals: (NSArray *)interstitialPlacements - rewardedPlacements: (NSArray *)rewardedPlacements - callback: (USRVWebViewCallback *)callback { ++(void)WebViewExposed_getSCARSignal: (NSString *)placementId + adFormat: (NSString *)adFormat + callback: (USRVWebViewCallback *)callback { id success = ^(NSString *_Nullable signals) { GMAWebViewEvent *event = [GMAWebViewEvent newSignalsEvent: signals]; [self sendEvent: event]; @@ -47,14 +47,10 @@ + (void)WebViewExposed_getSCARSignals: (NSArray *)interstitialPlacements [self.errorHandler catchError: error]; }; - UADSGMAEncodedSignalsCompletion *completion = [UADSGMAEncodedSignalsCompletion newWithSuccess: success - andError: error]; - - [self.facade getSCARSignalsUsingInterstitialList: interstitialPlacements - andRewardedList: rewardedPlacements - completion: completion]; - - [callback invoke: nil]; + UADSGMAEncodedSignalsCompletion *completion = [UADSGMAEncodedSignalsCompletion newWithSuccess: success andError: error]; + UADSScarSignalParameters *params = [[UADSScarSignalParameters alloc] initWithPlacementId:placementId adFormat: [self getInfoAdTypeFrom:adFormat]]; + [self.facade getSCARSignals: @[ params ] + completion: completion]; } + (void)WebViewExposed_load: (NSString *)placementId @@ -135,4 +131,14 @@ + (void)sendAvailabilityMetrics { } } ++ (GADQueryInfoAdType)getInfoAdTypeFrom: (NSString *)adFormat { + if ([adFormat isEqualToString: @"interstitial"]) { + return GADQueryInfoAdTypeInterstitial; + } + if ([adFormat isEqualToString: @"rewarded"]) { + return GADQueryInfoAdTypeRewarded; + } + return GADQueryInfoAdTypeBanner; +} + @end diff --git a/SourceCode/Private/Ads/Load/UADSBannerLoadModule/UADSBannerLoadModuleDelegateWrapper.m b/SourceCode/Private/Ads/Load/UADSBannerLoadModule/UADSBannerLoadModuleDelegateWrapper.m index 94c50584..9a9ab66d 100644 --- a/SourceCode/Private/Ads/Load/UADSBannerLoadModule/UADSBannerLoadModuleDelegateWrapper.m +++ b/SourceCode/Private/Ads/Load/UADSBannerLoadModule/UADSBannerLoadModuleDelegateWrapper.m @@ -25,31 +25,41 @@ - (void)didFailWithError:(UADSInternalError * _Nonnull)error forPlacementID:(NSS - (void)bannerViewDidLoad: (UADSBannerView *)bannerView { dispatch_on_main( ^{ - [self.decorated bannerViewDidLoad: self.bannerView]; + if ([self.decorated respondsToSelector: @selector(bannerViewDidLoad:)]) { + [self.decorated bannerViewDidLoad: self.bannerView]; + } }); } - (void)bannerViewDidShow:(UADSBannerView *)bannerView { dispatch_on_main( ^{ - [self.decorated bannerViewDidShow: self.bannerView]; + if ([self.decorated respondsToSelector: @selector(bannerViewDidShow:)]) { + [self.decorated bannerViewDidShow: self.bannerView]; + } }); } - (void)bannerViewDidClick: (UADSBannerView *)bannerView { dispatch_on_main( ^{ - [self.decorated bannerViewDidClick: self.bannerView]; + if ([self.decorated respondsToSelector: @selector(bannerViewDidClick:)]) { + [self.decorated bannerViewDidClick: self.bannerView]; + } }); } - (void)bannerViewDidLeaveApplication: (UADSBannerView *)bannerView { dispatch_on_main( ^{ - [self.decorated bannerViewDidLeaveApplication: self.bannerView]; + if ([self.decorated respondsToSelector: @selector(bannerViewDidLeaveApplication:)]) { + [self.decorated bannerViewDidLeaveApplication: self.bannerView]; + } }); } - (void)bannerViewDidError: (UADSBannerView *)bannerView error: (UADSBannerError *)error { dispatch_on_main( ^{ - [self.decorated bannerViewDidError: self.bannerView error: error]; + if ([self.decorated respondsToSelector: @selector(bannerViewDidError:error:)]) { + [self.decorated bannerViewDidError: self.bannerView error: error]; + } }); } diff --git a/SourceCode/Private/Banners/Api/UADSApiBanner.m b/SourceCode/Private/Banners/Api/UADSApiBanner.m index 3c770502..576e3934 100644 --- a/SourceCode/Private/Banners/Api/UADSApiBanner.m +++ b/SourceCode/Private/Banners/Api/UADSApiBanner.m @@ -7,6 +7,12 @@ #import "UADSBannerRefreshInfo.h" #import "UADSBannerWebPlayerContainerType.h" #import "UADSBannerLoadModule.h" +#import "UADSGMAScar.h" +#import "GADBannerViewBridge.h" +#import "GMABannerWebViewEvent.h" +#import "UADSGADBannerWrapper.h" +#import "UIViewController+TopController.h" +#import "UADSTools.h" @implementation UADSApiBanner @@ -70,4 +76,61 @@ + (void)WebViewExposed_setRefreshRate: (NSString *)placementId refreshRate: (NSN [callback invoke: nil]; } ++ (void)WebViewExposed_loadScar: (NSString *)bannerAd + placementId: (NSString *)placementId + queryId: (NSString *)queryId + adUnitId: (NSString *)adUnitId + adString: (NSString *)adString + width: (NSNumber *)width + height: (NSNumber *)height + callback: (USRVWebViewCallback *)callback { + + UADSBannerView *bannerView = [[UADSBannerLoadModule sharedInstance] bannerViewWithID:bannerAd]; + if (!bannerView) { + return; + } + + CGSize bannerSize = CGSizeMake(width.floatValue, height.floatValue); + GMAAdMetaData *data = [GMAAdMetaData new]; + data.type = GADQueryInfoAdTypeBanner; + data.placementID = placementId; + data.adString = adString; + data.adUnitID = adUnitId; + data.queryID = queryId; + data.bannerAdId = bannerAd; + data.bannerSize = bannerSize; + + UADSGADBannerWrapper *wrapper = [UADSGADBannerWrapper newWithMeta: data + eventSender: self.eventSender + gmaScar: UADSGMAScar.sharedInstance]; + + data.beforeLoad = ^(GADBaseAd *_Nullable ad) { + wrapper.gadBanner = (GADBannerViewBridge *)ad; + dispatch_on_main_sync(^{ + [wrapper addToBannerView:bannerView withSize:bannerSize]; + }); + }; + + id successHandler = ^(GADBaseAd *_Nullable ad) { + [self.eventSender sendEvent: [GMABannerWebViewEvent newBannerLoadedWithMeta: data]]; + }; + + id errorHandler = ^(id _Nonnull error) { + [self.eventSender sendEvent: [GMABannerWebViewEvent newBannerLoadFailedWithMeta: data]]; + dispatch_on_main_sync(^{ + [wrapper removeFromSuperview]; // remove from UADSBannerView + }); + }; + + UADSLoadAdCompletion *completion = [UADSLoadAdCompletion newWithSuccess: successHandler + andError: errorHandler]; + + [[UADSGMAScar sharedInstance] loadAdUsingMetaData:data andCompletion:completion]; + [callback invoke: nil]; +} + ++ (id)eventSender { + return [UADSWebViewEventSenderBase new]; +} + @end diff --git a/SourceCode/Private/Banners/GMAScar/UADSGADBannerWrapper.h b/SourceCode/Private/Banners/GMAScar/UADSGADBannerWrapper.h new file mode 100644 index 00000000..c6e57963 --- /dev/null +++ b/SourceCode/Private/Banners/GMAScar/UADSGADBannerWrapper.h @@ -0,0 +1,19 @@ +#import +#import "UADSBannerView.h" +#import "GADBannerViewBridge.h" +#import "UADSWebViewEventSender.h" +#import "GMAAdMetaData.h" +#import "UADSGMAScar.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface UADSGADBannerWrapper : UIView +@property (nonatomic, strong) GADBannerViewBridge *gadBanner; + ++ (instancetype)newWithMeta: (GMAAdMetaData *)meta eventSender: (id)eventSender gmaScar:(UADSGMAScar*)gmaScar; +- (void)addToBannerView: (UADSBannerView *)bannerView withSize: (CGSize)size; +- (void)updateGADBannerRootViewController; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/Banners/GMAScar/UADSGADBannerWrapper.m b/SourceCode/Private/Banners/GMAScar/UADSGADBannerWrapper.m new file mode 100644 index 00000000..a2540d91 --- /dev/null +++ b/SourceCode/Private/Banners/GMAScar/UADSGADBannerWrapper.m @@ -0,0 +1,69 @@ +#import +#import "UIView+Subview.h" +#import "UADSGADBannerWrapper.h" +#import "UIViewController+TopController.h" +#import "UIView+ParentViewController.h" +#import "GMABannerWebViewEvent.h" + +@interface UADSGADBannerWrapper() +@property (nonatomic, strong) id eventSender; +@property (nonatomic, strong) GMAAdMetaData *meta; +@property (nonatomic, strong) UADSGMAScar *gmaScar; +@end + +@implementation UADSGADBannerWrapper + ++ (instancetype)newWithMeta: (GMAAdMetaData *)meta eventSender: (id)eventSender gmaScar:(UADSGMAScar*)gmaScar { + UADSGADBannerWrapper *wrapper = [UADSGADBannerWrapper new]; + wrapper.meta = meta; + wrapper.eventSender = eventSender; + wrapper.gmaScar = gmaScar; + return wrapper; +} + +- (void)addToBannerView: (UADSBannerView *)bannerView withSize: (CGSize)size { + [bannerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + [bannerView addSubview:self withSize:size]; + + UIView *gBannerView = self.gadBannerView; + [self addSubview:gBannerView withSize:size]; + + [self updateGADBannerRootViewController]; +} + +- (void)updateGADBannerRootViewController { + [self.gadBanner setRootViewController: self.bannerRootViewController]; +} + +- (UIViewController *)bannerRootViewController { + return [self parentViewController] ?: [UIViewController uads_getTopController]; +} + +- (UIView *)gadBannerView { + return (UIView *)self.gadBanner.proxyObject; +} + +- (void)willMoveToSuperview:(UIView *)newSuperview { + if (newSuperview == nil) { + [self.gmaScar removeAdForPlacement: self.meta.placementID]; + } +} + +- (void)willMoveToWindow:(UIWindow *)newWindow { + if (newWindow) { + [self updateGADBannerRootViewController]; + [self sendAttachedEvent]; + } else { + [self sendDettachedEvent]; + } +} + +- (void)sendAttachedEvent { + [self.eventSender sendEvent:[GMABannerWebViewEvent newBannerAttachedWithMeta: self.meta]]; +} + +- (void)sendDettachedEvent { + [self.eventSender sendEvent:[GMABannerWebViewEvent newBannerDetachedWithMeta: self.meta]]; +} + +@end diff --git a/SourceCode/Private/Core/Configuration/ConfigurationStorage/UADSConfigurationCRUDBase.m b/SourceCode/Private/Core/Configuration/ConfigurationStorage/UADSConfigurationCRUDBase.m index 6753b502..34a2a971 100644 --- a/SourceCode/Private/Core/Configuration/ConfigurationStorage/UADSConfigurationCRUDBase.m +++ b/SourceCode/Private/Core/Configuration/ConfigurationStorage/UADSConfigurationCRUDBase.m @@ -165,31 +165,4 @@ - (NSString *)getCurrentScarHBURL { return scarURL ?: kDefaultScarURL; } -- (UADSSCARHBStrategyType) selectedSCARHBStrategyType { - USRVConfiguration *config = [ self getCurrentConfiguration]; - if (!config.experiments.json) { - return UADSSCARHeaderBiddingStrategyTypeDisabled; - } - NSDictionary* strategyDictionary = config.experiments.json[@"scar_bm"]; - if (![strategyDictionary isKindOfClass:[NSDictionary class]]) { - return UADSSCARHeaderBiddingStrategyTypeDisabled; - } - NSString* strategyValue = strategyDictionary[@"value"]; - return [self selectedStrategyTypeForString:strategyValue]; -} - -- (UADSSCARHBStrategyType) selectedStrategyTypeForString:(NSString*)stringValue { - if ([stringValue isEqualToString:@"eag"]) { - return UADSSCARHeaderBiddingStrategyTypeEager; - } - if ([stringValue isEqualToString:@"laz"]) { - return UADSSCARHeaderBiddingStrategyTypeLazy; - } - if ([stringValue isEqualToString:@"hyb"]) { - return UADSSCARHeaderBiddingStrategyTypeHybrid; - } - return UADSSCARHeaderBiddingStrategyTypeDisabled; -} - - @end diff --git a/SourceCode/Private/Core/Configuration/SDKConfigurationReader/UADSConfigurationExperiments.h b/SourceCode/Private/Core/Configuration/SDKConfigurationReader/UADSConfigurationExperiments.h index 0162840a..d8f72155 100644 --- a/SourceCode/Private/Core/Configuration/SDKConfigurationReader/UADSConfigurationExperiments.h +++ b/SourceCode/Private/Core/Configuration/SDKConfigurationReader/UADSConfigurationExperiments.h @@ -6,17 +6,18 @@ NS_ASSUME_NONNULL_BEGIN @property (readonly) NSDictionary *json; + (instancetype)newWithJSON: (NSDictionary *)json; -- (BOOL) isSwiftDownloadEnabled; -- (BOOL) isSwiftNativeRequestsEnabled; -- (BOOL) isSwiftWebViewRequestsEnabled; -- (BOOL) isSwiftInitFlowEnabled; -- (BOOL) isUseNewTasksEnabled; -- (BOOL) isParallelExecutionEnabled; -- (BOOL) isPrivacyWaitEnabled; -- (BOOL) isNativeWebViewCacheEnabled; -- (BOOL) isWebAdAssetCacheEnabled; -- (BOOL) isSwiftTokenEnabled; -- (BOOL) isOrientationSafeguardEnabled; +- (BOOL) isSwiftDownloadEnabled; +- (BOOL) isSwiftNativeRequestsEnabled; +- (BOOL) isSwiftWebViewRequestsEnabled; +- (BOOL) isSwiftInitFlowEnabled; +- (BOOL) isUseNewTasksEnabled; +- (BOOL) isParallelExecutionEnabled; +- (BOOL) isPrivacyWaitEnabled; +- (BOOL) isNativeWebViewCacheEnabled; +- (BOOL) isWebAdAssetCacheEnabled; +- (BOOL) isSwiftTokenEnabled; +- (BOOL) isOrientationSafeguardEnabled; +- (BOOL) isScarBannerSignalsEnabled; - (NSDictionary *)nextSessionFlags; - (NSDictionary *)currentSessionFlags; diff --git a/SourceCode/Private/Core/Configuration/SDKConfigurationReader/UADSConfigurationExperiments.m b/SourceCode/Private/Core/Configuration/SDKConfigurationReader/UADSConfigurationExperiments.m index 994ec96f..98ae2c4e 100644 --- a/SourceCode/Private/Core/Configuration/SDKConfigurationReader/UADSConfigurationExperiments.m +++ b/SourceCode/Private/Core/Configuration/SDKConfigurationReader/UADSConfigurationExperiments.m @@ -81,6 +81,10 @@ - (BOOL)isOrientationSafeguardEnabled { return [self isExperimentEnabledWithKey: @"osg"]; } +- (BOOL) isScarBannerSignalsEnabled { + return [self isExperimentEnabledWithKey: @"scar_bn"]; +} + - (NSDictionary *)nextSessionFlags { return [self flattenFlagsWith:^BOOL (id key) { return [self isExperimentForNextSession: key]; diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderSCARSignalsConfig.h b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderSCARSignalsConfig.h index 54a8a842..36c8d293 100644 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderSCARSignalsConfig.h +++ b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderSCARSignalsConfig.h @@ -14,7 +14,6 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong) id requestFactory; @property (nonatomic, strong) id signalService; @property (nonatomic, weak) id compressor; -@property (nonatomic, strong) id strategyFactory; @property (nonatomic, strong) id idfiReader; @property (nonatomic, strong) id configurationReader; @property (nonatomic, strong) id metricsSender; diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderSCARSignalsConfig.m b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderSCARSignalsConfig.m index 8a3dba8f..455198b2 100644 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderSCARSignalsConfig.m +++ b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderSCARSignalsConfig.m @@ -1,14 +1,9 @@ #import "UADSHeaderBiddingTokenReaderSCARSignalsConfig.h" -#import "UADSSCARHeaderBiddingFetchSendStrategyFactory.h" -#import "UADSSCARHeaderBiddingStrategyFactory.h" @implementation UADSHeaderBiddingTokenReaderSCARSignalsConfig -(instancetype) init { SUPER_INIT; - UADSSCARHeaderBiddingFetchSendStrategyFactory* strategyFactory = [UADSSCARHeaderBiddingFetchSendStrategyFactory new]; - strategyFactory.config = self; - self.strategyFactory = strategyFactory; self.idfiReader = [UADSDeviceIDFIReaderBase new]; self.timestampReader = [UADSCurrentTimestampBase new]; diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignals.m b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignals.m index 311e3f31..649d2f33 100644 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignals.m +++ b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignals.m @@ -1,6 +1,6 @@ #import "UADSHeaderBiddingTokenReaderWithSCARSignals.h" #import "UADSServiceProvider.h" -#import "UADSSCARHeaderBiddingFetchSendStrategyFactory.h" +#import "UADSHeaderBiddingTokenReaderWithSCARSignalsEagerStrategy.h" @interface UADSHeaderBiddingTokenReaderWithSCARSignals () @property (nonatomic, strong) id original; @@ -18,7 +18,7 @@ + (instancetype)decorateOriginal: (id)strategy { - return [self.config.strategyFactory strategyWithOriginal:self.original]; + return [UADSHeaderBiddingTokenReaderWithSCARSignalsEagerStrategy decorateOriginal:self.original config:self.config]; } - (void)getToken:(nonnull UADSHeaderBiddingTokenCompletion)completion { diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.h b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.h deleted file mode 100644 index da501c37..00000000 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.h +++ /dev/null @@ -1,10 +0,0 @@ -#import -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsBaseStrategy.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy : UADSHeaderBiddingTokenReaderWithSCARSignalsBaseStrategy - -@end - -NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.m b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.m deleted file mode 100644 index bc1dd8f3..00000000 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.m +++ /dev/null @@ -1,49 +0,0 @@ -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.h" -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsBaseStrategy+Internal.h" - -@implementation UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy { - dispatch_queue_t queue; -} - -- (instancetype)init { - SUPER_INIT; - queue = dispatch_queue_create("com.unity3d.scarhbhybrid.module", DISPATCH_QUEUE_SERIAL); - return self; -} - -- (void)getToken:(UADSHeaderBiddingTokenCompletion)completion { - __block UADSSCARSignals *_Nullable blockSignals; - __block UADSHeaderBiddingToken *_Nullable blockToken; - - dispatch_group_t group = dispatch_group_create(); - //To avoid returning too quickly - dispatch_group_enter(group); - dispatch_group_enter(group); - - dispatch_group_notify(group, queue, ^{ - if (blockToken) { - [self.scarSignalSender sendSCARSignalsWithUUIDString:blockToken.uuidString signals:blockSignals isAsync:true]; - } - }); - - - id signalCompletion = ^(UADSSCARSignals *_Nullable signals) { - blockSignals = signals; - dispatch_group_leave(group); - }; - - [self.scarSignalReader requestSCARSignalsWithIsAsync:true completion:signalCompletion]; - - UADSHeaderBiddingTokenCompletion injectedCompletion = ^(UADSHeaderBiddingToken *_Nullable token) { - token = [self setUUIDString:token.uuidString ifRemoteToken:token]; - if (token.isValid) { - blockToken = token; - } - dispatch_group_leave(group); - completion(token); - }; - - [super getToken:injectedCompletion]; -} - -@end diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.h b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.h deleted file mode 100644 index b7b95cca..00000000 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.h +++ /dev/null @@ -1,10 +0,0 @@ -#import -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsBaseStrategy.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy : UADSHeaderBiddingTokenReaderWithSCARSignalsBaseStrategy - -@end - -NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.m b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.m deleted file mode 100644 index 3ef72b8d..00000000 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.m +++ /dev/null @@ -1,26 +0,0 @@ -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.h" -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsBaseStrategy+Internal.h" - -@implementation UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy - - -- (void)getToken:(UADSHeaderBiddingTokenCompletion)completion { - __block NSString* uuidString; - - id signalCompletion = ^(UADSSCARSignals *_Nullable signals) { - [self.scarSignalSender sendSCARSignalsWithUUIDString:uuidString signals:signals isAsync:true]; - }; - - UADSHeaderBiddingTokenCompletion injectedCompletion = ^(UADSHeaderBiddingToken *_Nullable token) { - if (token.isValid) { - uuidString = token.uuidString; - [self.scarSignalReader requestSCARSignalsWithIsAsync:true completion:signalCompletion]; - token = [self setUUIDString:uuidString ifRemoteToken:token]; - } - completion(token); - }; - - [super getToken:injectedCompletion]; -} - -@end diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHBConfigurationReader.h b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHBConfigurationReader.h index fecfcc26..0b0c0fbe 100644 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHBConfigurationReader.h +++ b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHBConfigurationReader.h @@ -1,11 +1,7 @@ #ifndef UADSSCARHBConfigurationReader_h #define UADSSCARHBConfigurationReader_h -#import "UADSSCARHBStrategyType.h" - @protocol UADSSCARHBConfigurationReader - -- (UADSSCARHBStrategyType) selectedSCARHBStrategyType; - (NSString *)getCurrentScarHBURL; @end diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHBStrategyType.h b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHBStrategyType.h deleted file mode 100644 index a1823c24..00000000 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHBStrategyType.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef UADSSCARHBStrategyType_h -#define UADSSCARHBStrategyType_h - -typedef enum : NSUInteger { - UADSSCARHeaderBiddingStrategyTypeDisabled, - UADSSCARHeaderBiddingStrategyTypeEager, - UADSSCARHeaderBiddingStrategyTypeLazy, - UADSSCARHeaderBiddingStrategyTypeHybrid -} UADSSCARHBStrategyType; - -#endif /* UADSSCARHBStrategyType_h */ diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingFetchSendStrategyFactory.h b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingFetchSendStrategyFactory.h deleted file mode 100644 index 71337ae7..00000000 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingFetchSendStrategyFactory.h +++ /dev/null @@ -1,12 +0,0 @@ -#import -#import "UADSSCARHeaderBiddingStrategyFactory.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface UADSSCARHeaderBiddingFetchSendStrategyFactory : NSObject - -@property (nonatomic, weak) UADSHeaderBiddingTokenReaderSCARSignalsConfig* config; - -@end - -NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingFetchSendStrategyFactory.m b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingFetchSendStrategyFactory.m deleted file mode 100644 index 89026ed5..00000000 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingFetchSendStrategyFactory.m +++ /dev/null @@ -1,27 +0,0 @@ -#import "UADSSCARHeaderBiddingFetchSendStrategyFactory.h" -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsEagerStrategy.h" -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.h" -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.h" - -@implementation UADSSCARHeaderBiddingFetchSendStrategyFactory - -- (id) strategyWithOriginal:(id)original { - - id strategy = original; - switch (self.config.configurationReader.selectedSCARHBStrategyType) { - case UADSSCARHeaderBiddingStrategyTypeEager: - strategy = [UADSHeaderBiddingTokenReaderWithSCARSignalsEagerStrategy decorateOriginal:original config:self.config]; - break; - case UADSSCARHeaderBiddingStrategyTypeLazy: - strategy = [UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy decorateOriginal:original config:self.config]; - break; - case UADSSCARHeaderBiddingStrategyTypeHybrid: - strategy = [UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy decorateOriginal:original config:self.config]; - break; - case UADSSCARHeaderBiddingStrategyTypeDisabled: - default: - break; - } - return strategy; -} -@end diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingStrategyFactory.h b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingStrategyFactory.h deleted file mode 100644 index b87ec849..00000000 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARHeaderBiddingStrategyFactory.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef UADSSCARHeaderBiddingStrategyFactory_h -#define UADSSCARHeaderBiddingStrategyFactory_h - -#import "UADSGMAScar.h" -#import "USRVWebRequestFactory.h" -#import "UADSHeaderBiddingTokenReaderSCARSignalsConfig.h" -#import "UADSSCARHBStrategyType.h" - - -@protocol UADSSCARHeaderBiddingStrategyFactory - -- (id _Nonnull) strategyWithOriginal:(id_Nonnull)original; - -@end - -#endif /* UADSSCARHeaderBiddingStrategyFactory_h */ diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARRawSignalsReader.m b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARRawSignalsReader.m index d46d5a4d..b795c6dd 100644 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARRawSignalsReader.m +++ b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARRawSignalsReader.m @@ -2,6 +2,7 @@ #import "UADSSCARSignalIdentifiers.h" #import "UADSSCARHeaderBiddingMetric.h" #import "NSMutableDictionary+SafeOperations.h" +#import "UADSScarSignalParameters.h" @implementation UADSSCARRawSignalsReader @@ -12,8 +13,7 @@ - (void) requestSCARSignalsWithIsAsync:(BOOL)isAsync completion: (_Nullable UADS id success = ^(UADSSCARSignals *_Nullable signals) { [self.config.metricsSender sendMetric: [UADSSCARHeaderBiddingMetric newScarFetchTimeSuccess:[self durationFromStartTime:startTime] isAsync:isAsync]]; - completion(signals); - + completion([self validateSignals: signals]); }; id error = ^(id _Nonnull error) { @@ -25,12 +25,34 @@ - (void) requestSCARSignalsWithIsAsync:(BOOL)isAsync completion: (_Nullable UADS UADSGMAScarSignalsCompletion *scarSignalsCompletion = [UADSGMAScarSignalsCompletion newWithSuccess: success andError: error]; - [self.config.signalService getSCARSignalsUsingInterstitialList:@[UADSScarInterstitialSignal] andRewardedList:@[UADSScarRewardedSignal] completion:scarSignalsCompletion]; + [self.config.signalService getSCARSignals:self.signalsToCollect completion:scarSignalsCompletion]; } - (NSNumber *)durationFromStartTime:(CFTimeInterval)startTime { return [self.config.timestampReader msDurationFrom: startTime]; } +- (BOOL)scarBannerSignalsEnabled { + return [self.config.configurationReader.currentSessionExperiments isScarBannerSignalsEnabled]; +} +- (NSArray*)signalsToCollect { + NSMutableArray *params = [NSMutableArray arrayWithArray:@[ + [[UADSScarSignalParameters alloc] initWithPlacementId:UADSScarInterstitialSignal adFormat:GADQueryInfoAdTypeInterstitial], + [[UADSScarSignalParameters alloc] initWithPlacementId:UADSScarRewardedSignal adFormat: GADQueryInfoAdTypeRewarded] + ]]; + if ([self scarBannerSignalsEnabled]) { + [params addObject:[[UADSScarSignalParameters alloc] initWithPlacementId:UADSScarBannerSignal adFormat:GADQueryInfoAdTypeBanner]]; + } + return params; +} + +- (UADSSCARSignals *)validateSignals:(UADSSCARSignals *)signals { + if (![signals objectForKey:UADSScarRewardedSignal] && + ![signals objectForKey:UADSScarInterstitialSignal] && + (!self.scarBannerSignalsEnabled || ![signals objectForKey:UADSScarBannerSignal])) { + return nil; + } + return signals; +} @end diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARSignalIdentifiers.h b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARSignalIdentifiers.h index ef3f7466..1a840a9d 100644 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARSignalIdentifiers.h +++ b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARSignalIdentifiers.h @@ -4,10 +4,12 @@ static NSString *const UADSScarRewardedSignal = @"gmaScarBiddingRewardedSignal"; static NSString *const UADSScarInterstitialSignal = @"gmaScarBiddingInterstitialSignal"; +static NSString *const UADSScarBannerSignal = @"gmaScarBiddingBannerSignal"; static NSString *const UADSScarUUIDKey = @"tid"; static NSString *const UADSScarRewardedKey = @"rv"; static NSString *const UADSScarInterstitialKey = @"in"; +static NSString *const UADSScarBannerKey = @"bn"; static NSString *const UADSScarIdfiKey = @"idfi"; #endif /* UADSSCARSignalIdentifiers_h */ diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARWebRequestSignalSender.m b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARWebRequestSignalSender.m index 4720f472..17d0d4e3 100644 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARWebRequestSignalSender.m +++ b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/ScarHeaderBidding/UADSSCARWebRequestSignalSender.m @@ -15,7 +15,7 @@ - (instancetype)init { } - (void)sendSCARSignalsWithUUIDString:(NSString* _Nonnull)uuidString signals:(UADSSCARSignals * _Nonnull) signals isAsync:(BOOL)isAsync { - if (![signals objectForKey:UADSScarRewardedSignal] && ![signals objectForKey:UADSScarInterstitialSignal]) { + if (!signals) { NSMutableDictionary *tags = [NSMutableDictionary dictionaryWithDictionary: @{ @"reason": @"No SCAR Signals passed along" }]; @@ -45,6 +45,7 @@ - (void)sendSCARSignalsWithUUIDString:(NSString* _Nonnull)uuidString signals:(UA [info uads_setValueIfNotNil:uuidString forKey:UADSScarUUIDKey]; [info uads_setValueIfNotNil:[signals objectForKey:UADSScarRewardedSignal] forKey:UADSScarRewardedKey]; [info uads_setValueIfNotNil:[signals objectForKey:UADSScarInterstitialSignal] forKey:UADSScarInterstitialKey]; + [info uads_setValueIfNotNil:[signals objectForKey:UADSScarBannerSignal] forKey:UADSScarBannerKey]; [info uads_setValueIfNotNil:idfi forKey:UADSScarIdfiKey]; NSError *error; diff --git a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/UADSHeaderBiddingTokenReaderBase.m b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/UADSHeaderBiddingTokenReaderBase.m index e1396511..d1f26ca9 100644 --- a/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/UADSHeaderBiddingTokenReaderBase.m +++ b/SourceCode/Private/Core/Device/HeaderBiddingTokenReader/UADSHeaderBiddingTokenReaderBase.m @@ -28,9 +28,7 @@ + (instancetype)newWithDeviceInfoReader: (id)deviceInfoRea - (void)getToken:(UADSHeaderBiddingTokenCompletion)completion { NSMutableDictionary *info = [NSMutableDictionary dictionaryWithDictionary:[_deviceInfoReader getDeviceInfoForGameMode: UADSGameModeMix]]; NSString* uniqueId = [self.uniqueIdGenerator generateId]; - if (self.configurationReader.selectedSCARHBStrategyType != UADSSCARHeaderBiddingStrategyTypeDisabled) { - info[@"tid"] = uniqueId; - } + info[@"tid"] = uniqueId; NSString *tokenValue = [_compressor compressedIntoString: info]; NSString *prefixedTokenValue = [self.customPrefix stringByAppendingString: tokenValue]; UADSHeaderBiddingToken *hbToken = [UADSHeaderBiddingToken newNative:prefixedTokenValue]; diff --git a/SourceCode/Private/Core/Properties/USRVSdkProperties.m b/SourceCode/Private/Core/Properties/USRVSdkProperties.m index 512c5749..f46407fd 100644 --- a/SourceCode/Private/Core/Properties/USRVSdkProperties.m +++ b/SourceCode/Private/Core/Properties/USRVSdkProperties.m @@ -11,12 +11,12 @@ NSString *const kUnityServicesLocalStorageFilePrefix = @"UnityAdsStorage-"; NSString *const kUnityServicesWebviewBranchInfoDictionaryKey = @"UADSWebviewBranch"; NSString *const kUnityServicesWebviewConfigInfoDictionaryKey = @"UADSWebviewConfig"; -NSString *const kUnityServicesVersionName = @"4.8.0"; +NSString *const kUnityServicesVersionName = @"4.9.0"; NSString *const kUnityServicesFlavorDebug = @"debug"; NSString *const kUnityServicesFlavorRelease = @"release"; NSString *const kChinaIsoAlpha2Code = @"CN"; NSString *const kChinaIsoAlpha3Code = @"CHN"; -int const kUnityServicesVersionCode = 4800; +int const kUnityServicesVersionCode = 4900; @implementation USRVSdkProperties diff --git a/SourceCode/Private/Core/Request/Metrics/Events/Load/UADSLoadMetric.m b/SourceCode/Private/Core/Request/Metrics/Events/Load/UADSLoadMetric.m index d5b25d94..92c2c8db 100644 --- a/SourceCode/Private/Core/Request/Metrics/Events/Load/UADSLoadMetric.m +++ b/SourceCode/Private/Core/Request/Metrics/Events/Load/UADSLoadMetric.m @@ -40,7 +40,7 @@ + (instancetype)newEventSuccess: (UADSEventHandlerType)type time: (nullable NSNu break; } return [self newWithName: metricName - value: nil + value: value tags: metricTags]; } @@ -61,7 +61,7 @@ + (instancetype)newEventFailed: (UADSEventHandlerType)type time: (nullable NSNum break; } return [self newWithName: metricName - value: nil + value: value tags: metricTags]; } diff --git a/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/Banner/GMABannerAdLoader.h b/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/Banner/GMABannerAdLoader.h new file mode 100644 index 00000000..3267a715 --- /dev/null +++ b/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/Banner/GMABannerAdLoader.h @@ -0,0 +1,12 @@ +#import +#import "GMALoaderBase.h" +#import "GADBannerViewBridge.h" +#import "GMABannerViewDelegateProxy.h" +NS_ASSUME_NONNULL_BEGIN + +@interface GMABannerAdLoader : GMALoaderBase + + +@end + +NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/Banner/GMABannerAdLoader.m b/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/Banner/GMABannerAdLoader.m new file mode 100644 index 00000000..8865bff5 --- /dev/null +++ b/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/Banner/GMABannerAdLoader.m @@ -0,0 +1,46 @@ +#import "GMABannerAdLoader.h" + +typedef GMAGenericAdsDelegateObject StoredObject; + +@implementation GMABannerAdLoader + ++ (BOOL)isSupported { + return [super isSupported] && [GADBannerViewBridge exists]; +} + +- (void)loadAdUsingMetaData: (GMAAdMetaData *)meta + andCompletion: (UADSLoadAdCompletion *)completion { + idreturnedError; + GADRequestBridge *request = [self.requestFactory getAdRequestFor: meta + error: &returnedError]; + + if (returnedError) { + [completion error: returnedError]; + return; + } + + GADBannerViewBridge *banner = [GADBannerViewBridge newWithAdSize: meta.bannerSize]; + [banner setAdUnitId: meta.adUnitID]; + [self saveAdWithMetaData: banner + metaData: meta + andCompletion: completion]; + + meta.beforeLoad(banner); + meta.beforeLoad = nil; + [banner loadRequest:request]; +} + +- (void)saveAdWithMetaData: (GADBannerViewBridge *)ad + metaData: (GMAAdMetaData *)meta + andCompletion: (UADSLoadAdCompletion *)completion { + GMABannerViewDelegateProxy *delegate = [self.delegatesFactory bannerDelegate: meta + andCompletion: completion]; + StoredObject *adContainer = [StoredObject newWithAd: ad + delegate: delegate]; + + [ad setDelegate: delegate]; + [self.storage setValue: adContainer + forKey: meta.placementID]; +} + +@end diff --git a/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdLoaderStrategy.h b/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdLoaderStrategy.h index f84c43c6..00c99684 100644 --- a/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdLoaderStrategy.h +++ b/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdLoaderStrategy.h @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL) isSupported; @end -@interface GMAAdLoaderStrategy : NSObject +@interface GMAAdLoaderStrategy : NSObject + (instancetype)newWithRequestFactory: (id)requestFactory andDelegateFactory: (nonnull id)delegatesFactory; diff --git a/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdLoaderStrategy.m b/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdLoaderStrategy.m index 00705a09..43e42629 100644 --- a/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdLoaderStrategy.m +++ b/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdLoaderStrategy.m @@ -4,12 +4,14 @@ #import "GMARewardedAdLoaderV7.h" #import "GMARewardedAdLoaderV8.h" #import "GMAVersionReaderStrategy.h" +#import "GMABannerAdLoader.h" #import "GMAError.h" static NSString *const kGMAAdLoaderStrategyNotFoundError = @"ERROR: Cannot find loader of type: %li"; @interface GMAAdLoaderStrategy () @property (strong, nonatomic) GMALoaderBase *interstitialLoader; @property (strong, nonatomic) GMALoaderBase *rewardedLoader; +@property (strong, nonatomic) GMALoaderBase *bannerLoader; @property (strong, nonatomic) GMAVersionReaderStrategy *versionReader; @end @@ -22,6 +24,8 @@ + (instancetype)newWithRequestFactory: (id)requestFactory andDelegateFactory: delegatesFactory]; obj.rewardedLoader = [self createRewardedLoaderWithRequestFactory: requestFactory andDelegateFactory: delegatesFactory]; + obj.bannerLoader = [self createBannerLoaderWithRequestFactory: requestFactory + andDelegateFactory: delegatesFactory]; obj.versionReader = [[GMAVersionReaderStrategy alloc] init]; return obj; } @@ -76,17 +80,21 @@ + (GMALoaderBase *)createRewardedLoaderWithRequestFactory: (id)requestFactory + andDelegateFactory: (nonnull id)delegatesFactory { + + return [GMABannerAdLoader newWithRequestFactory: requestFactory + andDelegateFactory: delegatesFactory]; +} + - (id)strategyForAdType: (GADQueryInfoAdType)type { switch (type) { + case GADQueryInfoAdTypeBanner: + return _bannerLoader; case GADQueryInfoAdTypeInterstitial: return _interstitialLoader; - - break; - case GADQueryInfoAdTypeRewarded: return _rewardedLoader; - - break; } return nil; } @@ -119,4 +127,10 @@ - (void)showAdUsingMetaData: (GMAAdMetaData *)meta error: error]; } +- (void)removeAdForPlacement:(NSString *)placement { + [_interstitialLoader removeAdForPlacement:placement]; + [_rewardedLoader removeAdForPlacement:placement]; + [_bannerLoader removeAdForPlacement:placement]; +} + @end diff --git a/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdMetaData/GMAAdMetaData.h b/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdMetaData/GMAAdMetaData.h index e4ab552f..2674390e 100644 --- a/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdMetaData/GMAAdMetaData.h +++ b/SourceCode/Private/GMAScar/GMAAdLoaders/GMAAdLoaderStrategy/GMAAdMetaData/GMAAdMetaData.h @@ -1,5 +1,7 @@ #import +#import #import "GADQueryInfoBridge.h" +#import "GADBaseAd.h" NS_ASSUME_NONNULL_BEGIN @interface GMAAdMetaData : NSObject @@ -9,6 +11,10 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy) NSString *adUnitID; @property (nonatomic, copy) NSString *queryID; @property (nonatomic, strong) NSNumber *videoLength; +@property (nonatomic, strong) NSString *bannerAdId; +@property (nonatomic, assign) CGSize bannerSize; +@property (nonatomic, copy, nullable) void (^beforeLoad)(GADBaseAd *); + - (NSTimeInterval)videoLengthInSeconds; @end diff --git a/SourceCode/Private/GMAScar/GMAAdLoaders/GMALoaderBase.h b/SourceCode/Private/GMAScar/GMAAdLoaders/GMALoaderBase.h index b2450b53..313eb49f 100644 --- a/SourceCode/Private/GMAScar/GMAAdLoaders/GMALoaderBase.h +++ b/SourceCode/Private/GMAScar/GMAAdLoaders/GMALoaderBase.h @@ -23,8 +23,12 @@ typedef UADSGenericCompletion UADSLoadAdCompletion; @end +@protocol GMAAdStorage +- (void)removeAdForPlacement: (NSString *)placement; +@end + -@interface GMALoaderBase<__covariant AdType, __covariant DelegateType>: NSObject +@interface GMALoaderBase<__covariant AdType, __covariant DelegateType>: NSObject typedef GMAGenericAdsDelegateObject GMALoaderBaseStoredObject; typedef NSMutableDictionary GMALoaderBaseItemStorage; diff --git a/SourceCode/Private/GMAScar/GMAAdLoaders/GMALoaderBase.m b/SourceCode/Private/GMAScar/GMAAdLoaders/GMALoaderBase.m index a3942a45..4dc387fc 100644 --- a/SourceCode/Private/GMAScar/GMAAdLoaders/GMALoaderBase.m +++ b/SourceCode/Private/GMAScar/GMAAdLoaders/GMALoaderBase.m @@ -51,4 +51,8 @@ - (void)loadAdUsingMetaData: (nonnull GMAAdMetaData *)meta UADS_ABSTRACT_CLASS_EXCEPTION } +- (void)removeAdForPlacement:(NSString *)placementId { + [_storage removeObjectForKey: placementId]; +} + @end diff --git a/SourceCode/Private/GMAScar/GMABridges/BannerDelegateProxy/GMABannerViewDelegateProxy.h b/SourceCode/Private/GMAScar/GMABridges/BannerDelegateProxy/GMABannerViewDelegateProxy.h new file mode 100644 index 00000000..fb60e123 --- /dev/null +++ b/SourceCode/Private/GMAScar/GMABridges/BannerDelegateProxy/GMABannerViewDelegateProxy.h @@ -0,0 +1,32 @@ +#import +#import "GMAAdMetaData.h" +#import "UADSWebViewEventSender.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol UADSGADBannerViewDelegate +- (void)bannerViewDidReceiveAd:(nonnull id)bannerView; +- (void)bannerView:(nonnull id)bannerView didFailToReceiveAdWithError:(nonnull NSError *)error; +- (void)bannerViewDidRecordImpression:(nonnull id)bannerView; +- (void)bannerViewDidRecordClick:(nonnull id)bannerView; +- (void)bannerViewWillPresentScreen:(nonnull id)bannerView; +- (void)bannerViewWillDismissScreen:(nonnull id)bannerView; +- (void)bannerViewDidDismissScreen:(nonnull id)bannerView; +@end + +@interface GMABannerViewDelegateProxy : NSObject ++ (instancetype)newWithMetaData: (GMAAdMetaData *)meta + andErrorHandler: (id)errorHandler + andSender: (id)eventSender + andCompletion: (UADSAnyCompletion *)completion; + +- (void)bannerViewDidReceiveAd:(nonnull id)bannerView; +- (void)bannerView:(nonnull id)bannerView didFailToReceiveAdWithError:(nonnull NSError *)error; +- (void)bannerViewDidRecordImpression:(nonnull id)bannerView; +- (void)bannerViewDidRecordClick:(nonnull id)bannerView; +- (void)bannerViewWillPresentScreen:(nonnull id)bannerView; +- (void)bannerViewWillDismissScreen:(nonnull id)bannerView; +- (void)bannerViewDidDismissScreen:(nonnull id)bannerView; +@end + +NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/GMAScar/GMABridges/BannerDelegateProxy/GMABannerViewDelegateProxy.m b/SourceCode/Private/GMAScar/GMABridges/BannerDelegateProxy/GMABannerViewDelegateProxy.m new file mode 100644 index 00000000..8abe5278 --- /dev/null +++ b/SourceCode/Private/GMAScar/GMABridges/BannerDelegateProxy/GMABannerViewDelegateProxy.m @@ -0,0 +1,58 @@ +#import "GMABannerViewDelegateProxy.h" +#import "GMAError.h" +#import "GMABannerWebViewEvent.h" + +@interface GMABannerViewDelegateProxy () +@property (nonatomic, strong) GMAAdMetaData *meta; +@property (nonatomic, strong) ideventSender; +@property (nonatomic, strong) iderrorHandler; +@property (nonatomic, strong) UADSAnyCompletion *completion; +@end + +@implementation GMABannerViewDelegateProxy + ++ (instancetype)newWithMetaData: (GMAAdMetaData *)meta + andErrorHandler: (id)errorHandler + andSender: (id)eventSender + andCompletion: (UADSAnyCompletion *)completion { + GMABannerViewDelegateProxy *base = [[self alloc] init]; + + base.eventSender = eventSender; + base.meta = meta; + base.completion = completion; + base.errorHandler = errorHandler; + + return base; +} + +- (void)bannerViewDidReceiveAd:(nonnull id)bannerView { + [self.completion success: bannerView]; +} + +- (void)bannerView:(nonnull id)bannerView didFailToReceiveAdWithError:(nonnull NSError *)error { + GMAError *gmaError = [GMAError newLoadErrorUsingMetaData: _meta + andError: error]; + + [self.completion error: gmaError]; +} + +- (void)bannerViewDidRecordImpression:(nonnull id)bannerView { + [self.eventSender sendEvent: [GMABannerWebViewEvent newBannerImpressionWithMeta:self.meta]]; +} + +- (void)bannerViewDidRecordClick:(nonnull id)bannerView { + [self.eventSender sendEvent: [GMABannerWebViewEvent newBannerClickedWithMeta:self.meta]]; +} + +- (void)bannerViewWillPresentScreen:(nonnull id)bannerView { + [self.eventSender sendEvent: [GMABannerWebViewEvent newBannerOpenedWithMeta:self.meta]]; +} + +- (void)bannerViewWillDismissScreen:(nonnull id)bannerView { +} + +- (void)bannerViewDidDismissScreen:(nonnull id)bannerView { + [self.eventSender sendEvent: [GMABannerWebViewEvent newBannerClosedWithMeta:self.meta]]; +} + +@end diff --git a/SourceCode/Private/GMAScar/GMABridges/GADAdSizeBridge.h b/SourceCode/Private/GMAScar/GMABridges/GADAdSizeBridge.h new file mode 100644 index 00000000..3db609ad --- /dev/null +++ b/SourceCode/Private/GMAScar/GMABridges/GADAdSizeBridge.h @@ -0,0 +1,7 @@ +#import + +struct GADAdSizeBridge { + CGSize size; + NSUInteger flags; +}; +typedef struct GADAdSizeBridge GADAdSizeBridge; diff --git a/SourceCode/Private/GMAScar/GMABridges/GADBannerViewBridge.h b/SourceCode/Private/GMAScar/GMABridges/GADBannerViewBridge.h new file mode 100644 index 00000000..bbda4bfe --- /dev/null +++ b/SourceCode/Private/GMAScar/GMABridges/GADBannerViewBridge.h @@ -0,0 +1,20 @@ +#import +#import +#import "GADBaseAd.h" +#import "UADSProxyReflection.h" +#import "GADRequestBridge.h" +#import "GMABannerViewDelegateProxy.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface GADBannerViewBridge : GADBaseAd ++ (nullable instancetype)newWithAdSize:(CGSize)size; + +- (void)setAdUnitId:(NSString *)adUnitId; +- (void)setRootViewController:(UIViewController *)rootViewController; +- (void)setDelegate: (id)delegate; +- (void)loadRequest:(GADRequestBridge*)request; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/GMAScar/GMABridges/GADBannerViewBridge.m b/SourceCode/Private/GMAScar/GMABridges/GADBannerViewBridge.m new file mode 100644 index 00000000..5fc6b78c --- /dev/null +++ b/SourceCode/Private/GMAScar/GMABridges/GADBannerViewBridge.m @@ -0,0 +1,51 @@ +#import "GADBannerViewBridge.h" +#import "GADAdSizeBridge.h" +#import "GADAdSizeStructBox.h" + +#define INIT_SELECTOR @"initWithAdSize:" +#define LOAD_REQUEST_SELECTOR @"loadRequest:" +#define DELEGATE_KEY @"delegate" +#define AD_UNIT_ID_KEY @"adUnitID" +#define ROOT_VIEW_CONTROLLER_KEY @"rootViewController" + +@implementation GADBannerViewBridge + ++ (NSString *)className { + return @"GADBannerView"; +} + ++ (NSArray *)requiredSelectors { + return @[INIT_SELECTOR]; +} + ++ (nullable instancetype)newWithAdSize:(CGSize)size { + struct GADAdSizeBridge adSize; + adSize.size = size; + adSize.flags = 0; + GADAdSizeStructBox *box = [GADAdSizeStructBox newWithBytes:&adSize objCType:@encode(GADAdSizeBridge)]; + return [self getInstanceUsingMethod: INIT_SELECTOR + args: @[box]]; +} + +- (void)setAdUnitId:(nonnull NSString *)adUnitId { + [self.proxyObject setValue: adUnitId + forKey: AD_UNIT_ID_KEY]; +} + +- (void)setRootViewController:(nonnull UIViewController *)rootViewController { + [self.proxyObject setValue: rootViewController + forKey: ROOT_VIEW_CONTROLLER_KEY]; +} + +- (void)setDelegate: (id)delegate { + [self.proxyObject setValue: delegate + forKey: DELEGATE_KEY]; +} + +- (void)loadRequest:(nonnull GADRequestBridge *)request { + [self callInstanceMethod: LOAD_REQUEST_SELECTOR + args: @[request]]; +} + + +@end diff --git a/SourceCode/Private/GMAScar/GMABridges/GADQueryInfoBridge.h b/SourceCode/Private/GMAScar/GMABridges/GADQueryInfoBridge.h index 1420fb57..9a2bccf4 100644 --- a/SourceCode/Private/GMAScar/GMABridges/GADQueryInfoBridge.h +++ b/SourceCode/Private/GMAScar/GMABridges/GADQueryInfoBridge.h @@ -3,6 +3,7 @@ #import "UADSGenericCompletion.h" typedef NS_ENUM (NSInteger, GADQueryInfoAdType) { + GADQueryInfoAdTypeBanner = 0, GADQueryInfoAdTypeInterstitial = 1, GADQueryInfoAdTypeRewarded = 2 }; diff --git a/SourceCode/Private/GMAScar/GMABridges/GMADelegatesFactory/GMADelegatesFactory.h b/SourceCode/Private/GMAScar/GMABridges/GMADelegatesFactory/GMADelegatesFactory.h index 071bc97b..b768f8dd 100644 --- a/SourceCode/Private/GMAScar/GMABridges/GMADelegatesFactory/GMADelegatesFactory.h +++ b/SourceCode/Private/GMAScar/GMABridges/GMADelegatesFactory/GMADelegatesFactory.h @@ -1,6 +1,7 @@ #import #import "GMAInterstitialAdDelegateProxy.h" #import "GMARewardedAdDelegateProxy.h" +#import "GMABannerViewDelegateProxy.h" #import "UADSTimerFactory.h" NS_ASSUME_NONNULL_BEGIN @@ -9,7 +10,8 @@ NS_ASSUME_NONNULL_BEGIN - (GMAInterstitialAdDelegateProxy *)interstitialDelegate: (GMAAdMetaData *)meta andCompletion: (UADSAnyCompletion *)completion; - (GMARewardedAdDelegateProxy *)rewardedDelegate: (GMAAdMetaData *)meta; - +- (GMABannerViewDelegateProxy *)bannerDelegate: (GMAAdMetaData *)meta + andCompletion: (nonnull UADSAnyCompletion *)completion; @end @interface GMADelegatesBaseFactory : NSObject diff --git a/SourceCode/Private/GMAScar/GMABridges/GMADelegatesFactory/GMADelegatesFactory.m b/SourceCode/Private/GMAScar/GMABridges/GMADelegatesFactory/GMADelegatesFactory.m index ff180469..1c4f26bf 100644 --- a/SourceCode/Private/GMAScar/GMABridges/GMADelegatesFactory/GMADelegatesFactory.m +++ b/SourceCode/Private/GMAScar/GMABridges/GMADelegatesFactory/GMADelegatesFactory.m @@ -45,4 +45,11 @@ - (nonnull GMARewardedAdDelegateProxy *)rewardedDelegate: (nonnull GMAAdMetaData andTimer: [_timerFactory timerWithAppLifeCycle]]; } +- (GMABannerViewDelegateProxy *)bannerDelegate: (GMAAdMetaData *)meta andCompletion: (nonnull UADSAnyCompletion *)completion { + return [GMABannerViewDelegateProxy newWithMetaData: meta + andErrorHandler: _errorHandler + andSender: _eventSender + andCompletion:completion ]; +} + @end diff --git a/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReader.h b/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReader.h index 94a7624a..04b38584 100644 --- a/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReader.h +++ b/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReader.h @@ -1,5 +1,6 @@ #import "UADSGenericCompletion.h" #import "GMAQuerySignalReader.h" +#import "UADSScarSignalParameters.h" NS_ASSUME_NONNULL_BEGIN @@ -8,9 +9,8 @@ typedef NSDictionary UADSSCARSignals; typedef UADSGenericCompletion UADSGMAScarSignalsCompletion; @protocol GMASCARSignalsReader -- (void)getSCARSignalsUsingInterstitialList: (NSArray *)interstitialList - andRewardedList: (NSArray *)rewardedList - completion: (UADSGMAScarSignalsCompletion *)completion; +- (void)getSCARSignals: (NSArray*)signalParameters + completion: (UADSGMAScarSignalsCompletion *)completion; @end @protocol GMASCARSignalService; diff --git a/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReader.m b/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReader.m index 2b8cbcb7..bde904ea 100644 --- a/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReader.m +++ b/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReader.m @@ -21,28 +21,20 @@ - (instancetype)initWithSignalService: (id)signalService { return self; } -- (void)getSCARSignalsUsingInterstitialList: (nonnull NSArray *)interstitialList - andRewardedList: (nonnull NSArray *)rewardedList - completion: (nonnull UADSGMAScarSignalsCompletion *)completion { +- (void)getSCARSignals: (NSArray*)signalParameters + completion: (UADSGMAScarSignalsCompletion *)completion { __block UADSMutableScarSignals *signals = [[UADSMutableScarSignals alloc] init]; __block id signalError; dispatch_group_t group = dispatch_group_create(); - [self getSignalsOfType: GADQueryInfoAdTypeInterstitial - list: interstitialList - signalsMap: signals - group: group - error: ^(id returnedError) { - signalError = returnedError; - }]; - - [self getSignalsOfType: GADQueryInfoAdTypeRewarded - list: rewardedList - signalsMap: signals - group: group - error: ^(id returnedError) { - signalError = returnedError; - }]; + for (UADSScarSignalParameters *params in signalParameters) { + [self getSignalsWithParameters: params + signalsMap: signals + group: group + error: ^(id returnedError) { + signalError = returnedError; + }]; + } dispatch_group_notify(group, dispatch_get_main_queue(), ^{ if (signals.count == 0 && signalError) { @@ -51,6 +43,7 @@ - (void)getSCARSignalsUsingInterstitialList: (nonnull NSArray *)interstitialList [completion success: signals]; } }); + } - (void)updateSignals: (UADSSCARSignals *)signals @@ -62,22 +55,20 @@ - (void)updateSignals: (UADSSCARSignals *)signals }); } -- (void)getSignalsOfType: (GADQueryInfoAdType)adType - list: (NSArray *)list - signalsMap: (UADSSCARSignals *)signals - group: (dispatch_group_t)group - error: (ReturnErrorCompletion)error { - for (NSString *placementID in list) { - dispatch_group_enter(group); - - UADSGMASCARCompletion *completion = [self completionForPlacement: placementID - signalsMap: signals - group: group - error: error]; - [self.signalService getSignalOfAdType: adType - forPlacementId: placementID - completion: completion]; - } +- (void)getSignalsWithParameters: (UADSScarSignalParameters *)params + signalsMap: (UADSSCARSignals *)signals + group: (dispatch_group_t)group + error: (ReturnErrorCompletion)error { + dispatch_group_enter(group); + + UADSGMASCARCompletion *completion = [self completionForPlacement: params.placementId + signalsMap: signals + group: group + error: error]; + [self.signalService getSignalOfAdType: params.adFormat + forPlacementId: params.placementId + completion: completion]; + } - (UADSGMASCARCompletion *)completionForPlacement: (NSString *)placementID diff --git a/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReaderDecorator.h b/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReaderDecorator.h index 9d4a3447..efa1000d 100644 --- a/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReaderDecorator.h +++ b/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReaderDecorator.h @@ -1,13 +1,13 @@ #import "UADSGenericCompletion.h" #import "GMASCARSignalsReader.h" +#import "UADSScarSignalParameters.h" NS_ASSUME_NONNULL_BEGIN typedef UADSGenericCompletion UADSGMAEncodedSignalsCompletion; @protocol GMAEncodedSCARSignalsReader -- (void)getSCARSignalsUsingInterstitialList: (NSArray *)interstitialList - andRewardedList: (NSArray *)rewardedList - completion: (UADSGMAEncodedSignalsCompletion *)completion; +- (void)getSCARSignals: (NSArray*) signalParameters + completion: (UADSGMAEncodedSignalsCompletion *)completion; @end diff --git a/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReaderDecorator.m b/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReaderDecorator.m index f3353591..5150ca4a 100644 --- a/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReaderDecorator.m +++ b/SourceCode/Private/GMAScar/GMAScarSignalsReader/GMASCARSignalsReaderDecorator.m @@ -17,9 +17,8 @@ - (instancetype)initWithSignalService: (id)signalService { return self; } -- (void)getSCARSignalsUsingInterstitialList: (nonnull NSArray *)interstitialList - andRewardedList: (nonnull NSArray *)rewardedList - completion: (nonnull UADSGMAEncodedSignalsCompletion *)completion { +- (void)getSCARSignals: (NSArray*)signalParameters + completion: (UADSGMAEncodedSignalsCompletion *)completion { __weak typeof(self) weakSelf = self; UADSGMAScarSignalsCompletion *scarCompletion = [UADSGMAScarSignalsCompletion newWithSuccess: ^(UADSSCARSignals *_Nullable signals) { NSError *error; @@ -36,9 +35,7 @@ - (void)getSCARSignalsUsingInterstitialList: (nonnull NSArray *)interstitialList [completion error: error]; }]; - [_signalService getSCARSignalsUsingInterstitialList: interstitialList - andRewardedList: rewardedList - completion: scarCompletion]; + [_signalService getSCARSignals:signalParameters completion:scarCompletion]; } - (NSString *)encodeSignals: (UADSSCARSignals *)signals diff --git a/SourceCode/Private/GMAScar/GMAWebViewEvent/GMABannerWebViewEvent.h b/SourceCode/Private/GMAScar/GMAWebViewEvent/GMABannerWebViewEvent.h new file mode 100644 index 00000000..1bc5740e --- /dev/null +++ b/SourceCode/Private/GMAScar/GMAWebViewEvent/GMABannerWebViewEvent.h @@ -0,0 +1,19 @@ +#import +#import "GMAWebViewEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface GMABannerWebViewEvent : GMAWebViewEvent + ++ (instancetype)newBannerLoadedWithMeta: (GMAAdMetaData *)meta; ++ (instancetype)newBannerLoadFailedWithMeta: (GMAAdMetaData *)meta; ++ (instancetype)newBannerOpenedWithMeta: (GMAAdMetaData *)meta; ++ (instancetype)newBannerClosedWithMeta: (GMAAdMetaData *)meta; ++ (instancetype)newBannerImpressionWithMeta: (GMAAdMetaData *)meta; ++ (instancetype)newBannerClickedWithMeta: (GMAAdMetaData *)meta; ++ (instancetype)newBannerAttachedWithMeta: (GMAAdMetaData *)meta; ++ (instancetype)newBannerDetachedWithMeta: (GMAAdMetaData *)meta; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/GMAScar/GMAWebViewEvent/GMABannerWebViewEvent.m b/SourceCode/Private/GMAScar/GMAWebViewEvent/GMABannerWebViewEvent.m new file mode 100644 index 00000000..46cf9740 --- /dev/null +++ b/SourceCode/Private/GMAScar/GMAWebViewEvent/GMABannerWebViewEvent.m @@ -0,0 +1,55 @@ +#import "GMABannerWebViewEvent.h" + +@implementation GMABannerWebViewEvent + ++ (instancetype)newWithEventName: (NSString *)event andMeta: (GMAAdMetaData *)meta { + return [self newWithCategory: @"BANNER" + withEvent: event + withParams: [self defaultParamsFromMeta: meta]]; +} + ++ (NSArray *)defaultParamsFromMeta: (GMAAdMetaData *)meta { + return @[meta.bannerAdId]; +} + ++ (instancetype)newBannerLoadedWithMeta: (GMAAdMetaData *)meta { + return [self newWithEventName: @"SCAR_BANNER_LOADED" + andMeta: meta]; +} + ++ (instancetype)newBannerLoadFailedWithMeta: (GMAAdMetaData *)meta { + return [self newWithEventName: @"SCAR_BANNER_LOAD_FAILED" + andMeta: meta]; +} + ++ (instancetype)newBannerOpenedWithMeta: (GMAAdMetaData *)meta { + return [self newWithEventName: @"SCAR_BANNER_OPENED" + andMeta: meta]; +} + ++ (instancetype)newBannerClosedWithMeta: (GMAAdMetaData *)meta { + return [self newWithEventName: @"SCAR_BANNER_CLOSED" + andMeta: meta]; +} + ++ (instancetype)newBannerImpressionWithMeta: (GMAAdMetaData *)meta { + return [self newWithEventName: @"SCAR_BANNER_IMPRESSION" + andMeta: meta]; +} + ++ (instancetype)newBannerClickedWithMeta: (GMAAdMetaData *)meta { + return [self newWithEventName: @"SCAR_BANNER_CLICKED" + andMeta: meta]; +} + ++ (instancetype)newBannerAttachedWithMeta: (GMAAdMetaData *)meta { + return [self newWithEventName: @"SCAR_BANNER_ATTACHED" + andMeta: meta]; +} + ++ (instancetype)newBannerDetachedWithMeta: (GMAAdMetaData *)meta { + return [self newWithEventName: @"SCAR_BANNER_DETACHED" + andMeta: meta]; +} + +@end diff --git a/SourceCode/Private/GMAScar/GMAWebViewEvent/GMAWebViewEvent.h b/SourceCode/Private/GMAScar/GMAWebViewEvent/GMAWebViewEvent.h index 4dddc5c4..cf389d3c 100644 --- a/SourceCode/Private/GMAScar/GMAWebViewEvent/GMAWebViewEvent.h +++ b/SourceCode/Private/GMAScar/GMAWebViewEvent/GMAWebViewEvent.h @@ -8,6 +8,8 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)newWithEventName: (NSString *)event andParams: (NSArray *_Nullable)params; ++ (instancetype)newWithEventName: (NSString *)event + andMeta: (GMAAdMetaData *)meta; + (instancetype)newAdEarnRewardWithMeta: (GMAAdMetaData *)meta; + (instancetype)newAdStartedWithMeta: (GMAAdMetaData *)meta; + (instancetype)newFirstQuartileWithMeta: (GMAAdMetaData *)meta; diff --git a/SourceCode/Private/GMAScar/UADSGMAScar.h b/SourceCode/Private/GMAScar/UADSGMAScar.h index a25a1d2e..0435606a 100644 --- a/SourceCode/Private/GMAScar/UADSGMAScar.h +++ b/SourceCode/Private/GMAScar/UADSGMAScar.h @@ -7,6 +7,7 @@ #import "GMAAdMetaData.h" #import "UADSWebViewErrorHandler.h" #import "GMAAdLoaderStrategy.h" +#import "UADSScarSignalParameters.h" @interface UADSGMAScar : NSObject @property (strong, nonatomic) iderrorHandler; @@ -21,15 +22,17 @@ - (BOOL) isGADSupported; - (BOOL) isGADExists; -- (void)getSCARSignalsUsingInterstitialList: (NSArray *)interstitialList - andRewardedList: (NSArray *)rewardedList - completion: (UADSGMAEncodedSignalsCompletion *)completion; +- (void)getSCARSignals: (NSArray*) signalParameters + completion: (UADSGMAEncodedSignalsCompletion *)completion; + - (void)loadAdUsingMetaData: (GMAAdMetaData *)meta andCompletion: (UADSAnyCompletion *)completion; - (void)showAdUsingMetaData: (GMAAdMetaData *)meta inViewController: (UIViewController *)viewController; +- (void)removeAdForPlacement:(NSString *)placementId; + // exposed for tests - (id)queryInfoReader; @end diff --git a/SourceCode/Private/GMAScar/UADSGMAScar.m b/SourceCode/Private/GMAScar/UADSGMAScar.m index f12599fb..0855b765 100644 --- a/SourceCode/Private/GMAScar/UADSGMAScar.m +++ b/SourceCode/Private/GMAScar/UADSGMAScar.m @@ -19,7 +19,7 @@ @interface UADSGMAScar () @property (strong, nonatomic) id signalService; -@property (strong, nonatomic) id loaderStrategy; +@property (strong, nonatomic) id loaderStrategy; @end @implementation UADSGMAScar @@ -89,17 +89,14 @@ - (BOOL)isGADExists { return [GADMobileAdsBridge exists]; } -- (void)getSCARSignalsUsingInterstitialList: (NSArray *)interstitialList - andRewardedList: (NSArray *)rewardedList - completion: (UADSGMAEncodedSignalsCompletion *)completion { +- (void)getSCARSignals: (NSArray*) signalParameters + completion: (UADSGMAEncodedSignalsCompletion *)completion { if (!self.isAvailable) { [completion error: GMAError.newInternalSignalsError]; return; } - - [_signalService getSCARSignalsUsingInterstitialList: interstitialList - andRewardedList: rewardedList - completion: completion]; + + [_signalService getSCARSignals:signalParameters completion:completion]; } - (void)loadAdUsingMetaData: (GMAAdMetaData *)meta @@ -121,6 +118,10 @@ - (void)showAdUsingMetaData: (GMAAdMetaData *)meta } } +- (void)removeAdForPlacement:(NSString *)placementId { + [self.loaderStrategy removeAdForPlacement:placementId]; +} + + (UADSGMAScar *)sharedInstance { static UADSGMAScar *instance = nil; static dispatch_once_t onceToken; diff --git a/SourceCode/Private/GMAScar/UADSScarSignalParameters.h b/SourceCode/Private/GMAScar/UADSScarSignalParameters.h new file mode 100644 index 00000000..a2b7c48a --- /dev/null +++ b/SourceCode/Private/GMAScar/UADSScarSignalParameters.h @@ -0,0 +1,16 @@ +#import +#import "GADQueryInfoBridge.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface UADSScarSignalParameters: NSObject +@property (nonatomic, assign) GADQueryInfoAdType adFormat; +@property (nonatomic, strong) NSString *placementId; + +- (instancetype)initWithPlacementId: (NSString *)placementId + adFormat: (GADQueryInfoAdType)adFormat; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/GMAScar/UADSScarSignalParameters.m b/SourceCode/Private/GMAScar/UADSScarSignalParameters.m new file mode 100644 index 00000000..15ed2c8f --- /dev/null +++ b/SourceCode/Private/GMAScar/UADSScarSignalParameters.m @@ -0,0 +1,20 @@ +#import "UADSScarSignalParameters.h" + +@implementation UADSScarSignalParameters + +- (instancetype)initWithPlacementId: (NSString *)placementId adFormat: (GADQueryInfoAdType)adFormat { + SUPER_INIT; + _adFormat = adFormat; + _placementId = placementId; + return self; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:UADSScarSignalParameters.class]) { + return false; + } + UADSScarSignalParameters *other = object; + return [self.placementId isEqualToString:other.placementId] && self.adFormat == other.adFormat; +} + +@end diff --git a/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/GADAdSizeStructBox.h b/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/GADAdSizeStructBox.h new file mode 100644 index 00000000..6a5c8384 --- /dev/null +++ b/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/GADAdSizeStructBox.h @@ -0,0 +1,8 @@ +#import "NSPrimitivesBox.h" +#import +NS_ASSUME_NONNULL_BEGIN + +@interface GADAdSizeStructBox : NSPrimitivesBox +@end + +NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/GADAdSizeStructBox.m b/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/GADAdSizeStructBox.m new file mode 100644 index 00000000..2d5547ca --- /dev/null +++ b/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/GADAdSizeStructBox.m @@ -0,0 +1,13 @@ +#import "GADAdSizeStructBox.h" +#import "GADAdSizeBridge.h" + +@implementation GADAdSizeStructBox + +- (void)setAsArgumentForInvocation: (NSInvocation *)invocation atIndex:(NSInteger)index { + GADAdSizeBridge structValue; + [self getValue: &structValue]; + [invocation setArgument: &structValue + atIndex: index]; +} + +@end diff --git a/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/NSPrimitivesBox.h b/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/NSPrimitivesBox.h index e6e516f5..d75a5f4e 100644 --- a/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/NSPrimitivesBox.h +++ b/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/NSPrimitivesBox.h @@ -13,6 +13,8 @@ NS_ASSUME_NONNULL_BEGIN */ @interface NSPrimitivesBox : NSValue + (instancetype)newWithBytes: (nonnull const void *)bytes objCType: (nonnull const char *)type; + +- (void)setAsArgumentForInvocation: (NSInvocation *)invocation atIndex:(NSInteger)index; @end NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/NSPrimitivesBox.m b/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/NSPrimitivesBox.m index bc2b02fb..fb29e12c 100644 --- a/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/NSPrimitivesBox.m +++ b/SourceCode/Private/Tools/Categories/NSInvocation/NSEnumWrapper/NSPrimitivesBox.m @@ -35,4 +35,12 @@ - (const char *)objCType { return [_box objCType]; } +- (void)setAsArgumentForInvocation: (NSInvocation *)invocation atIndex:(NSInteger)index { + void *pointerToPrimitives; + [self getValue: &pointerToPrimitives]; + + [invocation setArgument: &pointerToPrimitives + atIndex: index]; +} + @end diff --git a/SourceCode/Private/Tools/Categories/NSInvocation/NSInvocation+Convenience.m b/SourceCode/Private/Tools/Categories/NSInvocation/NSInvocation+Convenience.m index 4b004550..f6b1855f 100644 --- a/SourceCode/Private/Tools/Categories/NSInvocation/NSInvocation+Convenience.m +++ b/SourceCode/Private/Tools/Categories/NSInvocation/NSInvocation+Convenience.m @@ -1,5 +1,7 @@ #import "NSInvocation+Convenience.h" #import "NSPrimitivesBox.h" +#import "GADAdSizeStructBox.h" +#import "GADAdSizeBridge.h" #import "UADSTools.h" @implementation NSInvocation (Category) @@ -62,16 +64,11 @@ + (nullable instancetype)uads_newUsingMethod: (NSString *)methodName NSPrimitivesBox *value = typecast(argument, [NSPrimitivesBox class]); if (value) { - void *pointerToPrimitives; - [value getValue: &pointerToPrimitives]; - /** from https://developer.apple.com/documentation/foundation/nsinvocation/1437834-setargument * An integer specifying the index of the argument. * Indices 0 and 1 indicate the hidden arguments self and _cmd, respectively; you should set these values directly with the target and selector properties. Use indices 2 and greater for the arguments normally passed in a message. */ - - [invocation setArgument: &pointerToPrimitives - atIndex: 2 + i]; + [value setAsArgumentForInvocation:invocation atIndex: 2 + i]; } else { [invocation setArgument: &argument atIndex: 2 + i]; diff --git a/SourceCode/Private/Tools/Categories/UIView/UIView+ParentViewController.h b/SourceCode/Private/Tools/Categories/UIView/UIView+ParentViewController.h new file mode 100644 index 00000000..773b810d --- /dev/null +++ b/SourceCode/Private/Tools/Categories/UIView/UIView+ParentViewController.h @@ -0,0 +1,7 @@ +#import + + +@interface UIView (ParentViewController) +- (nullable UIViewController *)parentViewController; +@end + diff --git a/SourceCode/Private/Tools/Categories/UIView/UIView+ParentViewController.m b/SourceCode/Private/Tools/Categories/UIView/UIView+ParentViewController.m new file mode 100644 index 00000000..47ff95f3 --- /dev/null +++ b/SourceCode/Private/Tools/Categories/UIView/UIView+ParentViewController.m @@ -0,0 +1,14 @@ +#import "UIView+ParentViewController.h" + +@implementation UIView (ParentViewController) +- (nullable UIViewController *)parentViewController { + UIResponder *responder = [self nextResponder]; + while (responder != nil) { + if ([responder isKindOfClass:[UIViewController class]]) { + return (UIViewController *)responder; + } + responder = [responder nextResponder]; + } + return nil; +} +@end diff --git a/SourceCode/Private/Tools/Categories/UIView/UIView+Subview.h b/SourceCode/Private/Tools/Categories/UIView/UIView+Subview.h new file mode 100644 index 00000000..7bb9a126 --- /dev/null +++ b/SourceCode/Private/Tools/Categories/UIView/UIView+Subview.h @@ -0,0 +1,11 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIView (Subview) + +- (void)addSubview:(UIView *)subview withSize:(CGSize)size; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SourceCode/Private/Tools/Categories/UIView/UIView+Subview.m b/SourceCode/Private/Tools/Categories/UIView/UIView+Subview.m new file mode 100644 index 00000000..371bb267 --- /dev/null +++ b/SourceCode/Private/Tools/Categories/UIView/UIView+Subview.m @@ -0,0 +1,40 @@ +#import "UIView+Subview.h" + +@implementation UIView (Subview) + +- (void)addSubview:(UIView *)subview withSize:(CGSize)size { + subview.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview: subview]; + [self addConstraints:@[ + [NSLayoutConstraint constraintWithItem: subview + attribute: NSLayoutAttributeCenterY + relatedBy: NSLayoutRelationEqual + toItem: self + attribute: NSLayoutAttributeCenterY + multiplier: 1 + constant: 0], + [NSLayoutConstraint constraintWithItem: subview + attribute: NSLayoutAttributeCenterX + relatedBy: NSLayoutRelationEqual + toItem: self + attribute: NSLayoutAttributeCenterX + multiplier: 1 + constant: 0], + [NSLayoutConstraint constraintWithItem: subview + attribute: NSLayoutAttributeWidth + relatedBy: NSLayoutRelationEqual + toItem: nil + attribute: NSLayoutAttributeNotAnAttribute + multiplier: 1.0 + constant: size.width], + [NSLayoutConstraint constraintWithItem: subview + attribute: NSLayoutAttributeHeight + relatedBy: NSLayoutRelationEqual + toItem: nil + attribute: NSLayoutAttributeNotAnAttribute + multiplier: 1.0 + constant: size.height] + ]]; +} + +@end diff --git a/SourceCode/Public/Banners/UADSBannerView.m b/SourceCode/Public/Banners/UADSBannerView.m index 7009372d..4caa06db 100644 --- a/SourceCode/Public/Banners/UADSBannerView.m +++ b/SourceCode/Public/Banners/UADSBannerView.m @@ -3,6 +3,7 @@ #import "UADSBannerWebPlayerContainer.h" #import "USRVSdkProperties.h" #import "UADSBannerLoadModule.h" +#import "UADSApiBanner.h" @interface UADSBannerView () diff --git a/SourceCode/Swift/Token/HeaderBiddingTokenReader.swift b/SourceCode/Swift/Token/HeaderBiddingTokenReader.swift index c8e82644..416d3240 100644 --- a/SourceCode/Swift/Token/HeaderBiddingTokenReader.swift +++ b/SourceCode/Swift/Token/HeaderBiddingTokenReader.swift @@ -14,9 +14,7 @@ final class HeaderBiddingTokenReaderBase: HeaderBiddingTokenReader { func getToken(_ completion: Closure) throws { var info = config.deviceInfoReader.getDeviceInfoBody(of: .extended) let uniqueId = config.uniqueIdGenerator.uniqueID - if config.experiments.experiments?.scarHbStrategyType != .disabled { - info["tid"] = uniqueId - } + info["tid"] = uniqueId let tokenValue = try config.compressor.compressedInfoString(info) let prefixedTokenValue = config.customPrefix + tokenValue let token = HeaderBiddingToken(value: prefixedTokenValue, diff --git a/Tests/GMAIntegrationTests/CommonTests/GMAAdLoaderStrategy/GMAAdLoaderStrategyTests.m b/Tests/GMAIntegrationTests/CommonTests/GMAAdLoaderStrategy/GMAAdLoaderStrategyTests.m index fd6c922c..bcec7aae 100644 --- a/Tests/GMAIntegrationTests/CommonTests/GMAAdLoaderStrategy/GMAAdLoaderStrategyTests.m +++ b/Tests/GMAIntegrationTests/CommonTests/GMAAdLoaderStrategy/GMAAdLoaderStrategyTests.m @@ -5,7 +5,8 @@ #import "GMAError.h" #import "XCTestCase+Convenience.h" #import "GMAIntegrationTestsConstants.h" - +#import "GADBannerViewBridge.h" +#import "UIViewController+TopController.h" #import "AppDelegate.h" static NSString *const kGMANullPlacementID = @"NULL_PLACEMENT_ID"; @@ -60,6 +61,10 @@ - (void)test_success_flow_for_loading_a_rewarded_ad { [self runSuccessTest: GADQueryInfoAdTypeRewarded]; } +- (void)test_success_flow_for_loading_a_banner { + [self runSuccessTest: GADQueryInfoAdTypeBanner]; +} + - (void)test_internal_error_loader_not_found { GMAAdMetaData *meta = [GMAAdMetaData new]; @@ -81,6 +86,10 @@ - (void)test_ad_load_rewarded_error { [self runTestAdLoadErrorForType: GADQueryInfoAdTypeRewarded]; } +- (void)test_ad_load_banner_error { + [self runTestAdLoadErrorForType: GADQueryInfoAdTypeBanner]; +} + - (void)runShowAdSuccessFlowForType: (GADQueryInfoAdType)type inViewController: (UIViewController *)vc { _sut = [GMAAdLoaderStrategy newWithRequestFactory: [GADRequestFactoryMock new] andDelegateFactory: _factoryMock]; @@ -197,8 +206,11 @@ - (void)runSuccessTest: (GADQueryInfoAdType)type { } - (GMAAdMetaData *)defaultMetaForType: (GADQueryInfoAdType)type { + if (type == GADQueryInfoAdTypeBanner) { + return self.bannerMetadata; + } + GMAAdMetaData *meta = [GMAAdMetaData new]; - meta.adString = @"adString"; meta.placementID = @"placement"; meta.adUnitID = kDefaultAdUnitID; @@ -208,6 +220,22 @@ - (GMAAdMetaData *)defaultMetaForType: (GADQueryInfoAdType)type { return meta; } +- (GMAAdMetaData *)bannerMetadata { + GMAAdMetaData *meta = [GMAAdMetaData new]; + + meta.placementID = @"placement"; + meta.queryID = @"queryID"; + meta.adUnitID = @"ca-app-pub-3940256099942544/2934735716"; + meta.type = GADQueryInfoAdTypeBanner; + meta.beforeLoad = ^(GADBaseAd *_Nullable ad) { + [(GADBannerViewBridge *)ad setRootViewController:[UIViewController uads_getTopController]]; + }; + meta.bannerSize = CGSizeMake(320, 50); + + return meta; +} + + - (id)delegatesFactory { return [GMADelegatesBaseFactory newWithEventSender: self.eventSender errorHandler: self.errorHandler]; diff --git a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/GMASCARSignalServiceMock.h b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/GMASCARSignalServiceMock.h new file mode 100644 index 00000000..c415f8b0 --- /dev/null +++ b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/GMASCARSignalServiceMock.h @@ -0,0 +1,15 @@ +#import "GMASCARSignalsReader.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GMASCARSignalServiceMock : NSObject + +@property (nonatomic, strong) NSArray *requestedSignals; + +- (void)callSuccessCompletion:(UADSSCARSignals *)result; +- (void)callErrorCompletion:(id)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/GMASCARSignalServiceMock.m b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/GMASCARSignalServiceMock.m new file mode 100644 index 00000000..2864ce49 --- /dev/null +++ b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/GMASCARSignalServiceMock.m @@ -0,0 +1,26 @@ +#import "GMASCARSignalServiceMock.h" + +@interface GMASCARSignalServiceMock() +@property (nonatomic, strong) UADSGMAScarSignalsCompletion *completion; +@end + +@implementation GMASCARSignalServiceMock + +- (void)getSCARSignals:(nonnull NSArray *)signalParameters completion:(nonnull UADSGMAScarSignalsCompletion *)completion { + self.requestedSignals = signalParameters; + self.completion = completion; +} + +- (nullable GADRequestBridge *)getAdRequestFor:(nonnull GMAAdMetaData *)meta error:(id _Nullable __autoreleasing * _Nullable)error { + return nil; +} + +- (void)callSuccessCompletion:(UADSSCARSignals *)result { + [self.completion success:result]; +} + +- (void)callErrorCompletion:(id)error { + [self.completion error:error]; +} + +@end diff --git a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/UADSSCARHeaderBiddingStrategyFactoryMock.h b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/UADSSCARHeaderBiddingStrategyFactoryMock.h deleted file mode 100644 index 28766729..00000000 --- a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/UADSSCARHeaderBiddingStrategyFactoryMock.h +++ /dev/null @@ -1,10 +0,0 @@ -#import -#import "UADSSCARHeaderBiddingStrategyFactory.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface UADSSCARHeaderBiddingStrategyFactoryMock : NSObject - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/UADSSCARHeaderBiddingStrategyFactoryMock.m b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/UADSSCARHeaderBiddingStrategyFactoryMock.m deleted file mode 100644 index cde0aefd..00000000 --- a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Mocks/UADSSCARHeaderBiddingStrategyFactoryMock.m +++ /dev/null @@ -1,9 +0,0 @@ -#import "UADSSCARHeaderBiddingStrategyFactoryMock.h" - -@implementation UADSSCARHeaderBiddingStrategyFactoryMock - -- (id _Nonnull)strategyWithOriginal:(id _Nonnull)original { - return nil; -} - -@end diff --git a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSHeaderBiddingTokenReaderWithSCARSignalsEagerStrategyTests.m b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSHeaderBiddingTokenReaderWithSCARSignalsEagerStrategyTests.m index 86cde65c..208a657b 100644 --- a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSHeaderBiddingTokenReaderWithSCARSignalsEagerStrategyTests.m +++ b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSHeaderBiddingTokenReaderWithSCARSignalsEagerStrategyTests.m @@ -36,8 +36,7 @@ - (void)setUp { _idGeneratorMock = [UADSUniqueIdGeneratorMock new]; _baseIdGeneratorMock = [UADSUniqueIdGeneratorMock new]; _configurationReaderMock = [UADSConfigurationReaderMock new]; - _configurationReaderMock.expectedStrategyType = UADSSCARHeaderBiddingStrategyTypeEager; - + _configMock = [UADSHeaderBiddingTokenReaderSCARSignalsConfig new]; _configMock.compressor = _compressor; diff --git a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategyTests.m b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategyTests.m deleted file mode 100644 index 57005c0b..00000000 --- a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategyTests.m +++ /dev/null @@ -1,140 +0,0 @@ -#import -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.h" -#import "UADSHeaderBiddingTokenAsyncReaderMock.h" -#import "UADSSCARHeaderBiddingStrategyFactoryMock.h" -#import "WebRequestFactoryMock.h" -#import "UADSSCARSignalReaderMock.h" -#import "UADSSCARSignalSenderMock.h" -#import "USRVBodyCompressorMock.h" -#import "UADSConfigurationReaderMock.h" -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsBaseStrategy+Internal.h" -#import "XCTestCase+Convenience.h" -#import "UADSUniqueIdGeneratorMock.h" -#import "UADSJSONCompressorMock.h" -#import "XCTestCase+SCARHBStrategies.h" - -@interface UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategyTests : XCTestCase -@property (nonatomic, strong) UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy *strategyToTest; -@property (nonatomic, strong) UADSHeaderBiddingTokenReaderSCARSignalsConfig* configMock; -@property (nonatomic, strong) UADSHeaderBiddingTokenAsyncReaderMock* originalMock; -@property (nonatomic, strong) UADSSCARSignalReaderMock* signalReaderMock; -@property (nonatomic, strong) UADSSCARSignalSenderMock* signalSenderMock; - -@end - -@implementation UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategyTests - -- (void)setUp { - _originalMock = [UADSHeaderBiddingTokenAsyncReaderMock new]; - _signalReaderMock = [UADSSCARSignalReaderMock new]; - _signalSenderMock = [UADSSCARSignalSenderMock new]; - _configMock = [UADSHeaderBiddingTokenReaderSCARSignalsConfig new]; - - _strategyToTest = [UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy decorateOriginal:_originalMock config:_configMock]; - _strategyToTest.scarSignalReader = _signalReaderMock; - _strategyToTest.scarSignalSender = _signalSenderMock; - _originalMock.expectedToken = @"tokenValue"; - _originalMock.shoudSkipCompletion = true; -} - -- (void)test_signals_recieved_and_signals_sent_before_token_returned { - __block UADSHeaderBiddingToken* blockToken; - [self checkWithStrategy:_strategyToTest signalSenderMock:_signalSenderMock original:_originalMock stepAfterGetTokenTriggered:^ { - [self.signalReaderMock triggerSignalCompletion]; - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Signals should not have been sent until both token and signals received"); - } getTokenReturn:^ (UADSHeaderBiddingToken *_Nullable token) { - blockToken = token; - }]; - - [self checkSenderCallHistoryCountIsOne:self.signalSenderMock withUUID:blockToken.uuidString]; -} - - -- (void)test_signals_received_and_signals_sent_after_token_recieved { - __block UADSHeaderBiddingToken* blockToken; - [self checkWithStrategy:_strategyToTest signalSenderMock:_signalSenderMock original:_originalMock stepAfterGetTokenTriggered:^ { } getTokenReturn:^ (UADSHeaderBiddingToken *_Nullable token) { - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Signals should not have been sent until both token and signals received"); - [self.signalReaderMock triggerSignalCompletion]; - blockToken = token; - }]; - [self checkSenderCallHistoryCountIsOne:self.signalSenderMock withUUID:blockToken.uuidString]; -} - -- (void)test_signals_sent_as_soon_as_received_remote_token_and_signals { - _originalMock.tokenType = kUADSTokenRemote; - __block UADSHeaderBiddingToken* blockToken; - [self checkWithStrategy:_strategyToTest signalSenderMock:_signalSenderMock original:_originalMock stepAfterGetTokenTriggered:^ { - [self.signalReaderMock triggerSignalCompletion]; - - } getTokenReturn:^ (UADSHeaderBiddingToken *_Nullable token) { - [self hasValueSamePrefix:token.value withUUID:token.uuidString]; - blockToken = token; - }]; - [self checkSenderCallHistoryCountIsOne:self.signalSenderMock withUUID:blockToken.uuidString]; -} - -- (void)test_nil_signals_sent_as_soon_as_received_signals_and_token { - _signalReaderMock.signals = nil; - __block UADSHeaderBiddingToken* blockToken; - [self checkWithStrategy:_strategyToTest signalSenderMock:_signalSenderMock original:_originalMock stepAfterGetTokenTriggered:^ { - [self.signalReaderMock triggerSignalCompletion]; - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Signals should not have been sent until both token and signals received"); - } getTokenReturn:^ (UADSHeaderBiddingToken *_Nullable token) { - blockToken = token; - }]; - [self checkSenderCallHistoryCountIsOne:self.signalSenderMock withUUID:blockToken.uuidString]; -} - -- (void)test_signals_not_sent_received_nil_token { - _originalMock.expectedToken = nil; - [self checkWithStrategy:_strategyToTest original:_originalMock stepAfterGetTokenTriggered:^ { - [self.signalReaderMock triggerSignalCompletion]; - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Signals should not have been sent until both token and signals received"); - } getTokenReturn:^ (UADSHeaderBiddingToken *_Nullable token) { }]; - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Signals should not have been sent until since token is not valid"); -} - -- (void)test_x_signals_recieved_and_signals_sent_before_x_token_returned_multithread { - int iterations = 500; - self.signalReaderMock.shouldAutoComplete = true; - self.originalMock.shoudSkipCompletion = false; - [self asyncExecuteTimes:iterations block:^(XCTestExpectation *_Nonnull expectation, int index) { - [self.strategyToTest getToken:^(UADSHeaderBiddingToken *_Nullable token) { - [expectation fulfill]; - }]; - }]; - XCTAssertEqual(self.signalSenderMock.callHistory.count,iterations, @"Signals should have the same count as the iterations"); -} - -- (void)test_x_signals_sent_same_thread { - NSMutableArray* tokens = [NSMutableArray new]; - NSMutableArray* tokenValues = [NSMutableArray new]; - XCTestExpectation *exp = self.defaultExpectation; - int iterations = 50; - exp.expectedFulfillmentCount = iterations; - for (int i=0; i -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.h" -#import "UADSHeaderBiddingTokenAsyncReaderMock.h" -#import "UADSSCARHeaderBiddingStrategyFactoryMock.h" -#import "WebRequestFactoryMock.h" -#import "UADSSCARSignalReaderMock.h" -#import "UADSSCARSignalSenderMock.h" -#import "USRVBodyCompressorMock.h" -#import "UADSConfigurationReaderMock.h" -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsBaseStrategy+Internal.h" -#import "XCTestCase+Convenience.h" -#import "UADSUniqueIdGeneratorMock.h" -#import "UADSJSONCompressorMock.h" -#import "XCTestCase+SCARHBStrategies.h" - -@interface UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategyTests : XCTestCase -@property (nonatomic, strong) UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy *strategyToTest; -@property (nonatomic, strong) UADSHeaderBiddingTokenReaderSCARSignalsConfig* configMock; -@property (nonatomic, strong) UADSHeaderBiddingTokenAsyncReaderMock* originalMock; -@property (nonatomic, strong) UADSSCARSignalReaderMock* signalReaderMock; -@property (nonatomic, strong) UADSSCARSignalSenderMock* signalSenderMock; - -@end - -@implementation UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategyTests - -- (void)setUp { - _originalMock = [UADSHeaderBiddingTokenAsyncReaderMock new]; - _signalReaderMock = [UADSSCARSignalReaderMock new]; - _signalSenderMock = [UADSSCARSignalSenderMock new]; - _configMock = [UADSHeaderBiddingTokenReaderSCARSignalsConfig new]; - - _strategyToTest = [UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy decorateOriginal:_originalMock config:_configMock]; - _strategyToTest.scarSignalReader = _signalReaderMock; - _strategyToTest.scarSignalSender = _signalSenderMock; - _originalMock.expectedToken = @"tokenValue"; - _originalMock.shoudSkipCompletion = true; -} - -- (void)test_signals_recieved_and_signals_sent_before_token_returned { - [self checkWithStrategy:_strategyToTest original:_originalMock stepAfterGetTokenTriggered:^ { - [self.signalReaderMock triggerSignalCompletion]; - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Signals should not have been sent until both token and signals received"); - } getTokenReturn:^ (UADSHeaderBiddingToken *_Nullable token) { - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Signals should not have been sent until both token and signals received"); - [self.signalReaderMock triggerSignalCompletion]; - [self checkSenderCallHistoryCountIsOne:self.signalSenderMock withUUID:token.uuidString]; - }]; - -} - - -- (void)test_signals_received_and_signals_sent_after_token_recieved { - [self checkWithStrategy:_strategyToTest original:_originalMock stepAfterGetTokenTriggered:^ { } getTokenReturn:^ (UADSHeaderBiddingToken *_Nullable token) { - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Signals should not have been sent until both token and signals received"); - [self.signalReaderMock triggerSignalCompletion]; - [self checkSenderCallHistoryCountIsOne:self.signalSenderMock withUUID:token.uuidString]; - }]; -} - -- (void)test_signals_sent_as_soon_as_received_remote_token_and_signals { - _originalMock.tokenType = kUADSTokenRemote; - [self checkWithStrategy:_strategyToTest original:_originalMock stepAfterGetTokenTriggered:^ { } getTokenReturn:^ (UADSHeaderBiddingToken *_Nullable token) { - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Signals should not have been sent until both token and signals received"); - [self.signalReaderMock triggerSignalCompletion]; - [self hasValueSamePrefix:token.value withUUID:token.uuidString]; - [self checkSenderCallHistoryCountIsOne:self.signalSenderMock withUUID:token.uuidString]; - }]; -} - -- (void)test_nil_signals_sent_as_soon_as_signal_and_token_received { - _signalReaderMock.signals = nil; - [self checkWithStrategy:_strategyToTest original:_originalMock stepAfterGetTokenTriggered:^ { } getTokenReturn:^ (UADSHeaderBiddingToken *_Nullable token) { - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Signals should not have been sent until both token and signals received"); - [self.signalReaderMock triggerSignalCompletion]; - [self checkSenderCallHistoryCountIsOne:self.signalSenderMock withUUID:token.uuidString]; - }]; -} - -- (void)test_signals_not_sent_as_received_nil_token { - _originalMock.expectedToken = nil; - [self checkWithStrategy:_strategyToTest original:_originalMock stepAfterGetTokenTriggered:^ { - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Signals should not have been sent until both token and signals received"); - } getTokenReturn:^ (UADSHeaderBiddingToken *_Nullable token) { - [self.signalReaderMock triggerSignalCompletion]; - XCTAssertEqual(self.signalSenderMock.callHistory.count,0, @"Token is invalid, no point sending signals"); - }]; -} - -- (void)test_x_signals_recieved_and_signals_sent_before_x_token_returned_multithread { - int iterations = 500; - self.signalReaderMock.shouldAutoComplete = true; - self.originalMock.shoudSkipCompletion = false; - [self asyncExecuteTimes:iterations block:^(XCTestExpectation *_Nonnull expectation, int index) { - [self.strategyToTest getToken:^(UADSHeaderBiddingToken *_Nullable token) { - [expectation fulfill]; - }]; - }]; - XCTAssertEqual(self.signalSenderMock.callHistory.count,iterations, @"Signals should have the same count as the iterations"); -} - -- (void)test_x_signals_sent_same_thread { - NSMutableArray* tokens = [NSMutableArray new]; - NSMutableArray* tokenValues = [NSMutableArray new]; - int iterations = 50; - XCTestExpectation *exp = self.defaultExpectation; - exp.expectedFulfillmentCount = iterations; - for (int i=0; i -#import "UADSHeaderBiddingTokenReaderSCARSignalsConfig.h" -#import "UADSSCARHeaderBiddingFetchSendStrategyFactory.h" -#import "UADSConfigurationReaderMock.h" -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsEagerStrategy.h" -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy.h" -#import "UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy.h" -#import "USRVSdkProperties.h" - -@interface UADSSCARHeaderBiddingFetchSendStrategyFactoryTests : XCTestCase -@property (nonatomic, strong) UADSHeaderBiddingTokenReaderSCARSignalsConfig* configMock; -@property (nonatomic, strong) UADSSCARHeaderBiddingFetchSendStrategyFactory* strategyFactory; -@property (nonatomic, strong) UADSConfigurationCRUDBase* configurationReader; - -@end - -@implementation UADSSCARHeaderBiddingFetchSendStrategyFactoryTests - -- (void)setUp { - _configMock = [UADSHeaderBiddingTokenReaderSCARSignalsConfig new]; - _configurationReader = [UADSConfigurationCRUDBase new]; - _strategyFactory = [UADSSCARHeaderBiddingFetchSendStrategyFactory new]; - - _configMock.configurationReader = _configurationReader; - _configMock.strategyFactory = _strategyFactory; - _strategyFactory.config = _configMock; -} - -- (void)test_eager_set_in_experiments { - [self saveLocalConfigWithObject:false experiments:[self eagerExperimentWithObject]]; - id strategy = [_strategyFactory strategyWithOriginal:nil]; - XCTAssertEqual([strategy class], [UADSHeaderBiddingTokenReaderWithSCARSignalsEagerStrategy class], @"Eager set, should return eager implementation"); -} - -- (void)test_lazy_set_in_experiments { - [self saveLocalConfigWithObject:false experiments:[self lazyExperimentWithObject]]; - id strategy = [_strategyFactory strategyWithOriginal:nil]; - XCTAssertEqual([strategy class], [UADSHeaderBiddingTokenReaderWithSCARSignalsLazyStrategy class], @"Lazy set, should return eager implementation"); -} - -- (void)test_hybrid_set_in_experiments { - [self saveLocalConfigWithObject:false experiments:[self hybridExperimentWithObject]]; - id strategy = [_strategyFactory strategyWithOriginal:nil]; - XCTAssertEqual([strategy class], [UADSHeaderBiddingTokenReaderWithSCARSignalsHybridStrategy class], @"Hybrid set, should return eager implementation"); -} - -- (void)test_empty_set_in_experiments { - [self saveLocalConfigWithObject:false experiments:[self emptyExperimentWithObject]]; - id strategy = [_strategyFactory strategyWithOriginal:nil]; - XCTAssertEqual([strategy class], nil, @"no experiment set, should return no implementation"); -} - -- (void)test_no_experiment_set_in_experiments { - [self saveLocalConfigWithObject:false experiments:[self noExperimentWithObject]]; - id strategy = [_strategyFactory strategyWithOriginal:nil]; - XCTAssertEqual([strategy class], nil, @"no experiment set, should return no implementation"); -} - -- (void)test_nil_experiment_set_in_experiments { - [self saveLocalConfigWithObject:false experiments:[self noExperimentWithNilObject]]; - id strategy = [_strategyFactory strategyWithOriginal:nil]; - XCTAssertEqual([strategy class], nil, @"no experiment set, should return no implementation"); -} - -- (void)saveLocalConfigWithObject: (BOOL)withObject experiments:(NSDictionary *)localExperiments { - USRVConfiguration *localConfiguration = [self mockConfigWithUrl: self.localWebViewUrl - experiments: localExperiments - experimentObject: withObject]; - - [[localConfiguration toJson] writeToFile: [USRVSdkProperties getLocalConfigFilepath] - atomically: YES]; -} - -- (USRVConfiguration *)mockConfigWithUrl: (NSString *)url experiments: (NSDictionary *)experiments experimentObject: (BOOL)isObject { - NSString *experimentsKey = isObject ? kUnityServicesConfigValueExperimentsObject : kUnityServicesConfigValueExperiments; - USRVConfiguration *configuration = [USRVConfiguration newFromJSON: @{ - kUnityServicesConfigValueUrl: url, - experimentsKey: experiments ?: @{}, - kUnityServicesConfigValueSource: self.source - }]; - - return configuration; -} - -- (NSDictionary *)eagerExperimentWithObject { - return @{ - @"scar_bm": @{ - @"value": @"eag" - } - }; -} - -- (NSDictionary *)lazyExperimentWithObject { - return @{ - @"scar_bm": @{ - @"value": @"laz" - } - }; -} - -- (NSDictionary *)hybridExperimentWithObject { - return @{ - @"scar_bm": @{ - @"value": @"hyb" - } - }; -} - -- (NSDictionary *)emptyExperimentWithObject { - return @{ - @"scar_bm": @{ - } - }; -} - -- (NSDictionary *)noExperimentWithObject { - return @{ - }; -} - -- (NSDictionary *)noExperimentWithNilObject { - return nil; -} - -- (NSString *)localWebViewUrl { - return @"local-fake-url"; -} - -- (NSString *)source { - return @"srvc"; -} - -@end diff --git a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSSCARWebRequestSignalSenderTests.m b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSSCARWebRequestSignalSenderTests.m index 5afec0bd..30d289be 100644 --- a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSSCARWebRequestSignalSenderTests.m +++ b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/Strategies/UADSSCARWebRequestSignalSenderTests.m @@ -1,6 +1,5 @@ #import #import "UADSHeaderBiddingTokenReaderSCARSignalsConfig.h" -#import "UADSSCARHeaderBiddingFetchSendStrategyFactory.h" #import "UADSConfigurationReaderMock.h" #import "UADSSCARWebRequestSignalSender.h" #import "USRVSdkProperties.h" @@ -35,27 +34,50 @@ - (void)setUp { } - (void)test_send_valid_signals_and_valid_uuid { - [self checkSentRequestValuesWithRewardedValue:@"rewarded" interstitialValue:@"interstitial" uuidValue:@"uuid"]; + [self checkSentRequestValuesWithRewardedValue:@"rewarded" + interstitialValue:@"interstitial" + bannerValue:@"banner" + uuidValue:@"uuid"]; } - (void)test_send_one_valid_rv_signal_and_valid_uuid { - [self checkSentRequestValuesWithRewardedValue:@"rewarded" interstitialValue:nil uuidValue:@"uuid"]; + [self checkSentRequestValuesWithRewardedValue:@"rewarded" + interstitialValue:nil + bannerValue:nil + uuidValue:@"uuid"]; } - (void)test_send_one_valid_int_signal_and_valid_uuid { - [self checkSentRequestValuesWithRewardedValue:nil interstitialValue:@"interstitial" uuidValue:@"uuid"]; + [self checkSentRequestValuesWithRewardedValue:nil + interstitialValue:@"interstitial" + bannerValue:nil + uuidValue:@"uuid"]; +} + +- (void)test_send_one_valid_bn_signal_and_valid_uuid { + [self checkSentRequestValuesWithRewardedValue:nil + interstitialValue:nil + bannerValue:@"banner" + uuidValue:@"uuid"]; } - (void)test_send_nil_signals_and_valid_uuid { - [self checkNoSentRequestValuesWithRewardedValue:nil interstitialValue:nil uuidValue:@"uuid"]; + [self checkNoSentRequestValuesWithSignals: nil + uuidValue: @"uuid"]; } - (void)test_send_valid_signals_and_nil_uuid { - [self checkNoSentRequestValuesWithRewardedValue:@"rewarded" interstitialValue:@"interstitial" uuidValue:nil]; + [self checkNoSentRequestValuesWithSignals: [self signalsWithRewardedValue:@"rewarded" + interstitialValue:@"interstitial" + bannerValue:@"banner"] + uuidValue: nil]; } - (void)test_send_valid_signals_and_empty_uuid { - [self checkNoSentRequestValuesWithRewardedValue:@"rewarded" interstitialValue:@"interstitial" uuidValue:@""]; + [self checkNoSentRequestValuesWithSignals: [self signalsWithRewardedValue:@"rewarded" + interstitialValue:@"interstitial" + bannerValue:@"banner"] + uuidValue: @""]; } - (void)test_send_nil_signal_reference_and_valid_uuid { @@ -63,10 +85,14 @@ - (void)test_send_nil_signal_reference_and_valid_uuid { XCTAssertEqual(self.requestFactoryMock.createdRequests.count, 0); } -- (void)checkSentRequestValuesWithRewardedValue:(NSString*)rewardedValue interstitialValue:(NSString*)interstitialValue uuidValue:(NSString*)uuidValue { +- (void)checkSentRequestValuesWithRewardedValue:(NSString*)rewardedValue + interstitialValue:(NSString*)interstitialValue + bannerValue:(NSString*)bannerValue + uuidValue:(NSString*)uuidValue { NSMutableDictionary* signals = [NSMutableDictionary new]; [signals uads_setValueIfNotNil:rewardedValue forKey:UADSScarRewardedSignal]; [signals uads_setValueIfNotNil:interstitialValue forKey:UADSScarInterstitialSignal]; + [signals uads_setValueIfNotNil:bannerValue forKey:UADSScarBannerSignal]; [self.signalSender sendSCARSignalsWithUUIDString:uuidValue signals:signals isAsync:true]; @@ -77,16 +103,24 @@ - (void)checkSentRequestValuesWithRewardedValue:(NSString*)rewardedValue interst XCTAssertEqualObjects(mockRequestBodyDictionary[UADSScarUUIDKey], uuidValue); XCTAssertEqualObjects(mockRequestBodyDictionary[UADSScarRewardedKey], rewardedValue); XCTAssertEqualObjects(mockRequestBodyDictionary[UADSScarInterstitialKey], interstitialValue); + XCTAssertEqualObjects(mockRequestBodyDictionary[UADSScarBannerKey], bannerValue); XCTAssertEqualObjects(mockRequestBodyDictionary[UADSScarIdfiKey], _idfiReaderMock.expectedIdfi); } -- (void)checkNoSentRequestValuesWithRewardedValue:(NSString*)rewardedValue interstitialValue:(NSString*)interstitialValue uuidValue:(NSString*)uuidValue { +- (void)checkNoSentRequestValuesWithSignals: (NSDictionary *)signals + uuidValue:(NSString*)uuidValue { + [self.signalSender sendSCARSignalsWithUUIDString:uuidValue signals:signals isAsync:true]; + XCTAssertEqual(self.requestFactoryMock.createdRequests.count, 0); +} + +- (NSDictionary *)signalsWithRewardedValue:(NSString*)rewardedValue + interstitialValue:(NSString*)interstitialValue + bannerValue:(NSString*)bannerValue { NSMutableDictionary* signals = [NSMutableDictionary new]; [signals uads_setValueIfNotNil:rewardedValue forKey:UADSScarRewardedSignal]; [signals uads_setValueIfNotNil:interstitialValue forKey:UADSScarInterstitialSignal]; - - [self.signalSender sendSCARSignalsWithUUIDString:uuidValue signals:signals isAsync:true]; - XCTAssertEqual(self.requestFactoryMock.createdRequests.count, 0); + [signals uads_setValueIfNotNil:bannerValue forKey:UADSScarBannerSignal]; + return signals; } - (NSDictionary*)stringToDictionary:(NSString*)stringValue { diff --git a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/UADSSCARRawSignalsReaderTests.m b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/UADSSCARRawSignalsReaderTests.m new file mode 100644 index 00000000..6471c371 --- /dev/null +++ b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/GMASCARHeaderBidding/UADSSCARRawSignalsReaderTests.m @@ -0,0 +1,80 @@ +#import +#import "UADSSCARRawSignalsReader.h" +#import "GMASCARSignalServiceMock.h" +#import "UADSSCARSignalIdentifiers.h" +#import "UADSConfigurationReaderMock.h" + +@interface UADSSCARRawSignalsReaderTests : XCTestCase +@property(nonatomic, strong) UADSSCARRawSignalsReader* scarSignalReader; +@property(nonatomic, strong) UADSHeaderBiddingTokenReaderSCARSignalsConfig *configMock; +@property(nonatomic, strong) GMASCARSignalServiceMock *signalsMock; +@property(nonatomic, strong) UADSConfigurationReaderMock *configReaderMock; +@end + +@implementation UADSSCARRawSignalsReaderTests + +- (void)setUp { + _scarSignalReader = [UADSSCARRawSignalsReader new]; + _configMock = [UADSHeaderBiddingTokenReaderSCARSignalsConfig new]; + _signalsMock = [GMASCARSignalServiceMock new]; + _configReaderMock = [UADSConfigurationReaderMock new]; + _configMock.signalService = _signalsMock; + _configMock.configurationReader = _configReaderMock; + _scarSignalReader.config = _configMock; +} + +- (void)test_does_not_collect_banner_signals_if_not_enabled { + [self executeWithBanner: NO completeWith: @{} result: nil]; +} + +- (void)test_collects_banner_signals_if_enabled { + [self executeWithBanner: YES completeWith: @{} result: nil]; +} + +- (void)test_returns_nil_if_no_requested_signals_collected { + NSDictionary *expected = @{ UADSScarBannerSignal: @"signal" }; + [self executeWithBanner: NO completeWith: expected result: nil]; +} + +- (void)test_returns_signals_if_collected_banner { + NSDictionary *expected = @{ UADSScarBannerSignal: @"signal" }; + [self executeWithBanner: YES completeWith: expected result: expected]; +} + +- (void)test_returns_signals_if_collected_with_banner_disabled { + NSDictionary *expected = @{ UADSScarRewardedSignal: @"signal", UADSScarInterstitialSignal: @"signal"}; + [self executeWithBanner: NO completeWith: expected result: expected]; +} + +- (void)test_returns_signals_if_collected_with_banner_enabled { + NSDictionary *expected = @{ UADSScarRewardedSignal: @"signal", UADSScarInterstitialSignal: @"signal"}; + [self executeWithBanner: YES completeWith: expected result: expected]; +} + +- (void)executeWithBanner: (BOOL)banner completeWith:(UADSSCARSignals *)completion result:(UADSSCARSignals *)expectedResult { + _configReaderMock.experiments = @{ @"scar_bn": @(banner) }; + + XCTestExpectation *exp = [self expectationWithDescription:@"signals"]; + [_scarSignalReader requestSCARSignalsWithIsAsync:true + completion:^(UADSSCARSignals * _Nullable result) { + XCTAssertEqualObjects(result, expectedResult); + [exp fulfill]; + }]; + [_signalsMock callSuccessCompletion: completion]; + [self waitForExpectations:@[exp] timeout:1.0]; + + XCTAssertEqualObjects(_signalsMock.requestedSignals, [self signalsToCollectWithBanner: banner]); +} + +- (NSArray*)signalsToCollectWithBanner:(BOOL)withBanner { + NSMutableArray *params = [NSMutableArray arrayWithArray:@[ + [[UADSScarSignalParameters alloc] initWithPlacementId:UADSScarInterstitialSignal adFormat:GADQueryInfoAdTypeInterstitial], + [[UADSScarSignalParameters alloc] initWithPlacementId:UADSScarRewardedSignal adFormat: GADQueryInfoAdTypeRewarded] + ]]; + if (withBanner) { + [params addObject:[[UADSScarSignalParameters alloc] initWithPlacementId:UADSScarBannerSignal adFormat:GADQueryInfoAdTypeBanner]]; + } + return params; +} + +@end diff --git a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/UADSAsyncTokenWithPrivacyIntegrationTests.m b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/UADSAsyncTokenWithPrivacyIntegrationTests.m index d6756830..0d47fe4c 100644 --- a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/UADSAsyncTokenWithPrivacyIntegrationTests.m +++ b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/UADSAsyncTokenWithPrivacyIntegrationTests.m @@ -136,7 +136,7 @@ - (void)validateIfTokenContextual: (UADSHeaderBiddingToken *)token isContextual: } - (NSArray *)contextualTokenKeys { - return [_infoTester allExpectedKeysWithNonBehavioral: false]; + return [[_infoTester allExpectedKeysWithNonBehavioral: false] arrayByAddingObject: @"tid"]; } - (NSArray *)behavioralTokenKeys { diff --git a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/UADSHeaderBiddingTokenIntegrationTestCase.m b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/UADSHeaderBiddingTokenIntegrationTestCase.m index b2fd7773..cfe76511 100644 --- a/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/UADSHeaderBiddingTokenIntegrationTestCase.m +++ b/Tests/UnityAdsTests/Core/Device/HeaderBiddingTokenReader/UADSHeaderBiddingTokenIntegrationTestCase.m @@ -97,8 +97,8 @@ - (void)test_if_state_is_not_initialized_return_null_token_even_if_queue_is_not_ - (void)test_adds_prefix_to_native_generated_token { self.nativeGeneratorMock = nil; self.builder.deviceInfoReader = self.readerMock; - // encoded device info: @{ @"test": @"info" }; - NSString *tokenString = @"1:H4sIAAAAAAAAE6tWKkktLlGyUsrMS8tXqgUAIuq+TA8AAAA="; + // encoded device info: @{ @"test": @"info", @"tid": @"uuid" }; + NSString *tokenString = @"1:H4sIAAAAAAAAE6tWKslMUbJSKi0FUjpKJanFJUBeZl5avlItAPQMbt8cAAAA"; UADSUniqueIdGeneratorMock *idGeneratorMock = [UADSUniqueIdGeneratorMock new]; idGeneratorMock.expectedValue = @"uuid"; _builder.uniqueIdGenerator = idGeneratorMock; diff --git a/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABannerViewDelegateProxy/GMABannerViewDelegateProxyTests.m b/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABannerViewDelegateProxy/GMABannerViewDelegateProxyTests.m new file mode 100644 index 00000000..269a3e4b --- /dev/null +++ b/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABannerViewDelegateProxy/GMABannerViewDelegateProxyTests.m @@ -0,0 +1,93 @@ +#import +#import "GMABaseAdDelegateProxyTests.h" +#import "GMATestCommonConstants.h" +#import "GMABannerViewDelegateProxy.h" +#import "GMABannerWebViewEvent.h" +#import "GMALoaderBase.h" + +@interface GMABannerViewDelegateProxyTests : GMABaseAdDelegateProxyTests +@end + +@implementation GMABannerViewDelegateProxyTests + +- (void)test_calls_success_completion_block_on_did_receive_ad { + XCTestExpectation *exp = [self expectationWithDescription:@"load"]; + id successHandler = ^(id _Nullable obj) { + XCTAssertNotNil(obj); + [exp fulfill]; + }; + + id errorHandler = ^(id _Nonnull error) { + XCTFail(@"Should not call errorHandler"); + [exp fulfill]; + }; + + UADSAnyCompletion *anyCompletion = [UADSAnyCompletion newWithSuccess: successHandler + andError: errorHandler]; + + GMABannerViewDelegateProxy *delegateToTest = [self defaultProxyToTestWithCompletion:anyCompletion]; + [delegateToTest bannerViewDidReceiveAd:self.fakeAdObject]; + [self waitForExpectations:@[exp] timeout: 1.0]; +} + +- (void)test_calls_error_completion_block_on_failure { + XCTestExpectation *exp = [self expectationWithDescription:@"load"]; + NSError *fakeError = [[NSError alloc] initWithDomain: @"domain " + code: 100 + userInfo: nil]; + id successHandler = ^(id _Nullable obj) { + XCTFail(@"Should not call successHandler"); + [exp fulfill]; + }; + + id errorHandler = ^(id _Nonnull error) { + XCTAssertEqualObjects(error.errorDomain, kGMAEventName); + XCTAssertEqual(error.errorCode.intValue, fakeError.code); + [exp fulfill]; + }; + + UADSAnyCompletion *anyCompletion = [UADSAnyCompletion newWithSuccess: successHandler + andError: errorHandler]; + + GMABannerViewDelegateProxy *delegateToTest = [self defaultProxyToTestWithCompletion:anyCompletion]; + [delegateToTest bannerView:self.fakeAdObject didFailToReceiveAdWithError:fakeError]; + [self waitForExpectations:@[exp] timeout: 1.0]; +} + +- (void)test_sends_impression_and_click_events { + + GMABannerViewDelegateProxy *delegateToTest = [self defaultProxyToTestWithCompletion: [UADSAnyCompletion new]]; + [delegateToTest bannerViewDidRecordImpression: self.fakeAdObject]; + [delegateToTest bannerViewDidRecordClick: self.fakeAdObject]; + GMAAdMetaData *meta = self.defaultMeta; + NSArray *expectedEvents = @[ + [GMABannerWebViewEvent newBannerImpressionWithMeta:meta], + [GMABannerWebViewEvent newBannerClickedWithMeta:meta] + ]; + + [self validateExpectedEvents: expectedEvents]; + [self validateExpectedDefaultParamsInEvents: expectedEvents]; +} + +- (GMABannerViewDelegateProxy *)defaultProxyToTestWithCompletion:(UADSLoadAdCompletion *)completion { + return [self.delegatesFactory bannerDelegate: self.defaultMeta + andCompletion: completion]; +} + +- (GMAAdMetaData *)defaultMeta { + GMAAdMetaData *meta = [GMAAdMetaData new]; + + meta.bannerAdId = kGMABannerAdId; + meta.placementID = kFakePlacementID; + meta.queryID = kGMAQueryID; + meta.type = GADQueryInfoAdTypeBanner; + meta.beforeLoad = ^(GADBaseAd *_Nullable ad) {}; + return meta; +} + +- (NSArray *)expectedParams { + return @[kGMABannerAdId]; +} + + +@end diff --git a/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABaseAdDelegateProxyTests.h b/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABaseAdDelegateProxyTests.h new file mode 100644 index 00000000..e68e1d72 --- /dev/null +++ b/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABaseAdDelegateProxyTests.h @@ -0,0 +1,19 @@ +#import +#import "GMADelegatesFactory.h" +#import "GMAWebViewEvent.h" +#import "USRVWebViewAppMock.h" +#import "UADSTimerFactoryMock.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface GMABaseAdDelegateProxyTests : XCTestCase +@property (nonatomic, strong) USRVWebViewAppMock *webAppMock; +@property (nonatomic, strong) UADSTimerFactoryMock *timerFactoryMock; + +- (id)delegatesFactory; +- (id)fakeAdObject; +- (void)validateExpectedEvents: (NSArray *)expectedEvents; +- (void)validateExpectedDefaultParamsInEvents: (NSArray *)expectedEvents; +@end + +NS_ASSUME_NONNULL_END diff --git a/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABaseAdDelegateProxyTests.m b/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABaseAdDelegateProxyTests.m new file mode 100644 index 00000000..84e01dad --- /dev/null +++ b/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMABaseAdDelegateProxyTests.m @@ -0,0 +1,65 @@ +#import "GMABaseAdDelegateProxyTests.h" +#import "XCTestCase+Convenience.h" +#import "GMALoaderBase.h" +#import "UADSWebViewErrorHandler.h" +#import "NSArray+Map.h" +#import "GMAWebViewEvent.h" + +@implementation GMABaseAdDelegateProxyTests + +- (void)setUp { + [self resetUnityAds]; + _timerFactoryMock = [UADSTimerFactoryMock new]; + _webAppMock = [USRVWebViewAppMock new]; + [USRVWebViewApp setCurrentApp: _webAppMock]; +} + +- (void)tearDown { + _webAppMock = nil; + [USRVWebViewApp setCurrentApp: _webAppMock]; + [self resetUnityAds]; +} + + +- (NSArray *)expectedParams { + return @[]; +} + +- (id)delegatesFactory { + ideventSender = [UADSWebViewEventSenderBase new]; + + iderrorHandler = [UADSWebViewErrorHandler newWithEventSender: eventSender]; + + return [GMADelegatesBaseFactory newWithEventSender: eventSender + errorHandler: errorHandler + timerFactory: _timerFactoryMock]; +} + +- (void)validateExpectedEvents: (NSArray *)expectedEvents { + NSArray *expectedEventNames = [expectedEvents uads_mapObjectsUsingBlock: ^id _Nonnull (GMAWebViewEvent *_Nonnull obj) { + return obj.eventName; + }]; + + NSArray *expectedCategoryNames = [expectedEvents uads_mapObjectsUsingBlock: ^id _Nonnull (GMAWebViewEvent *_Nonnull obj) { + return obj.categoryName; + }]; + + XCTAssertEqualObjects(_webAppMock.eventNames, expectedEventNames); + XCTAssertEqualObjects(_webAppMock.categoryNames, expectedCategoryNames); +} + +- (void)validateExpectedDefaultParamsInEvents: (NSArray *)expectedEvents { + NSArray *expectedParams = [NSArray new]; + + for (id event in expectedEvents) { + expectedParams = [expectedParams arrayByAddingObject: self.expectedParams]; // creating expected array since default params are the same + } + + XCTAssertEqualObjects(_webAppMock.params, expectedParams); +} + +- (id)fakeAdObject { + return [NSObject new]; +} + +@end diff --git a/Tests/UnityAdsTests/GMAInfo/GMAInterstitialAdDelegateProxy/GMAInterstitialAdDelegateProxyTests.m b/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMAInterstitialAdDelegateProxy/GMAInterstitialAdDelegateProxyTests.m similarity index 85% rename from Tests/UnityAdsTests/GMAInfo/GMAInterstitialAdDelegateProxy/GMAInterstitialAdDelegateProxyTests.m rename to Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMAInterstitialAdDelegateProxy/GMAInterstitialAdDelegateProxyTests.m index f8974334..da2da70c 100644 --- a/Tests/UnityAdsTests/GMAInfo/GMAInterstitialAdDelegateProxy/GMAInterstitialAdDelegateProxyTests.m +++ b/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMAInterstitialAdDelegateProxy/GMAInterstitialAdDelegateProxyTests.m @@ -1,39 +1,17 @@ #import -#import "USRVWebViewAppMock.h" -#import "USRVWebViewApp.h" +#import "GMABaseAdDelegateProxyTests.h" #import "GMAInterstitialAdDelegateProxy.h" -#import "GMAWebViewEvent.h" -#import "NSArray+Map.h" #import "XCTestCase+Convenience.h" #import "NSError+UADSError.h" -#import "GMADelegatesFactory.h" #import "UADSWebViewErrorHandler.h" #import "GMAError.h" #import "GMATestCommonConstants.h" -#import "UADSRepeatableTimerMock.h" -#import "UADSTimerFactoryMock.h" -#import "XCTestCase+Convenience.h" -@interface GMAInterstitialAdDelegateProxyTests : XCTestCase -@property (nonatomic, strong) USRVWebViewAppMock *webAppMock; -@property (nonatomic, strong) UADSTimerFactoryMock *timerFactoryMock; +@interface GMAInterstitialAdDelegateProxyTests : GMABaseAdDelegateProxyTests @end @implementation GMAInterstitialAdDelegateProxyTests -- (void)setUp { - [self resetUnityAds]; - _timerFactoryMock = [UADSTimerFactoryMock new]; - _webAppMock = [USRVWebViewAppMock new]; - [USRVWebViewApp setCurrentApp: _webAppMock]; -} - -- (void)tearDown { - _webAppMock = nil; - [USRVWebViewApp setCurrentApp: _webAppMock]; - [self resetUnityAds]; -} - - (void)test_will_present_for_the_first_time_triggers_events { GMAInterstitialAdDelegateProxy *delegateToTest = self.defaultProxyToTest; @@ -269,7 +247,7 @@ - (void)test_did_fail_sends_id_error_and_code { [self validateExpectedEvents: expectedEvents]; - NSArray *receivedParams = _webAppMock.params[0]; + NSArray *receivedParams = self.webAppMock.params[0]; XCTAssertEqualObjects(receivedParams[0], kFakePlacementID); XCTAssertEqualObjects(receivedParams[1], kGMAQueryID); @@ -281,33 +259,6 @@ - (void)simulateQuartilesPlayed: (NSInteger)count { [self.timerFactoryMock.lastTimerMock fire: count]; } -- (void)validateExpectedEvents: (NSArray *)expectedEvents { - NSArray *expectedEventNames = [expectedEvents uads_mapObjectsUsingBlock: ^id _Nonnull (GMAWebViewEvent *_Nonnull obj) { - return obj.eventName; - }]; - - NSArray *expectedCategoryNames = [expectedEvents uads_mapObjectsUsingBlock: ^id _Nonnull (GMAWebViewEvent *_Nonnull obj) { - return obj.categoryName; - }]; - - XCTAssertEqualObjects(_webAppMock.eventNames, expectedEventNames); - XCTAssertEqualObjects(_webAppMock.categoryNames, expectedCategoryNames); -} - -- (void)validateExpectedDefaultParamsInEvents: (NSArray *)expectedEvents { - NSArray *expectedParams = [NSArray new]; - - for (id event in expectedEvents) { - expectedParams = [expectedParams arrayByAddingObject: @[kFakePlacementID, kGMAQueryID]]; // creating expected array since default params are the same - } - - XCTAssertEqualObjects(_webAppMock.params, expectedParams); -} - -- (id)fakeAdObject { - return [NSObject new]; -} - - (GMAInterstitialAdDelegateProxy *)defaultProxyToTest { return [self.delegatesFactory interstitialDelegate: self.defaultMeta andCompletion: [UADSAnyCompletion new]]; @@ -324,14 +275,8 @@ - (GMAAdMetaData *)defaultMeta { return meta; } -- (id)delegatesFactory { - ideventSender = [UADSWebViewEventSenderBase new]; - - iderrorHandler = [UADSWebViewErrorHandler newWithEventSender: eventSender]; - - return [GMADelegatesBaseFactory newWithEventSender: eventSender - errorHandler: errorHandler - timerFactory: self.timerFactoryMock]; +- (NSArray *)expectedParams { + return @[kFakePlacementID, kGMAQueryID]; } - (void)test_factory_not_crash_if_ad_not_started_before_background { diff --git a/Tests/UnityAdsTests/GMAInfo/GMARewardedAdDelegateProxy/GMARewardedAdDelegateProxyTests.m b/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMARewardedAdDelegateProxy/GMARewardedAdDelegateProxyTests.m similarity index 85% rename from Tests/UnityAdsTests/GMAInfo/GMARewardedAdDelegateProxy/GMARewardedAdDelegateProxyTests.m rename to Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMARewardedAdDelegateProxy/GMARewardedAdDelegateProxyTests.m index b7dba7f5..624c1b7b 100644 --- a/Tests/UnityAdsTests/GMAInfo/GMARewardedAdDelegateProxy/GMARewardedAdDelegateProxyTests.m +++ b/Tests/UnityAdsTests/GMAInfo/DelegateProxyTests/GMARewardedAdDelegateProxy/GMARewardedAdDelegateProxyTests.m @@ -1,37 +1,17 @@ #import -#import "USRVWebViewAppMock.h" -#import "USRVWebViewApp.h" +#import "GMABaseAdDelegateProxyTests.h" #import "GMARewardedAdDelegateProxy.h" -#import "GMAWebViewEvent.h" -#import "NSArray+Map.h" -#import "XCTestCase+Convenience.h" #import "NSError+UADSError.h" -#import "GMADelegatesFactory.h" #import "UADSWebViewErrorHandler.h" #import "GMAError.h" #import "GMATestCommonConstants.h" -#import "UADSRepeatableTimerMock.h" -#import "UADSTimerFactoryMock.h" #import "XCTestCase+Convenience.h" -@interface GMARewardedAdDelegateProxyTests : XCTestCase -@property (nonatomic, strong) USRVWebViewAppMock *webAppMock; -@property (nonatomic, strong) UADSTimerFactoryMock *timerFactoryMock; +@interface GMARewardedAdDelegateProxyTests : GMABaseAdDelegateProxyTests @end @implementation GMARewardedAdDelegateProxyTests -- (void)setUp { - _timerFactoryMock = [UADSTimerFactoryMock new]; - _webAppMock = [USRVWebViewAppMock new]; - [USRVWebViewApp setCurrentApp: _webAppMock]; -} - -- (void)tearDown { - _webAppMock = nil; - [USRVWebViewApp setCurrentApp: _webAppMock]; -} - - (void)test_will_present_for_the_first_time_triggers_only_ad_started_event { GMARewardedAdDelegateProxy *delegateToTest = self.defaultProxyToTest; @@ -212,7 +192,7 @@ - (void)test_did_fail_sends_id_error_and_code { [self validateExpectedEvents: expectedEvents]; - NSArray *receivedParams = _webAppMock.params[0]; + NSArray *receivedParams = self.webAppMock.params[0]; XCTAssertEqualObjects(receivedParams[0], kFakePlacementID); XCTAssertEqualObjects(receivedParams[1], kGMAQueryID); @@ -237,22 +217,6 @@ - (void)simulateQuartilesPlayed: (NSInteger)count { [self.timerFactoryMock.lastTimerMock fire: count]; } -- (void)validateExpectedEvents: (NSArray *)expectedEvents { - NSArray *expectedEventNames = [expectedEvents uads_mapObjectsUsingBlock: ^id _Nonnull (GMAWebViewEvent *_Nonnull obj) { - return obj.eventName; - }]; - - NSArray *expectedCategoryNames = [expectedEvents uads_mapObjectsUsingBlock: ^id _Nonnull (GMAWebViewEvent *_Nonnull obj) { - return obj.categoryName; - }]; - - XCTAssertEqualObjects(_webAppMock.eventNames, expectedEventNames); - XCTAssertEqualObjects(_webAppMock.categoryNames, expectedCategoryNames); -} - -- (id)fakeAdObject { - return [NSObject new]; -} - (GMARewardedAdDelegateProxy *)defaultProxyToTest { return [self.delegatesFactory rewardedDelegate: self.defaultMeta]; @@ -269,16 +233,6 @@ - (GMAAdMetaData *)defaultMeta { return meta; } -- (id)delegatesFactory { - ideventSender = [UADSWebViewEventSenderBase new]; - - iderrorHandler = [UADSWebViewErrorHandler newWithEventSender: eventSender]; - - return [GMADelegatesBaseFactory newWithEventSender: eventSender - errorHandler: errorHandler - timerFactory: self.timerFactoryMock]; -} - - (void)test_rewarded_delegate_not_crash_if_ad_not_started_before_background { ideventSender = [UADSWebViewEventSenderBase new]; iderrorHandler = [UADSWebViewErrorHandler newWithEventSender: eventSender]; @@ -319,4 +273,8 @@ - (void)test_no_quartile_events_sent_after_dismiss_ad { [self validateExpectedEvents: expectedEvents]; } +- (NSArray *)expectedParams { + return @[kFakePlacementID, kGMAQueryID]; +} + @end diff --git a/Tests/UnityAdsTests/GMAInfo/GMASCARSignalsReaderDecorator/GMASCARSignalsReaderDecoratorTests.m b/Tests/UnityAdsTests/GMAInfo/GMASCARSignalsReaderDecorator/GMASCARSignalsReaderDecoratorTests.m index 94b5bb5e..8592aab4 100644 --- a/Tests/UnityAdsTests/GMAInfo/GMASCARSignalsReaderDecorator/GMASCARSignalsReaderDecoratorTests.m +++ b/Tests/UnityAdsTests/GMAInfo/GMASCARSignalsReaderDecorator/GMASCARSignalsReaderDecoratorTests.m @@ -27,9 +27,8 @@ - (void)test_returns_empty_string_when_empty_dictionary_is_passed { returnedString = string; }]; - [_sut getSCARSignalsUsingInterstitialList: EMPTY_ARRAY - andRewardedList: EMPTY_ARRAY - completion: completion]; + [_sut getSCARSignals: EMPTY_ARRAY + completion: completion]; [_readerMock emulateReturnOfAnEmptyDictionary]; XCTAssertEqualObjects(returnedString, kUADS_EMPTY_STRING); @@ -41,9 +40,8 @@ - (void)test_returns_empty_string_when_nil_dictionary_is_passed { returnedString = string; }]; - [_sut getSCARSignalsUsingInterstitialList: EMPTY_ARRAY - andRewardedList: EMPTY_ARRAY - completion: completion]; + [_sut getSCARSignals: EMPTY_ARRAY + completion: completion]; [_readerMock emulateReturnOfNil]; XCTAssertEqualObjects(returnedString, kUADS_EMPTY_STRING); @@ -59,9 +57,8 @@ - (void)test_returns_encoded_non_empty_string { @"key": @"value" }; - [_sut getSCARSignalsUsingInterstitialList: EMPTY_ARRAY - andRewardedList: EMPTY_ARRAY - completion: completion]; + [_sut getSCARSignals: EMPTY_ARRAY + completion: completion]; [_readerMock emulateReturnOfADictionary: testDictionary]; diff --git a/Tests/UnityAdsTests/GMAInfo/GMASCARSignalsReaderDecorator/Mocks/GMASCARSignalsReaderMock.m b/Tests/UnityAdsTests/GMAInfo/GMASCARSignalsReaderDecorator/Mocks/GMASCARSignalsReaderMock.m index 8b6618d5..3f839f62 100644 --- a/Tests/UnityAdsTests/GMAInfo/GMASCARSignalsReaderDecorator/Mocks/GMASCARSignalsReaderMock.m +++ b/Tests/UnityAdsTests/GMAInfo/GMASCARSignalsReaderDecorator/Mocks/GMASCARSignalsReaderMock.m @@ -6,12 +6,6 @@ @interface GMASCARSignalsReaderMock () @implementation GMASCARSignalsReaderMock -- (void)getSCARSignalsUsingInterstitialList: (nonnull NSArray *)interstitialList - andRewardedList: (nonnull NSArray *)rewardedList - completion: (nonnull UADSGMAScarSignalsCompletion *)completion { - self.completion = completion; -} - - (void)emulateReturnOfAnEmptyDictionary { [self.completion success: [UADSSCARSignals new]]; } @@ -24,4 +18,8 @@ - (void)emulateReturnOfADictionary: (UADSSCARSignals *)dictionary { [self.completion success: dictionary]; } +- (void)getSCARSignals:(nonnull NSArray *)signalParameters completion:(nonnull UADSGMAScarSignalsCompletion *)completion { + self.completion = completion; +} + @end diff --git a/Tests/UnityAdsTests/GMAInfo/GMAScarSignalsReaderTests/GMAScarSignalsReaderTests.m b/Tests/UnityAdsTests/GMAInfo/GMAScarSignalsReaderTests/GMAScarSignalsReaderTests.m index f0cbaeb3..a2fa5a7f 100644 --- a/Tests/UnityAdsTests/GMAInfo/GMAScarSignalsReaderTests/GMAScarSignalsReaderTests.m +++ b/Tests/UnityAdsTests/GMAInfo/GMAScarSignalsReaderTests/GMAScarSignalsReaderTests.m @@ -6,10 +6,12 @@ #import "XCTestAssert+Fail.h" #import "XCTestCase+Convenience.h" +#define FAKE_BANNER_PLACEMENT @"FAKE_BANNER_PLACEMENT" #define FAKE_REWARDED_PLACEMENT @"FAKE_REWARDED_PLACEMENT" #define FAKE_INTERSTITIAL_PLACEMENT @"FAKE_INTERSTITIAL_PLACEMENT" #define FAKE_REWARDED_SIGNAL @"FAKE_REWARDED_SIGNAL" #define FAKE_INTERSTITIAL_SIGNAL @"FAKE_INTERSTITIAL_SIGNAL" +#define FAKE_BANNER_SIGNAL @"FAKE_BANNER_SIGNAL" typedef void (^SuccessCompletion)(UADSSCARSignals *); @interface GMAScarSignalsReaderTests : XCTestCase @@ -25,158 +27,163 @@ - (void)setUp { } - (void)test_calls_signal_reader_for_rewarded_list { - [self launch_success_flow_test_with_interstitialList: @[] - andRewardedList: @[FAKE_REWARDED_PLACEMENT] - conditionSuccess: ^(UADSSCARSignals *signals) { - XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeRewarded], 1); - }]; -} - -- (void)test_should_not_call_signal_reader_for_interstitial { - [self launch_success_flow_test_with_interstitialList: @[] - andRewardedList: @[FAKE_REWARDED_PLACEMENT] - conditionSuccess: ^(UADSSCARSignals *signals) { - XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeInterstitial], 0); - }]; + [self launch_success_flow_test_with_parameters_list: @[self.rewardedParams] + conditionSuccess: ^(UADSSCARSignals *signals) { + XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeRewarded], 1); + XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeInterstitial], 0); + XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeBanner], 0); + }]; } - (void)test_when_both_lists_are_empty_return_empty_dictionary { - [self launch_success_flow_test_with_interstitialList: @[] - andRewardedList: @[] - conditionSuccess: ^(UADSSCARSignals *signals) { - XCTAssertTrue(signals.allKeys.count == 0); - XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeInterstitial], 0); - XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeRewarded], 0); - }]; + [self launch_success_flow_test_with_parameters_list: @[] + conditionSuccess: ^(UADSSCARSignals *signals) { + XCTAssertTrue(signals.allKeys.count == 0); + XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeInterstitial], 0); + XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeRewarded], 0); + }]; } - (void)test_calls_signal_reader_for_interstitial_list { - [self launch_success_flow_test_with_interstitialList: @[FAKE_INTERSTITIAL_PLACEMENT] - andRewardedList: @[] - conditionSuccess: ^(UADSSCARSignals *signals) { - XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeInterstitial], 1); - }]; + [self launch_success_flow_test_with_parameters_list: @[self.interstitialParams] + conditionSuccess: ^(UADSSCARSignals *signals) { + XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeInterstitial], 1); + XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeRewarded], 0); + XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeBanner], 0); + }]; } -- (void)test_should_not_call_signal_reader_for_rewarded { - [self launch_success_flow_test_with_interstitialList: @[FAKE_INTERSTITIAL_PLACEMENT] - andRewardedList: @[] - conditionSuccess: ^(UADSSCARSignals *signals) { - XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeRewarded], 0); - }]; +- (void)test_calls_signal_reader_for_banner_list { + [self launch_success_flow_test_with_parameters_list: @[self.bannerParams] + conditionSuccess: ^(UADSSCARSignals *signals) { + XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeInterstitial], 0); + XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeRewarded], 0); + XCTAssertEqual([self.mock numberOfCallsForType: GADQueryInfoAdTypeBanner], 1); + }]; } - (void)test_should_return_proper_signals { - [self launch_success_flow_test_with_interstitialList: @[FAKE_INTERSTITIAL_PLACEMENT] - andRewardedList: @[FAKE_REWARDED_PLACEMENT] - conditionSuccess: ^(UADSSCARSignals *signals) { - XCTAssertEqualObjects([signals valueForKey: FAKE_INTERSTITIAL_PLACEMENT], FAKE_INTERSTITIAL_SIGNAL); - XCTAssertEqualObjects([signals valueForKey: FAKE_REWARDED_PLACEMENT], FAKE_REWARDED_SIGNAL); - XCTAssertEqual(signals.count, 2); - }]; + [self launch_success_flow_test_with_parameters_list: @[self.interstitialParams, self.rewardedParams, self.bannerParams] + conditionSuccess: ^(UADSSCARSignals *signals) { + XCTAssertEqualObjects([signals valueForKey: FAKE_INTERSTITIAL_PLACEMENT], FAKE_INTERSTITIAL_SIGNAL); + XCTAssertEqualObjects([signals valueForKey: FAKE_REWARDED_PLACEMENT], FAKE_REWARDED_SIGNAL); + XCTAssertEqualObjects([signals valueForKey: FAKE_BANNER_PLACEMENT], FAKE_BANNER_SIGNAL); + XCTAssertEqual(signals.count, 3); + }]; } - (void)test_should_return_error_if_there_is_no_signal_map { - [self launch_test_with_interstitial_list: @[FAKE_INTERSTITIAL_PLACEMENT] - andRewardedList: @[] - error: [UADSDefaultError newWithString: @"error"] - callSuccess: false - conditionError: ^(id _Nonnull error) { - XCTAssertEqualObjects(error.errorString, @"error"); - } - conditionSuccess: self.failIfSuccess]; + [self launch_test_with_parameters_list: @[self.interstitialParams] + error: [UADSDefaultError newWithString: @"error"] + callSuccess: false + conditionError: ^(id _Nonnull error) { + XCTAssertEqualObjects(error.errorString, @"error"); + } + conditionSuccess: self.failIfSuccess]; } - (void)test_should_call_success_if_map_is_not_empty_even_if_error_is_present { - [self launch_test_with_interstitial_list: @[] - andRewardedList: @[FAKE_REWARDED_PLACEMENT] - error: [UADSDefaultError newWithString: @"error"] - callSuccess: true - conditionError: self.failIfError - conditionSuccess: ^(UADSSCARSignals *signals) { - XCTAssertEqualObjects([signals valueForKey: FAKE_REWARDED_PLACEMENT], FAKE_REWARDED_SIGNAL); - XCTAssertEqual(signals.count, 1); - }]; + [self launch_test_with_parameters_list: @[self.rewardedParams] + error: [UADSDefaultError newWithString: @"error"] + callSuccess: true + conditionError: self.failIfError + conditionSuccess: ^(UADSSCARSignals *signals) { + XCTAssertEqualObjects([signals valueForKey: FAKE_REWARDED_PLACEMENT], FAKE_REWARDED_SIGNAL); + XCTAssertEqual(signals.count, 1); + }]; } //MARK: - HELPER METHODS - (SuccessCompletion)failIfSuccess { return ^(UADSSCARSignals *signals) { - XCTFail(@"Should not fall through success branch"); + XCTFail(@"Should not fall through success branch"); }; } -- (void)launch_success_flow_test_with_interstitialList: (NSArray *)interstitialList - andRewardedList: (NSArray *)rewardedList - conditionSuccess: (SuccessCompletion)condition { - [self launch_test_with_interstitial_list: interstitialList - andRewardedList: rewardedList - error: nil - callSuccess: true - conditionError: self.failIfError - conditionSuccess: condition]; +- (void)launch_success_flow_test_with_parameters_list: (NSArray *)list + conditionSuccess: (SuccessCompletion)condition { + [self launch_test_with_parameters_list: list + error: nil + callSuccess: true + conditionError: self.failIfError + conditionSuccess: condition]; } -- (void)launch_test_with_interstitial_list: (NSArray *)interstitialList - andRewardedList: (NSArray *)rewardedList - error: (id)error - callSuccess: (bool)shouldCallSuccess - conditionError: (ErrorCompletion)errorCompletion - conditionSuccess: (SuccessCompletion)condition { +- (void)launch_test_with_parameters_list: (NSArray *)list + error: (id)error + callSuccess: (bool)shouldCallSuccess + conditionError: (ErrorCompletion)errorCompletion + conditionSuccess: (SuccessCompletion)condition { XCTestExpectation *expectation = self.defaultExpectation; - - [self emulate_reader_call_with_interstitial_list: interstitialList - andRewardedList: rewardedList - withExpectation: expectation - conditionSuccess: condition - errorCondition: errorCompletion]; - + + [self emulate_reader_call_with_parameters_list: list + withExpectation: expectation + conditionSuccess: condition + errorCondition: errorCompletion]; + if (error) { [_mock callErrorForType: GADQueryInfoAdTypeInterstitial forPlacementId: FAKE_INTERSTITIAL_PLACEMENT error: error]; } - + if (shouldCallSuccess) { - for (NSString *placementID in interstitialList) { - [_mock callSuccessForType: GADQueryInfoAdTypeInterstitial - forPlacementId: placementID - signal: FAKE_INTERSTITIAL_SIGNAL]; - } - - for (NSString *placementID in rewardedList) { - [_mock callSuccessForType: GADQueryInfoAdTypeRewarded - forPlacementId: placementID - signal: FAKE_REWARDED_SIGNAL]; + for (UADSScarSignalParameters *params in list) { + [_mock callSuccessForType: params.adFormat + forPlacementId: params.placementId + signal: [self fakeSignalForType: params.adFormat]]; } } - + [self waitForExpectations: @[expectation] timeout: 5]; } -- (void)emulate_reader_call_with_interstitial_list: (NSArray *)interstitialList - andRewardedList: (NSArray *)rewardedList - withExpectation: (XCTestExpectation *)expectation - conditionSuccess: (SuccessCompletion)condition - errorCondition: (ErrorCompletion)errorCondition { - UADSGMAScarSignalsCompletion *completion = [UADSGMAScarSignalsCompletion newWithSuccess: ^(UADSSCARSignals *_Nullable signal) { +- (void)emulate_reader_call_with_parameters_list: (NSArray *)list + withExpectation: (XCTestExpectation *)expectation + conditionSuccess: (SuccessCompletion)condition + errorCondition: (ErrorCompletion)errorCondition { + UADSGMAScarSignalsCompletion *completion = [UADSGMAScarSignalsCompletion + newWithSuccess: ^(UADSSCARSignals *_Nullable signal) { condition(signal); [expectation fulfill]; } - andError: ^(id error) { - errorCondition(error); - [expectation fulfill]; - }]; - - [_readerToTest getSCARSignalsUsingInterstitialList: interstitialList - andRewardedList: rewardedList - completion: completion]; + andError: ^(id error) { + errorCondition(error); + [expectation fulfill]; + }]; + + [_readerToTest getSCARSignals:list completion:completion]; } - (id)createUsingMock: (GMASignalServiceMock *)mock { return [GMABaseSCARSignalsReader newWithSignalService: mock]; } +- (NSString *)fakeSignalForType:(GADQueryInfoAdType)type { + switch (type) { + case GADQueryInfoAdTypeBanner: + return FAKE_BANNER_SIGNAL; + case GADQueryInfoAdTypeInterstitial: + return FAKE_INTERSTITIAL_SIGNAL; + case GADQueryInfoAdTypeRewarded: + return FAKE_REWARDED_SIGNAL; + } +} + +- (UADSScarSignalParameters *)bannerParams { + return [[UADSScarSignalParameters alloc] initWithPlacementId: FAKE_BANNER_PLACEMENT adFormat: GADQueryInfoAdTypeBanner]; +} + +- (UADSScarSignalParameters *)rewardedParams { + return [[UADSScarSignalParameters alloc] initWithPlacementId: FAKE_REWARDED_PLACEMENT adFormat: GADQueryInfoAdTypeRewarded]; +} + +- (UADSScarSignalParameters *)interstitialParams { + return [[UADSScarSignalParameters alloc] initWithPlacementId: FAKE_INTERSTITIAL_PLACEMENT adFormat: GADQueryInfoAdTypeInterstitial]; +} + + + @end diff --git a/Tests/UnityAdsTests/GMAInfo/GMAScarSignalsReaderTests/Mocks/GMASignalServiceMock.m b/Tests/UnityAdsTests/GMAInfo/GMAScarSignalsReaderTests/Mocks/GMASignalServiceMock.m index fef4aa86..b6623110 100644 --- a/Tests/UnityAdsTests/GMAInfo/GMAScarSignalsReaderTests/Mocks/GMASignalServiceMock.m +++ b/Tests/UnityAdsTests/GMAInfo/GMAScarSignalsReaderTests/Mocks/GMASignalServiceMock.m @@ -5,8 +5,10 @@ @interface GMASignalServiceMock () @property (nonatomic, assign) NSUInteger rewardSignalsCalls; @property (nonatomic, assign) NSUInteger interstitialCalls; +@property (nonatomic, assign) NSUInteger bannersCalls; @property (nonatomic, strong) CompletionMap *interstitialCompletions; @property (nonatomic, strong) CompletionMap *rewardCompletions; +@property (nonatomic, strong) CompletionMap *bannerCompletions; @end @implementation GMASignalServiceMock @@ -14,6 +16,7 @@ - (instancetype)init { SUPER_INIT self.interstitialCompletions = [[CompletionMap alloc] init]; self.rewardCompletions = [[CompletionMap alloc] init]; + self.bannerCompletions = [[CompletionMap alloc] init]; return self; } @@ -23,6 +26,10 @@ - (void)getSignalOfAdType: (GADQueryInfoAdType)adType CompletionMap *map; switch (adType) { + case GADQueryInfoAdTypeBanner: + _bannersCalls += 1; + map = _bannerCompletions; + break; case GADQueryInfoAdTypeInterstitial: _interstitialCalls += 1; map = _interstitialCompletions; @@ -51,6 +58,9 @@ - (void)callErrorForType: (GADQueryInfoAdType)adType - (CompletionMap *)getMapOfType: (GADQueryInfoAdType)type { switch (type) { + case GADQueryInfoAdTypeBanner: + return _bannerCompletions; + case GADQueryInfoAdTypeInterstitial: return _interstitialCompletions; @@ -61,9 +71,12 @@ - (CompletionMap *)getMapOfType: (GADQueryInfoAdType)type { - (NSUInteger)numberOfCallsForType: (GADQueryInfoAdType)type { switch (type) { + case GADQueryInfoAdTypeBanner: + return _bannersCalls; + case GADQueryInfoAdTypeRewarded: return _rewardSignalsCalls; - + case GADQueryInfoAdTypeInterstitial: return _interstitialCalls; } @@ -75,4 +88,8 @@ - (nullable GADRequestBridge *)getAdRequestFor: (nonnull NSString *)placementId return nil; } +- (nullable GADRequestBridge *)getAdRequestFor:(nonnull GMAAdMetaData *)meta error:(id _Nullable __autoreleasing * _Nullable)error { + return nil; +} + @end diff --git a/Tests/UnityAdsTests/GMAInfo/GMASignalReaderTests/Mocks/GMAQueryInfoReaderMock.m b/Tests/UnityAdsTests/GMAInfo/GMASignalReaderTests/Mocks/GMAQueryInfoReaderMock.m index 7b3341b5..ac8f2d94 100644 --- a/Tests/UnityAdsTests/GMAInfo/GMASignalReaderTests/Mocks/GMAQueryInfoReaderMock.m +++ b/Tests/UnityAdsTests/GMAInfo/GMASignalReaderTests/Mocks/GMAQueryInfoReaderMock.m @@ -12,8 +12,10 @@ @implementation GMAQueryInfoMock : NSObject @interface GMAQueryInfoReaderMock () @property (nonatomic, assign) NSUInteger rewardCalls; @property (nonatomic, assign) NSUInteger intCalls; +@property (nonatomic, assign) NSUInteger bannerCalls; @property (nonatomic, strong) CompletionsList *intCompletions; @property (nonatomic, strong) CompletionsList *rewCompletions; +@property (nonatomic, strong) CompletionsList *bannerCompletions; @end @implementation GMAQueryInfoReaderMock @@ -27,6 +29,10 @@ - (instancetype)init { - (void)getQueryInfoOfFormat: (GADQueryInfoAdType)type completion: (nonnull GADQueryInfoBridgeCompletion *)completion { switch (type) { + case GADQueryInfoAdTypeBanner: + _bannerCalls += 1; + [_bannerCompletions addObject: completion]; + break; case GADQueryInfoAdTypeInterstitial: _intCalls += 1; [_intCompletions addObject: completion]; @@ -60,6 +66,9 @@ - (GADQueryInfoBridgeCompletion *)getAndRemoveLastCompletionForAdType: (GADQuery - (CompletionsList *)getListOfType: (GADQueryInfoAdType)type { switch (type) { + case GADQueryInfoAdTypeBanner: + return _bannerCompletions; + case GADQueryInfoAdTypeInterstitial: return _intCompletions; @@ -70,11 +79,15 @@ - (CompletionsList *)getListOfType: (GADQueryInfoAdType)type { - (NSUInteger)numberOfCallsForType: (GADQueryInfoAdType)type { switch (type) { + case GADQueryInfoAdTypeBanner: + return _bannerCalls; + case GADQueryInfoAdTypeRewarded: return _rewardCalls; case GADQueryInfoAdTypeInterstitial: return _intCalls; + } } diff --git a/Tests/UnityAdsTests/GMAInfo/UADSGMAScarNoGMATests/UADSNoGMAApiTests.m b/Tests/UnityAdsTests/GMAInfo/UADSGMAScarNoGMATests/UADSNoGMAApiTests.m index 646b8e3e..085b7f67 100644 --- a/Tests/UnityAdsTests/GMAInfo/UADSGMAScarNoGMATests/UADSNoGMAApiTests.m +++ b/Tests/UnityAdsTests/GMAInfo/UADSGMAScarNoGMATests/UADSNoGMAApiTests.m @@ -33,10 +33,7 @@ - (void)test_returns_version_placeholder { - (void)test_returns_internal_error_when_get_signals_is_called { GMAError *error = [GMAError newInternalSignalsError]; - [_tester emulateGetScarSignals: @[@"test"] - rewardedPlacements: @[] - testCase: self - expectedEvents: @[[error convertToEvent]]]; + [_tester emulateGetScarSignal:@"test" adFormat:@"banner" testCase:self expectedEvents:@[[error convertToEvent]]]; } - (void)test_returns_internal_error_when_load_is_called { diff --git a/Tests/UnityAdsTests/Mocks/UADSConfigurationReaderMock.h b/Tests/UnityAdsTests/Mocks/UADSConfigurationReaderMock.h index 3ef723d4..466d9889 100644 --- a/Tests/UnityAdsTests/Mocks/UADSConfigurationReaderMock.h +++ b/Tests/UnityAdsTests/Mocks/UADSConfigurationReaderMock.h @@ -12,6 +12,5 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong) NSDictionary *experiments; @property (nonatomic, strong) NSString *metricURL; @property (nonatomic, strong) NSDictionary *expectedMetricInfo; -@property (nonatomic) UADSSCARHBStrategyType expectedStrategyType; @end NS_ASSUME_NONNULL_END diff --git a/Tests/UnityAdsTests/Mocks/UADSConfigurationReaderMock.m b/Tests/UnityAdsTests/Mocks/UADSConfigurationReaderMock.m index dd612319..bab51124 100644 --- a/Tests/UnityAdsTests/Mocks/UADSConfigurationReaderMock.m +++ b/Tests/UnityAdsTests/Mocks/UADSConfigurationReaderMock.m @@ -44,8 +44,6 @@ - (nonnull NSString *)getCurrentMetricsUrl { return @""; } - - - (NSDictionary *)metricTags { return self.experiments; } @@ -54,13 +52,8 @@ - (NSDictionary *)metricContainerConfigurationInfo { return _expectedMetricInfo; } - - (NSString *)getCurrentScarHBURL { return @""; } -- (UADSSCARHBStrategyType)selectedSCARHBStrategyType { - return self.expectedStrategyType ?: UADSSCARHeaderBiddingStrategyTypeDisabled; -} - @end diff --git a/Tests/UnityAdsTests/Swift/TestTools/Mocks/Network/Responses/ConfigResponseMock.json b/Tests/UnityAdsTests/Swift/TestTools/Mocks/Network/Responses/ConfigResponseMock.json index 755d537c..6a589b18 100644 --- a/Tests/UnityAdsTests/Swift/TestTools/Mocks/Network/Responses/ConfigResponseMock.json +++ b/Tests/UnityAdsTests/Swift/TestTools/Mocks/Network/Responses/ConfigResponseMock.json @@ -22,9 +22,6 @@ "ntwd": { "value": "true" }, - "scar_bm": { - "value": "laz" - }, "sto": { "value": "30000" }, diff --git a/Tests/UnityAdsTests/Swift/Token/HeaderBiddingTokenReaderTestsCase.swift b/Tests/UnityAdsTests/Swift/Token/HeaderBiddingTokenReaderTestsCase.swift index 7741d061..eb04754a 100644 --- a/Tests/UnityAdsTests/Swift/Token/HeaderBiddingTokenReaderTestsCase.swift +++ b/Tests/UnityAdsTests/Swift/Token/HeaderBiddingTokenReaderTestsCase.swift @@ -18,16 +18,9 @@ class HeaderBiddingTokenReaderTestsCase: XCTestCase { ) } - func test_returns_token_without_tid() throws { - deviceInfoBodyReaderMock.expected = ["key": "value"] - experimentsDict = [:] - try runTestWithExpectedToken("1:H4sIAAAAAAAAE6tWyk6tVLJSKkvMKU1VqgUAv5wYPw8AAAA=") - } - func test_returns_token_with_tid() throws { deviceInfoBodyReaderMock.expected = [:] uniqueGeneratorMock.uniqueID = "1" - experimentsDict = ["scar_bm": "eag"] try runTestWithExpectedToken("1:H4sIAAAAAAAAE6tWKslMUbJSMlSqBQCgUV/nCwAAAA==") } diff --git a/Tests/UnityAdsTests/UADTestsTools/GMATestCommonConstants.h b/Tests/UnityAdsTests/UADTestsTools/GMATestCommonConstants.h index 0e5c2e0c..6ff908ee 100644 --- a/Tests/UnityAdsTests/UADTestsTools/GMATestCommonConstants.h +++ b/Tests/UnityAdsTests/UADTestsTools/GMATestCommonConstants.h @@ -4,4 +4,5 @@ static NSString *const kFakePlacementID = @"TEST"; static NSString *const kGMAEventName = @"GMA"; static NSString *const kGMAQueryID = @"kGMAQueryID"; +static NSString *const kGMABannerAdId = @"kBannerAdId"; #endif /* GMATestCommonConstants_h */ diff --git a/Tests/UnityAdsTests/UADTestsTools/GMATestsHelper/GMATestsHelper.h b/Tests/UnityAdsTests/UADTestsTools/GMATestsHelper/GMATestsHelper.h index 79bf5774..ab9be7f8 100644 --- a/Tests/UnityAdsTests/UADTestsTools/GMATestsHelper/GMATestsHelper.h +++ b/Tests/UnityAdsTests/UADTestsTools/GMATestsHelper/GMATestsHelper.h @@ -11,10 +11,10 @@ NS_ASSUME_NONNULL_BEGIN - (void)clear; - (void)emulateIsAvailableCall: (UADSSuccessCompletion)completion; - (void)emulateGetVersionCall: (UADSSuccessCompletion)completion; -- (void)emulateGetScarSignals: (NSArray *)interstitialPlacements - rewardedPlacements: (NSArray *)rewardedPlacements - testCase: (XCTestCase *)testCase - expectedEvents: (NSArray *)expectedEvents; +- (void)emulateGetScarSignal: (NSString *)placementId + adFormat: (NSString *)adFormat + testCase: (XCTestCase *)testCase + expectedEvents: (NSArray *)expectedEvents; - (void)emulateLoadWithParams: (NSArray *)params testCase: (XCTestCase *)testCase diff --git a/Tests/UnityAdsTests/UADTestsTools/GMATestsHelper/GMATestsHelper.m b/Tests/UnityAdsTests/UADTestsTools/GMATestsHelper/GMATestsHelper.m index 2f1d19ad..82b24b4f 100644 --- a/Tests/UnityAdsTests/UADTestsTools/GMATestsHelper/GMATestsHelper.m +++ b/Tests/UnityAdsTests/UADTestsTools/GMATestsHelper/GMATestsHelper.m @@ -44,16 +44,16 @@ - (void)emulateGetVersionCall: (UADSSuccessCompletion)completion { }]; } -- (void)emulateGetScarSignals: (NSArray *)interstitialPlacements - rewardedPlacements: (NSArray *)rewardedPlacements - testCase: (XCTestCase *)testCase - expectedEvents: (NSArray *)expectedEvents { +- (void)emulateGetScarSignal: (NSString *)placementId + adFormat: (NSString *)adFormat + testCase: (XCTestCase *)testCase + expectedEvents: (NSArray *)expectedEvents { XCTestExpectation *exp = [testCase expectationWithDescription: @"Signals Integration test"]; _webViewMock.expectation = exp; - [self emulateCallOfMethod: @"getSCARSignals" - withParams: @[interstitialPlacements, rewardedPlacements] + [self emulateCallOfMethod: @"getSCARSignal" + withParams: @[placementId, adFormat] withCallback:^(NSArray *_Nullable array) { }]; diff --git a/Tests/UnityAdsTests/UADTestsTools/UADSGMAScar+Sync/UADSGMAScar+SyncGetter.m b/Tests/UnityAdsTests/UADTestsTools/UADSGMAScar+Sync/UADSGMAScar+SyncGetter.m index 65d08342..d1756cb4 100644 --- a/Tests/UnityAdsTests/UADTestsTools/UADSGMAScar+Sync/UADSGMAScar+SyncGetter.m +++ b/Tests/UnityAdsTests/UADTestsTools/UADSGMAScar+Sync/UADSGMAScar+SyncGetter.m @@ -42,10 +42,15 @@ - (void)getSignalsSyncFor: (NSArray *)interstitialList UADSGMAEncodedSignalsCompletion *completion = [UADSGMAEncodedSignalsCompletion newWithSuccess: successHandler andError: errorHandler]; + NSMutableArray*list = [[NSMutableArray alloc] init]; + for (NSString *interstitial in interstitialList) { + [list addObject:[[UADSScarSignalParameters alloc] initWithPlacementId:interstitial adFormat:GADQueryInfoAdTypeInterstitial]]; + } + for (NSString *rewareded in rewardedList) { + [list addObject:[[UADSScarSignalParameters alloc] initWithPlacementId:rewareded adFormat:GADQueryInfoAdTypeRewarded]]; + } + [self getSCARSignals:list completion:completion]; - [self getSCARSignalsUsingInterstitialList: interstitialList - andRewardedList: rewardedList - completion: completion]; [testCase waitForExpectations: @[exp] timeout: DEFAULT_WAITING_INTERVAL]; } diff --git a/UnityAds.podspec b/UnityAds.podspec index d31968b7..dd9a308c 100644 --- a/UnityAds.podspec +++ b/UnityAds.podspec @@ -1,12 +1,12 @@ Pod::Spec.new do |s| s.name = 'UnityAds' - s.version = '4.8.0' + s.version = '4.9.0' s.license = { :type => 'Unity License', :file => 'LICENSE' } s.author = { 'UnityAds' => 'itunes@unity3d.com' } s.homepage = 'https://unity3d.com/services/ads' s.summary = 'Monetize your entire player base and reach new audiences with video ads.' s.platform = :ios - s.source = { :http => 'https://github.com/Unity-Technologies/unity-ads-ios/releases/download/4.8.0/UnityAds.zip' } + s.source = { :http => 'https://github.com/Unity-Technologies/unity-ads-ios/releases/download/4.9.0/UnityAds.zip' } s.ios.deployment_target = '9.0' s.ios.vendored_frameworks = 'UnityAds.xcframework' s.swift_version = '5.0'