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

[MT-1504] Refresh and Reload improvements #331

Merged
merged 33 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8eef183
Make remote commands accept local paths with and without extension de…
Enricoza Mar 21, 2024
79f81e0
Use constants for dle and tiq urls
Enricoza Mar 26, 2024
3a38bcd
Share a ResourceRetriever and ResourceRefresher for RemoteCommands an…
Enricoza Mar 26, 2024
36199bc
Add retry mechanism for ResourceRetriever and improve shouldRefresh c…
Enricoza Mar 28, 2024
1bb1965
Fix refresh logic with wrong conditions
Enricoza Apr 3, 2024
9abfc7c
Remove resource retriever forced refresh when not cached and add back…
Enricoza Apr 4, 2024
2cd3b72
Make condition clearer for when to use local bundle RemoteCommand config
Enricoza Apr 4, 2024
0d4dc83
Use commandId instead of filename for remote commands cache and asset…
Enricoza Apr 5, 2024
16fdaf9
Reorganize files
Enricoza Apr 5, 2024
44466d1
Improve VisitorServiceRetriever urlSession and completion calls
Enricoza Apr 5, 2024
b5955ef
Simplify Resource Refresher error handling
Enricoza Apr 5, 2024
a2f5ce9
Improve Collect urlSession and Completion calls
Enricoza Apr 5, 2024
7af2aad
Test ResourceRetriever with a new MockURLSession
Enricoza Apr 8, 2024
810c7e2
Fix ResourceRefresher Cooldown logic and add some tests
Enricoza Apr 8, 2024
e941a4b
Add ResourceRefresher tests and create ErrorCooldown utility to help …
Enricoza Apr 9, 2024
cc14be1
Improve and test ErrorCooldown
Enricoza Apr 10, 2024
62254b1
Remove settings from bundle option
Enricoza Apr 10, 2024
104c99f
Fix old remote commands manager tests
Enricoza Apr 10, 2024
2cacf9a
Fix collect completion
Enricoza Apr 10, 2024
cb3e492
Fix remaining old tests for remote commands
Enricoza Apr 10, 2024
9ba0b93
Add RemoteCommands tests for bundle and refreshes
Enricoza Apr 12, 2024
0fda51a
Fix TagManagement flaky tests
Enricoza Apr 12, 2024
ca99430
Reload webview after session updates
Enricoza Apr 15, 2024
1d92dfe
Add some documentation and improve isFileCached
Enricoza Apr 15, 2024
dfac7bb
Fix comment spacing
Enricoza Apr 16, 2024
eff227e
Fix inAppPurchase tests
Enricoza Apr 16, 2024
a52b0d2
Improve readability of dynamicTrack and fix mock webview in tests
Enricoza Apr 16, 2024
89a13c1
Try to use M1 mac on CICD
Enricoza Apr 17, 2024
08c8061
Fix wrong macos specification
Enricoza Apr 17, 2024
a79d1bb
Reset EccordCooldown counter on non-errors
Enricoza Apr 26, 2024
d7756a5
Make publishsettings tests more reliable
Enricoza Apr 29, 2024
fb1e7f2
Ignore 304 errors from ResourceRetriever in ResourceRefresher's Error…
Enricoza Apr 29, 2024
073631e
Try to make Autotracking UI tests more reliable on slow CICD
Enricoza Apr 29, 2024
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
14 changes: 7 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on: [pull_request]
jobs:
build_iOS:
name: Build iOS
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand Down Expand Up @@ -42,7 +42,7 @@ jobs:
working-directory: ${{ env.working-directory }}
build_macOS:
name: Build macOS
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand Down Expand Up @@ -74,7 +74,7 @@ jobs:
working-directory: ${{ env.working-directory }}
build_tvOS:
name: Build tvOS
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand Down Expand Up @@ -102,7 +102,7 @@ jobs:
working-directory: ${{ env.working-directory }}
build_TealiumSwiftExample_iOS:
name: Build TealiumSwiftExample iOS
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand All @@ -125,7 +125,7 @@ jobs:
working-directory: ${{ env.working-directory }}
build_TealiumSwiftExample_tvOS:
name: Build TealiumSwiftExample tvOS
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand All @@ -148,7 +148,7 @@ jobs:
working-directory: ${{ env.working-directory }}
build_ConsentManagerDemo:
name: Build ConsentManagerDemo
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand All @@ -171,7 +171,7 @@ jobs:
working-directory: ${{ env.working-directory }}
build_VisitorServiceDemo:
name: Build TealiumVisitorProfileDemo
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on: [pull_request]
jobs:
install:
name: Setup Fastlane
runs-on: macos-13
runs-on: macos-14
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
Expand All @@ -17,7 +17,7 @@ jobs:
test_iOS:
needs: install
name: iOS Tests
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand Down Expand Up @@ -79,7 +79,7 @@ jobs:
test_macOS:
needs: install
name: macOS Tests
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand Down Expand Up @@ -131,7 +131,7 @@ jobs:
test_tvOS:
needs: install
name: tvOS Tests
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand Down Expand Up @@ -199,7 +199,7 @@ jobs:
# working-directory: ${{ env.working-directory }}
test_Autotracking_iOS_uiTests:
name: Test TealiumAutotracking iOS UI Tests
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand All @@ -219,7 +219,7 @@ jobs:
test_Autotracking_macOS_uiTests:
needs: install
name: Test TealiumAutotracking macOS UI Tests
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand All @@ -239,7 +239,7 @@ jobs:
test_Autotracking_tvOS_uiTests:
needs: install
name: Test TealiumAutotracking tvOS UI Tests
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 60
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
Expand Down
166 changes: 138 additions & 28 deletions builder/tealium-swift.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

75 changes: 75 additions & 0 deletions support/tests/MockURLSession.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//
// MockURLSession.swift
// tealium-swift
//
// Created by Enrico Zannini on 08/04/24.
// Copyright © 2024 Tealium, Inc. All rights reserved.
//

import Foundation
import XCTest
@testable import TealiumCore

extension DataTaskResult {
private static func urlResponse(statusCode: Int, headerFields: [String: String]?) -> HTTPURLResponse? {
HTTPURLResponse(url: URL(string: "someURL")!, statusCode: statusCode, httpVersion: "1.1", headerFields: headerFields)
}
static func success(withData data: Data?, statusCode: Int = 200, headers: [String: String]? = nil) -> DataTaskResult {
return .success((urlResponse(statusCode: statusCode, headerFields: headers), data))
}
static func success<Obj: Codable>(with object: Obj, statusCode: Int = 200, headers: [String: String]? = nil) -> DataTaskResult {
return .success(withData: try? JSONEncoder().encode(object), statusCode: statusCode, headers: headers)
}
}

class MockURLSession: URLSessionProtocol {
var isInvalidated = false
var result: DataTaskResult?
@ToAnyObservable<TealiumReplaySubject<URLRequest>>(TealiumReplaySubject<URLRequest>())
var onRequestSent: TealiumObservable<URLRequest>

class MockDataTask: URLSessionDataTaskProtocol {
let completion: () -> Void
init(completion: @escaping () -> Void) {
self.completion = completion
}
func resume() {
completion()
}
}

func tealiumDataTask(with url: URL, completionHandler: @escaping DataTaskCompletion) -> URLSessionDataTaskProtocol {
let request = URLRequest(url: url)
_onRequestSent.publish(request)
return tealiumDataTask(with: request, completionHandler: completionHandler)

}

func tealiumDataTask(with request: URLRequest, completionHandler: @escaping DataTaskCompletion) -> URLSessionDataTaskProtocol {
_onRequestSent.publish(request)
return tealiumDataTask(with: request.url!) { result in
do {
let tuple = try result.get()
completionHandler(tuple.1, tuple.0, nil)
} catch {
completionHandler(nil, nil, error)
}
}
}

func tealiumDataTask(with url: URL, completionHandler: @escaping (DataTaskResult) -> Void) -> URLSessionDataTaskProtocol {
MockDataTask {
guard let result = self.result else {
XCTFail("MockURLSession called with with no result")
return
}
completionHandler(result)
}
}

func finishTealiumTasksAndInvalidate() {
isInvalidated = true
}


}
2 changes: 1 addition & 1 deletion support/tests/TestTealiumHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var testOptionalData = [TealiumTestKey.stringKey: TealiumTestValue.stringValue,
let testTealiumConfig: TealiumConfig = TealiumConfig(account: TealiumTestValue.account,
profile: TealiumTestValue.profile,
environment: TealiumTestValue.environment,
options: testOptionalData as [String: Any])
options: testOptionalData)

let testTrackRequest = TealiumTrackRequest(data: [:])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ extension XCUIApplication {
let predicate = NSPredicate(format: "value CONTAINS[c] %@ || label CONTAINS[c] %@", text, text) // don't know why value works for macOS and label for iOS and tvOS
XCTAssertTrue(staticTexts
.containing(predicate).firstMatch
.waitForExistence(timeout: 5),
"Can not find \(text)")
.waitForExistence(timeout: 25), "Can not find \(text)")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class DataLayerTests: XCTestCase {

func testInsertSingleExpiresAfterASecond() {
eventData = Set<DataLayerItem>()
eventData.insert(key: "itemOne", value: "test1", expiry: .after(Date().addSeconds(1)!))
eventData.insert(key: "itemOne", value: "test1", expiry: .after(Date().addingTimeInterval(1)))
var eventDataExpired = eventData.removeExpired()
XCTAssertEqual(eventDataExpired.count, 1)
let exp = expectation(description: "waiting")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,23 @@ class MockDataLayerManager: DataLayerManagerProtocol {
var deleteSingleCount = 0
var deleteMultiCount = 0
var deleteAllCount = 0
var onDataUpdated: TealiumObservable<[String : Any]> = TealiumPublisher<[String:Any]>().asObservable()
var _onDataUpdated = TealiumPublisher<[String:Any]>()
var onDataUpdated: TealiumObservable<[String : Any]> { _onDataUpdated.asObservable() }
var onDataRemoved: TealiumObservable<[String]> = TealiumPublisher<[String]>().asObservable()
var all: [String: Any] {
get {
["all": "eventdata"]
}
set {
self.add(data: newValue, expiration: .forever)
}
}
var all: [String: Any] = ["all": "eventdata"]

var allSessionData: [String: Any] {
["all": "sessiondata"]
}
var allSessionData: [String: Any] = ["all": "sessiondata"]

var minutesBetweenSessionIdentifier: TimeInterval = 1.0

var secondsBetweenTrackEvents: TimeInterval = 1.0

var sessionId: String? {
get {
"testsessionid"
all[TealiumDataKey.sessionId] as? String
}
set {
self.add(data: ["sessionId": newValue!], expiration: .session)
self.add(data: [TealiumDataKey.sessionId: newValue as Any], expiration: .session)
}
}

Expand All @@ -61,10 +53,16 @@ class MockDataLayerManager: DataLayerManagerProtocol {

func add(data: [String: Any], expiration: Expiry) {
addMultiCount += 1
for kv in data {
all[kv.key] = kv.value
}
_onDataUpdated.publish(data)
}

func add(key: String, value: Any, expiration: Expiry) {
addSingleCount += 1
all[key] = value
_onDataUpdated.publish([key: value])
}

func joinTrace(id: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class SessionStarterTests: XCTestCase {

func testSessionURL() {
let sessionURL = sessionStarter.sessionURL
XCTAssertEqual(true, sessionURL.hasPrefix("https://tags.tiqcdn.com/utag/tiqapp/utag.v.js?a=ssTestAccount/ssTestProfile/"))
XCTAssertTrue(sessionURL.hasPrefix("https://tags.tiqcdn.com/utag/tiqapp/utag.v.js?a=ssTestAccount/ssTestProfile/"))
}

func testRequestSessionSuccessful() {
Expand Down
72 changes: 72 additions & 0 deletions support/tests/test_tealium_core/network/ErrorCooldownTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//
// ErrorCooldownTests.swift
// tealium-swift
//
// Created by Enrico Zannini on 09/04/24.
// Copyright © 2024 Tealium, Inc. All rights reserved.
//

import XCTest
@testable import TealiumCore

final class ErrorCooldownTests: XCTestCase {
let errorCooldown = ErrorCooldown(baseInterval: 10, maxInterval: 50)!

func testStartsNotInCooldown() {
XCTAssertFalse(errorCooldown.isInCooldown(lastFetch: Date()))
}

func testGoesInCooldownAfterError() {
errorCooldown.newCooldownEvent(error: HTTPError.unknown)
XCTAssertTrue(errorCooldown.isInCooldown(lastFetch: Date()))
}

func testCooldownEndsAfterErrorBaseInterval() {
errorCooldown.newCooldownEvent(error: HTTPError.unknown)
XCTAssertTrue(errorCooldown.isInCooldown(lastFetch: Date()))
XCTAssertFalse(errorCooldown.isInCooldown(lastFetch: Date().addingTimeInterval(-11)))
}

func testCooldownIncreasesAfterNewErrors() {
errorCooldown.newCooldownEvent(error: HTTPError.unknown)
XCTAssertTrue(errorCooldown.isInCooldown(lastFetch: Date()))
errorCooldown.newCooldownEvent(error: HTTPError.unknown)
XCTAssertTrue(errorCooldown.isInCooldown(lastFetch: Date().addingTimeInterval(-11)))
XCTAssertFalse(errorCooldown.isInCooldown(lastFetch: Date().addingTimeInterval(-21)))
}

func testCooldownCantBeOverMaxInterval() {
for _ in 0..<7 {
errorCooldown.newCooldownEvent(error: HTTPError.unknown)
}
XCTAssertTrue(errorCooldown.isInCooldown(lastFetch: Date().addingTimeInterval(-49)))
XCTAssertFalse(errorCooldown.isInCooldown(lastFetch: Date().addingTimeInterval(-51)))
}

func testCooldownIsResetOnSuccessEvent() {
for _ in 0..<7 {
errorCooldown.newCooldownEvent(error: HTTPError.unknown)
}
XCTAssertTrue(errorCooldown.isInCooldown(lastFetch: Date().addingTimeInterval(-49)))
XCTAssertFalse(errorCooldown.isInCooldown(lastFetch: Date().addingTimeInterval(-51)))
errorCooldown.newCooldownEvent(error: nil)
XCTAssertFalse(errorCooldown.isInCooldown(lastFetch: Date()))
}

func testCooldownIsOnBaseValueAfterBeingReset() {
for _ in 0..<7 {
errorCooldown.newCooldownEvent(error: HTTPError.unknown)
}
XCTAssertTrue(errorCooldown.isInCooldown(lastFetch: Date().addingTimeInterval(-49)))
XCTAssertFalse(errorCooldown.isInCooldown(lastFetch: Date().addingTimeInterval(-51)))
errorCooldown.newCooldownEvent(error: nil)
errorCooldown.newCooldownEvent(error: HTTPError.unknown)
XCTAssertTrue(errorCooldown.isInCooldown(lastFetch: Date().addingTimeInterval(-9)))
XCTAssertFalse(errorCooldown.isInCooldown(lastFetch: Date().addingTimeInterval(-11)))
}

func testInitializationFailsWithoutBaseInterval() {
let errorCooldown = ErrorCooldown(baseInterval: nil, maxInterval: 50)
XCTAssertNil(errorCooldown)
}
}
Loading
Loading