Skip to content

Commit

Permalink
5.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
unity-thull committed Nov 5, 2021
1 parent 640feaf commit 7992792
Show file tree
Hide file tree
Showing 19 changed files with 573 additions and 8 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Change Log

## [5.0.0](https://github.com/deltaDNA/ios-sdk/releases/tag/5.0.0)
### New

**Breaking Change**: New APIs provided for checking if PIPL consent is required, and recording users' consent. Note that
it is now required to check if PIPL consent is required, and provide that consent if necessary, before collect and engage
requests will be sent from the SDK.


## [4.13.3](https://github.com/deltaDNA/ios-sdk/releases/tag/4.13.3) (2021-10-06)
### Fixed
- Event Triggered Campaigns will now respect repeat and interval triggers
Expand Down
178 changes: 178 additions & 0 deletions Consent/DDNAConsentTrackerTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import Foundation
import XCTest
@testable import DeltaDNA

class DDNAConsentTrackerTests: XCTestCase {
var consentTracker: DDNAConsentTracker!
var userDefaults: UserDefaults!
var geoIPMock: GeoIpNetworkClientMock!

override func setUp() {
let userDefaultDomain = "com.deltadna.test.consenttracker"
UserDefaults().removePersistentDomain(forName: userDefaultDomain)
userDefaults = UserDefaults(suiteName: userDefaultDomain)

geoIPMock = GeoIpNetworkClientMock()

consentTracker = DDNAConsentTracker(userDefaults: userDefaults, geoIpNetworkClient: geoIPMock)
}

// MARK: isPiplConsentRequired

func test_whenCheckingIfConsentIsRequired_noPreviousResponse_andGeoIpReturnsResponseNotInChina_consentIsNotRequired() {
let expectationToCheck = expectation(description: "Waiting for callback to complete")

geoIPMock.responseToReturn = GeoIpResponse(identifier: "gdpr", country: "uk", region: "scotland", ageGateLimit: 13)

consentTracker.isPiplConsentRequired(callback: { isRequired, error in
XCTAssertNil(error)
XCTAssertFalse(isRequired)
expectationToCheck.fulfill()
})

waitForExpectations(timeout: 3, handler: { error in
if let error = error {
XCTFail("\(error)")
}
})
}

func test_whenCheckingIfConsentIsRequired_noPreviousResponse_andGeoIpReturnsResponseInChina_consentIsRequired() {
let expectationToCheck = expectation(description: "Waiting for callback to complete")
geoIPMock.responseToReturn = GeoIpResponse(identifier: "pipl", country: "cn", region: "beijing", ageGateLimit: 13)

consentTracker.isPiplConsentRequired(callback: { isRequired, error in
XCTAssertNil(error)
XCTAssertTrue(isRequired)
expectationToCheck.fulfill()
})

waitForExpectations(timeout: 3, handler: { error in
if let error = error {
XCTFail("\(error)")
}
})
}

func test_whenCheckingIfConsentIsRequired_andNotBothPreviousResponseIsRecorded_andGeoIpReturnsResponseInChina_consentCheckIsRequired() {
let expectationToCheck = expectation(description: "Waiting for callback to complete")
geoIPMock.responseToReturn = GeoIpResponse(identifier: "pipl", country: "cn", region: "beijing", ageGateLimit: 13)
userDefaults.set(ConsentStatus.consentGiven.rawValue, forKey: "ddnaPiplUseStatus")

consentTracker.isPiplConsentRequired(callback: { isRequired, error in
XCTAssertNil(error)
XCTAssertTrue(isRequired)
expectationToCheck.fulfill()
})

waitForExpectations(timeout: 3, handler: { error in
if let error = error {
XCTFail("\(error)")
}
})
}

func test_whenCheckingIfConsentIsRequired_andBothPreviousResponseIsRecorded_consentCheckIsNotRequired() {
let expectationToCheck = expectation(description: "Waiting for callback to complete")
geoIPMock.responseToReturn = GeoIpResponse(identifier: "pipl", country: "cn", region: "beijing", ageGateLimit: 13)
userDefaults.set(ConsentStatus.consentGiven.rawValue, forKey: "ddnaPiplUseStatus")
userDefaults.set(ConsentStatus.consentGiven.rawValue, forKey: "ddnaPiplExportStatus")

consentTracker.isPiplConsentRequired(callback: { isRequired, error in
XCTAssertNil(error)
XCTAssertTrue(isRequired)
expectationToCheck.fulfill()
})

waitForExpectations(timeout: 3, handler: { error in
if let error = error {
XCTFail("\(error)")
}
})
}

// MARK: hasCheckedForConsent

func test_whenCheckingIfConsentHasBeenChecked_andNoConsentsAreChecked_returnsFalse() {
consentTracker.piplUseStatus = .unknown
consentTracker.piplExportStatus = .unknown

XCTAssertFalse(consentTracker.hasCheckedForConsent())
}

func test_whenCheckingIfConsentHasBeenChecked_andExportIsNotChecked_returnsFalse() {
consentTracker.piplUseStatus = .notRequired
consentTracker.piplExportStatus = .unknown

XCTAssertFalse(consentTracker.hasCheckedForConsent())
}

func test_whenCheckingIfConsentHasBeenChecked_andStatusIsNotChecked_returnsFalse() {
consentTracker.piplUseStatus = .unknown
consentTracker.piplExportStatus = .notRequired

XCTAssertFalse(consentTracker.hasCheckedForConsent())
}

func test_whenCheckingIfConsentHasBeenChecked_andBothHaveBeenChecked_returnsTrue() {
consentTracker.piplUseStatus = .consentGiven
consentTracker.piplExportStatus = .consentDenied

XCTAssertTrue(consentTracker.hasCheckedForConsent())
}

// MARK: setPiplUseConsent

func test_whenSettingUserConsent_andConsentIsProvided_theCorrectConsentIsSaved() {
consentTracker.setPiplUseConsent(true)

XCTAssertEqual(ConsentStatus.consentGiven.rawValue, userDefaults.integer(forKey: "ddnaPiplUseStatus"))
XCTAssertEqual(ConsentStatus.consentGiven, consentTracker.piplUseStatus)
}

func test_whenSettingUserConsent_andConsentIsNotProvided_theCorrectConsentIsSaved() {
consentTracker.setPiplUseConsent(false)

XCTAssertEqual(ConsentStatus.consentDenied.rawValue, userDefaults.integer(forKey: "ddnaPiplUseStatus"))
XCTAssertEqual(ConsentStatus.consentDenied, consentTracker.piplUseStatus)
}

// MARK: setPiplExportConsent

func test_whenSettingUserExportConsent_andConsentIsProvided_theCorrectConsentIsSaved() {
consentTracker.setPiplExportConsent(true)

XCTAssertEqual(ConsentStatus.consentGiven.rawValue, userDefaults.integer(forKey: "ddnaPiplExportStatus"))
XCTAssertEqual(ConsentStatus.consentGiven, consentTracker.piplExportStatus)
}

func test_whenSettingUserExportConsent_andConsentIsNotProvided_theCorrectConsentIsSaved() {
consentTracker.setPiplExportConsent(false)

XCTAssertEqual(ConsentStatus.consentDenied.rawValue, userDefaults.integer(forKey: "ddnaPiplExportStatus"))
XCTAssertEqual(ConsentStatus.consentDenied, consentTracker.piplExportStatus)
}

// MARK: allConsentsAreMet

func test_whenCheckingAllConsentsAreMet_IfNoneAreMet_returnsFalse() {
consentTracker.piplExportStatus = .consentDenied
consentTracker.piplUseStatus = .unknown

XCTAssertFalse(consentTracker.allConsentsAreMet())
}

func test_whenCheckingAllConsentsAreMet_IfSomeAreMet_returnsFalse() {
consentTracker.piplExportStatus = .consentGiven
consentTracker.piplUseStatus = .unknown

XCTAssertFalse(consentTracker.allConsentsAreMet())
}

func test_whenCheckingAllConsentsAreMet_IfAllAreMet_returnsTrue() {
consentTracker.piplExportStatus = .consentGiven
consentTracker.piplUseStatus = .consentGiven

XCTAssertTrue(consentTracker.allConsentsAreMet())
}
}
85 changes: 85 additions & 0 deletions Consent/GeoIpNetworkClientTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import Foundation
import XCTest
@testable import DeltaDNA

class URLSessionDataTaskMock: URLSessionDataTask {
override func resume() {
// Do nothing
}
}

class URLSessionWithDataTaskMock: URLSessionDataTaskProtocol {
var dataToReturn: Data?
var error: Error?

func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask {
completionHandler(dataToReturn, nil, error)
return URLSessionDataTaskMock() // Deprecated, but doesn't really matter as we don't use this return value
}
}

class GeoIpNetworkClientTests: XCTestCase {
var geoIpClient: GeoIpNetworkClient!
var urlSessionMock: URLSessionWithDataTaskMock!

override func setUp() {
urlSessionMock = URLSessionWithDataTaskMock()
geoIpClient = GeoIpNetworkClient(urlSession: urlSessionMock)
}

func test_ifErrorIsReturned_correctCallbackParamsAreReturned() {
let expectationToCheck = expectation(description: "Ensure callback is called")

urlSessionMock.error = URLError(.notConnectedToInternet)

geoIpClient.fetchGeoIpResponse {(response, error) in
XCTAssertNil(response)
XCTAssertEqual((error as? URLError)?.code, URLError.Code.notConnectedToInternet)
expectationToCheck.fulfill()
}

waitForExpectations(timeout: 3) { error in
if let error = error {
XCTFail("\(error)")
}
}
}

func test_ifResponseIsReturned_correctCallbackParamsAreReturned() {
let expectationToCheck = expectation(description: "Ensure callback is called")

let responseObject = GeoIpResponse(identifier: "pipl", country: "cn", region: "beijing", ageGateLimit: 13)
urlSessionMock.dataToReturn = try! JSONEncoder().encode(responseObject)

geoIpClient.fetchGeoIpResponse {(response, error) in
XCTAssertEqual(responseObject.identifier, response?.identifier)
XCTAssertNil(error)
expectationToCheck.fulfill()
}

waitForExpectations(timeout: 3) { error in
if let error = error {
XCTFail("\(error)")
}
}
}

func test_ifInvalidResponseIsReturned_correctCallbackParamsAreReturned() {
let expectationToCheck = expectation(description: "Ensure callback is called")

let responseObject = ["notAValidObject": 1234]
urlSessionMock.dataToReturn = try! JSONEncoder().encode(responseObject)

geoIpClient.fetchGeoIpResponse {(response, error) in
XCTAssertNil(response)
XCTAssertNotNil(error)
expectationToCheck.fulfill()
}

waitForExpectations(timeout: 3) { error in
if let error = error {
XCTFail("\(error)")
}
}
}
}
4 changes: 2 additions & 2 deletions DeltaDNA.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Pod::Spec.new do |spec|

# Spec Metadata
spec.name = "DeltaDNA"
spec.version = "4.13.3"
spec.version = "5.0.0"
spec.summary = "A gaming analytics platform."

spec.homepage = "https://deltadna.com"
Expand All @@ -18,7 +18,7 @@ Pod::Spec.new do |spec|
spec.platform = :ios

# Source Location
spec.source = { :http => "https://github.com/deltaDNA/ios-sdk/releases/download/4.13.3/DeltaDNA-4.13.3.zip" }
spec.source = { :http => "https://github.com/deltaDNA/ios-sdk/releases/download/5.0.0/DeltaDNA-5.0.0.zip" }

# Source Code
spec.vendored_frameworks = 'build/Frameworks/DeltaDNA.xcframework'
Expand Down
Loading

0 comments on commit 7992792

Please sign in to comment.