Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: added region support in NSE #836

Merged
merged 3 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
17 changes: 17 additions & 0 deletions Sources/MessagingPush/Config/MessagingPushConfigBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class MessagingPushConfigBuilder {

// configuration options for MessagingPushConfigOptions
private let cdpApiKey: String
private var region: Region = .US
private var autoFetchDeviceToken: Bool = true
private var autoTrackPushEvents: Bool = true
private var showPushAppInForeground: Bool = true
Expand All @@ -54,6 +55,17 @@ public class MessagingPushConfigBuilder {
self.cdpApiKey = cdpApiKey
}

/// Configures the region for NotificationServiceExtension for metric tracking
@discardableResult
@available(iOS, unavailable)
@available(visionOS, unavailable)
@available(iOSApplicationExtension, introduced: 13.0)
@available(visionOSApplicationExtension, introduced: 1.0)
public func region(_ region: Region) -> MessagingPushConfigBuilder {
self.region = region
return self
}

/// Configures the log level for NotificationServiceExtension, allowing customization of SDK log
/// verbosity to help setup and debugging
@discardableResult
Expand Down Expand Up @@ -94,6 +106,7 @@ public class MessagingPushConfigBuilder {
let configOptions = MessagingPushConfigOptions(
logLevel: logLevel,
cdpApiKey: cdpApiKey,
region: region,
autoFetchDeviceToken: autoFetchDeviceToken,
autoTrackPushEvents: autoTrackPushEvents,
showPushAppInForeground: showPushAppInForeground
Expand All @@ -106,6 +119,7 @@ public class MessagingPushConfigBuilder {
public extension MessagingPushConfigBuilder {
/// Constants used to map each of the options in MessagingPushConfigOptions.
enum Keys: String {
case region
case autoFetchDeviceToken
case autoTrackPushEvents
case showPushAppInForeground
Expand All @@ -116,6 +130,9 @@ public extension MessagingPushConfigBuilder {
static func build(from dictionary: [String: Any]) -> MessagingPushConfigOptions {
let builder = MessagingPushConfigBuilder()

if let region = dictionary[Keys.region.rawValue] as? String {
builder.region = Region.getRegion(from: region)
}
if let autoFetchDeviceToken = dictionary[Keys.autoFetchDeviceToken.rawValue] as? Bool {
builder.autoFetchDeviceToken(autoFetchDeviceToken)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import CioInternalCommon
public struct MessagingPushConfigOptions {
public let logLevel: CioLogLevel
public let cdpApiKey: String
public let region: Region
public let autoFetchDeviceToken: Bool
public let autoTrackPushEvents: Bool
public let showPushAppInForeground: Bool
Expand Down
4 changes: 3 additions & 1 deletion Sources/MessagingPush/RichPush/RichPushDeliveryTracker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
class RichPushDeliveryTracker {
let httpClient: HttpClient
let logger: Logger
let region: Region

init(httpClient: HttpClient, logger: Logger) {
self.httpClient = httpClient
self.logger = logger
self.region = MessagingPush.moduleConfig.region

Check warning on line 13 in Sources/MessagingPush/RichPush/RichPushDeliveryTracker.swift

View check run for this annotation

Codecov / codecov/patch

Sources/MessagingPush/RichPush/RichPushDeliveryTracker.swift#L13

Added line #L13 was not covered by tests
}

func trackMetric(token: String, event: Metric, deliveryId: String, timestamp: String? = nil, onComplete: @escaping (Result<Void, HttpRequestError>) -> Void) {
Expand All @@ -25,7 +27,7 @@
let endpoint: CIOApiEndpoint = .trackPushMetricsCdp
guard let httpParams = HttpRequestParams(
endpoint: endpoint,
baseUrl: RichPushHttpClient.defaultAPIHost,
baseUrl: RichPushHttpClient.getDefaultApiHost(region: region),

Check warning on line 30 in Sources/MessagingPush/RichPush/RichPushDeliveryTracker.swift

View check run for this annotation

Codecov / codecov/patch

Sources/MessagingPush/RichPush/RichPushDeliveryTracker.swift#L30

Added line #L30 was not covered by tests
headers: nil,
body: try? JSONSerialization.data(withJSONObject: properties)
) else {
Expand Down
15 changes: 12 additions & 3 deletions Sources/MessagingPush/RichPush/RichPushHttpClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public class RichPushHttpClient: HttpClient {
[cioApiSession, publicSession]
}

private let region: Region

public func request(_ params: CioInternalCommon.HttpRequestParams, onComplete: @escaping (Result<Data, CioInternalCommon.HttpRequestError>) -> Void) {
httpRequestRunner
.request(
Expand Down Expand Up @@ -57,7 +59,7 @@ public class RichPushHttpClient: HttpClient {
}

func getSessionForRequest(url: URL) -> URLSession {
let cioApiHostname = URL(string: Self.defaultAPIHost)!.host
let cioApiHostname = URL(string: Self.getDefaultApiHost(region: region))!.host
let requestHostname = url.host
let isRequestToCIOApi = cioApiHostname == requestHostname

Expand Down Expand Up @@ -123,7 +125,7 @@ public class RichPushHttpClient: HttpClient {
self.httpRequestRunner = httpRequestRunner
self.jsonAdapter = jsonAdapter
self.logger = logger

self.region = MessagingPush.moduleConfig.region
self.publicSession = Self.getBasicSession()
self.cioApiSession = Self.getCIOApiSession(
key: MessagingPush.moduleConfig.cdpApiKey,
Expand All @@ -137,7 +139,14 @@ public class RichPushHttpClient: HttpClient {
}

extension RichPushHttpClient {
public static let defaultAPIHost = "https://cdp.customer.io/v1"
static func getDefaultApiHost(region: Region) -> String {
mrehan27 marked this conversation as resolved.
Show resolved Hide resolved
switch region {
case .US:
"https://cdp.customer.io/v1"
case .EU:
"https://cdp-eu.customer.io/v1"
}
}

static func authorizationHeaderForCdpApiKey(_ key: String) -> String {
var returnHeader = "\(key):"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@testable import CioInternalCommon
@testable import CioMessagingPush
import SharedTests
import XCTest
Expand Down Expand Up @@ -41,14 +42,16 @@ class MessagingPushConfigBuilderTest: UnitTest {
let givenDict: [String: Any] = [
"autoFetchDeviceToken": givenAutoFetchDeviceToken,
"autoTrackPushEvents": givenAutoTrackPushEvents,
"showPushAppInForeground": givenShowPushAppInForeground
"showPushAppInForeground": givenShowPushAppInForeground,
"region": "EU"
]

let config = MessagingPushConfigBuilder.build(from: givenDict)

XCTAssertEqual(config.autoFetchDeviceToken, givenAutoFetchDeviceToken)
XCTAssertEqual(config.autoTrackPushEvents, givenAutoTrackPushEvents)
XCTAssertEqual(config.showPushAppInForeground, givenShowPushAppInForeground)
XCTAssertEqual(config.region, Region.EU)
}

func test_initializeFromDictionaryWithIncorrectKeys_expectDefaultValues() {
Expand Down Expand Up @@ -83,5 +86,6 @@ extension MessagingPushConfigBuilderTest {
XCTAssertTrue(config.autoFetchDeviceToken, file: file, line: line)
XCTAssertTrue(config.autoTrackPushEvents, file: file, line: line)
XCTAssertTrue(config.showPushAppInForeground, file: file, line: line)
XCTAssertEqual(config.region, Region.US, file: file, line: line)
}
}
78 changes: 71 additions & 7 deletions Tests/MessagingPush/HttpClientTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ class HttpClientTest: UnitTest {

private let url = URL(string: "https://customer.io")!

override func setUp() {
super.setUp()
override func setUp(
enableLogs: Bool = false,
modifyModuleConfig: ((MessagingPushConfigBuilder) -> Void)? = nil
) {
super.setUp(enableLogs: enableLogs, modifyModuleConfig: modifyModuleConfig)

client = RichPushHttpClient(
jsonAdapter: jsonAdapter,
Expand Down Expand Up @@ -45,7 +48,7 @@ class HttpClientTest: UnitTest {
let expectComplete = expectation(description: "Expect to complete")
let params = HttpRequestParams(
endpoint: .trackPushMetricsCdp,
baseUrl: RichPushHttpClient.defaultAPIHost,
baseUrl: RichPushHttpClient.getDefaultApiHost(region: Region.US),
headers: nil,
body: nil
)!
Expand All @@ -71,7 +74,7 @@ class HttpClientTest: UnitTest {
let expectComplete = expectation(description: "Expect to complete")
let params = HttpRequestParams(
endpoint: .trackPushMetricsCdp,
baseUrl: RichPushHttpClient.defaultAPIHost,
baseUrl: RichPushHttpClient.getDefaultApiHost(region: Region.US),
headers: nil,
body: nil
)!
Expand All @@ -95,7 +98,7 @@ class HttpClientTest: UnitTest {
let expectComplete = expectation(description: "Expect to complete")
let params = HttpRequestParams(
endpoint: .trackPushMetricsCdp,
baseUrl: RichPushHttpClient.defaultAPIHost,
baseUrl: RichPushHttpClient.getDefaultApiHost(region: Region.US),
headers: nil,
body: nil
)!
Expand All @@ -111,6 +114,41 @@ class HttpClientTest: UnitTest {
waitForExpectations()
}

@available(iOS, unavailable)
@available(visionOS, unavailable)
@available(iOSApplicationExtension, introduced: 13.0)
@available(visionOSApplicationExtension, introduced: 1.0)
func test_request_givenEuRegion_expectRequestToBeMade() {
super.setUp(modifyModuleConfig: { config in
config.region(Region.EU)
})

let expected = #"{ "message": "Success!" }"#.data!

mockRequestResponse {
(body: expected, response: HTTPURLResponse(url: self.url, statusCode: 200, httpVersion: nil, headerFields: nil), failure: nil)
}

let expectComplete = expectation(description: "Expect to complete")
let params = HttpRequestParams(
endpoint: .trackPushMetricsCdp,
baseUrl: RichPushHttpClient.getDefaultApiHost(region: messagingPushConfigOptions.region),
headers: nil,
body: nil
)!
client.request(params) { result in
XCTAssertTrue(self.requestRunnerMock.requestCalled)

XCTAssertNil(result.error)

XCTAssertEqual(result.success, expected)

expectComplete.fulfill()
}

waitForExpectations()
}

func test_request_givenSuccessfulResponse_expectGetResponseBody() {
let expected = #"{ "message": "Success!" }"#.data!

Expand All @@ -121,7 +159,7 @@ class HttpClientTest: UnitTest {
let expectComplete = expectation(description: "Expect to complete")
let params = HttpRequestParams(
endpoint: .trackPushMetricsCdp,
baseUrl: RichPushHttpClient.defaultAPIHost,
baseUrl: RichPushHttpClient.getDefaultApiHost(region: messagingPushConfigOptions.region),
headers: nil,
body: nil
)!
Expand Down Expand Up @@ -151,7 +189,28 @@ class HttpClientTest: UnitTest {
func test_getSessionForRequest_givenCIOApiEndpoint_expectGetCIOApiSession() {
let cioApiEndpointUrl = HttpRequestParams(
endpoint: .trackPushMetricsCdp,
baseUrl: RichPushHttpClient.defaultAPIHost,
baseUrl: RichPushHttpClient.getDefaultApiHost(region: Region.US),
headers: nil,
body: nil
)!.url

let actualSession = client.getSessionForRequest(url: cioApiEndpointUrl)

let containsAuthorizationHeader = actualSession.configuration.httpAdditionalHeaders!["Authorization"] != nil
XCTAssertTrue(containsAuthorizationHeader)
}

@available(iOS, unavailable)
@available(visionOS, unavailable)
@available(iOSApplicationExtension, introduced: 13.0)
@available(visionOSApplicationExtension, introduced: 1.0)
func test_getSessionForRequest_givenCIOEUApiEndpoint_expectGetCIOApiSession() {
setUp(modifyModuleConfig: { config in
config.region(.EU)
})
let cioApiEndpointUrl = HttpRequestParams(
endpoint: .trackPushMetricsCdp,
baseUrl: RichPushHttpClient.getDefaultApiHost(region: Region.EU),
headers: nil,
body: nil
)!.url
Expand All @@ -162,6 +221,11 @@ class HttpClientTest: UnitTest {
XCTAssertTrue(containsAuthorizationHeader)
}

func test_getDefaultApiHost_givenRegion_expectCorrectApiHost() {
XCTAssertEqual(RichPushHttpClient.getDefaultApiHost(region: .US), "https://cdp.customer.io/v1")
XCTAssertEqual(RichPushHttpClient.getDefaultApiHost(region: .EU), "https://cdp-eu.customer.io/v1")
}

func test_getSessionForRequest_givenCIOAssetLibraryEndpoint_expectPublicSession() {
let actualSession = client.getSessionForRequest(url: URL(string: "https://storage.googleapis.com/cio-asset-manager-standalone/1670599791846_frederick_adoption_day.jpg")!)

Expand Down
Loading