Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,11 @@ - (void)videoViewCompletedDisplay {
}

if (self.creativeModel.adConfiguration.presentAsInterstitial) {
// no companion ads so pass this event to the PBMModalManager
// and close video automatically
[self.modalManager creativeDisplayCompleted:self];
if (self.dismissInterstitialModalState) {
// No companion ads, so pass completion to the modal manager and
// close automatically unless the publisher disabled that behavior.
[self.modalManager creativeDisplayCompleted:self];
if (self.creativeModel.adConfiguration.videoControlsConfig.isAutoCloseOnCompletionEnabled &&
self.dismissInterstitialModalState) {
self.dismissInterstitialModalState();
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ public class VideoControlsConfiguration: NSObject {

/// This property indicates whether mute controls is visible on the screen.
public var isSoundButtonVisible = false

/// This property indicates whether a full-screen video without a companion ad closes automatically when playback completes.
public var isAutoCloseOnCompletionEnabled = true

/// Use to initialize video controls with server values.
public func initialize(with ortbAdConfiguration: ORTBAdConfiguration?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ public class InterstitialRenderingAdUnit: NSObject, BaseInterstitialAdUnitProtoc
get { adUnitConfig.adConfiguration.videoControlsConfig.isSoundButtonVisible }
set { adUnitConfig.adConfiguration.videoControlsConfig.isSoundButtonVisible = newValue }
}

/// A Boolean value indicating whether video ads without an end card close when playback completes.
public var isAutoCloseOnCompletionEnabled: Bool {
get { adUnitConfig.adConfiguration.videoControlsConfig.isAutoCloseOnCompletionEnabled }
set { adUnitConfig.adConfiguration.videoControlsConfig.isAutoCloseOnCompletionEnabled = newValue }
}

// MARK: Private properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ public class RewardedAdUnit: NSObject, BaseInterstitialAdUnitProtocol {
get { adUnitConfig.adConfiguration.videoControlsConfig.isSoundButtonVisible }
set { adUnitConfig.adConfiguration.videoControlsConfig.isSoundButtonVisible = newValue }
}

/// A Boolean value indicating whether video ads without an end card close when playback completes.
public var isAutoCloseOnCompletionEnabled: Bool {
Comment thread
mdanylov-sigma marked this conversation as resolved.
Outdated
get { adUnitConfig.adConfiguration.videoControlsConfig.isAutoCloseOnCompletionEnabled }
set { adUnitConfig.adConfiguration.videoControlsConfig.isAutoCloseOnCompletionEnabled = newValue }
}

// MARK: Internal Properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ public class MediationBaseInterstitialAdUnit : NSObject {
get { adUnitConfig.adConfiguration.videoControlsConfig.isSoundButtonVisible }
set { adUnitConfig.adConfiguration.videoControlsConfig.isSoundButtonVisible = newValue }
}

/// Indicates whether video ads without an end card close when playback completes.
public var isAutoCloseOnCompletionEnabled: Bool {
get { adUnitConfig.adConfiguration.videoControlsConfig.isAutoCloseOnCompletionEnabled }
set { adUnitConfig.adConfiguration.videoControlsConfig.isAutoCloseOnCompletionEnabled = newValue }
}

/// The area for the close button in the video ad.
public var closeButtonArea: Double {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ import AVFoundation

@testable @_spi(PBMInternal) import PrebidMobile

private final class CompletionTrackingModalManager: MockModalManager {
private(set) var completedCreative: AbstractCreative?

override func creativeDisplayCompleted(_ creative: AbstractCreative) {
completedCreative = creative
}
}

class VideoCreativeDelegateTest: XCTestCase, CreativeResolutionDelegate, CreativeViewDelegate, PBMVideoViewDelegate {

var videoCreative:PBMVideoCreative!
Expand Down Expand Up @@ -223,6 +231,84 @@ class VideoCreativeDelegateTest: XCTestCase, CreativeResolutionDelegate, Creativ

waitForExpectations(timeout: 1, handler: nil)
}

func testInterstitialWithoutCompanionAutoClosesByDefault() {
let adConfiguration = AdConfiguration()
adConfiguration.isInterstitialAd = true
let model = CreativeModel(adConfiguration: adConfiguration)
model.hasCompanionAd = false

videoCreative = PBMVideoCreative(
creativeModel: model,
transaction: UtilitiesForTesting.createEmptyTransaction(),
videoData: Data()
)

let modalManager = MockModalManager()
videoCreative.modalManager = modalManager
videoCreative.showAsInterstitial(
fromRootViewController: UIViewController(),
displayProperties: InterstitialDisplayProperties()
)
XCTAssertEqual(modalManager.modalStateStack.count, 1)

videoCreative.videoViewCompletedDisplay()

XCTAssertTrue(modalManager.modalStateStack.isEmpty)
}

func testInterstitialWithoutCompanionCanDisableAutoClose() {
let adConfiguration = AdConfiguration()
adConfiguration.isInterstitialAd = true
adConfiguration.videoControlsConfig.isAutoCloseOnCompletionEnabled = false
let model = CreativeModel(adConfiguration: adConfiguration)
model.hasCompanionAd = false

videoCreative = PBMVideoCreative(
creativeModel: model,
transaction: UtilitiesForTesting.createEmptyTransaction(),
videoData: Data()
)

let modalManager = MockModalManager()
videoCreative.modalManager = modalManager
videoCreative.showAsInterstitial(
fromRootViewController: UIViewController(),
displayProperties: InterstitialDisplayProperties()
)
XCTAssertEqual(modalManager.modalStateStack.count, 1)

videoCreative.videoViewCompletedDisplay()

XCTAssertEqual(modalManager.modalStateStack.count, 1)
}

func testRewardedCompletionIsReportedWhenAutoCloseIsDisabled() {
let adConfiguration = AdConfiguration()
adConfiguration.isInterstitialAd = true
adConfiguration.isRewarded = true
adConfiguration.videoControlsConfig.isAutoCloseOnCompletionEnabled = false
let model = CreativeModel(adConfiguration: adConfiguration)
model.hasCompanionAd = false

videoCreative = PBMVideoCreative(
creativeModel: model,
transaction: UtilitiesForTesting.createEmptyTransaction(),
videoData: Data()
)

let modalManager = CompletionTrackingModalManager()
videoCreative.modalManager = modalManager
videoCreative.showAsInterstitial(
fromRootViewController: UIViewController(),
displayProperties: InterstitialDisplayProperties()
)

videoCreative.videoViewCompletedDisplay()

XCTAssertTrue(modalManager.completedCreative === videoCreative)
XCTAssertEqual(modalManager.modalStateStack.count, 1)
}

func testSkipOffset() {
let expectation = self.expectation(description: "Should push Modal")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ class VideoControlsConfigTests: XCTestCase {
XCTAssertTrue(adConfiguration.isSoundButtonVisible == false)
}

func testAutoCloseOnCompletion() {
let adConfiguration = VideoControlsConfiguration()
XCTAssertTrue(adConfiguration.isAutoCloseOnCompletionEnabled)

adConfiguration.isAutoCloseOnCompletionEnabled = false
XCTAssertFalse(adConfiguration.isAutoCloseOnCompletionEnabled)
}

func testCloseButtonArea() {
let adConfiguration = VideoControlsConfiguration()
XCTAssertEqual(adConfiguration.closeButtonArea, PrebidConstants.BUTTON_AREA_DEFAULT.doubleValue)
Expand Down
Loading