-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[MT-1504] Refresh and Reload improvements (#331)
* Make remote commands accept local paths with and without extension definition * Use constants for dle and tiq urls * Share a ResourceRetriever and ResourceRefresher for RemoteCommands and RemotePublishSettings Fix RemoteCommands issues: - load url remote commands successfully after others have been previously added - refresh remote commands on interval - fix cache usage for remote commands - use etag instead of if-not-modified-since - safely extract fileName from url - always use commandId to access different remote commands instead of a mix of commandId and fileName Fix ResourceRetriever to accept all 20x responses as correct * Add retry mechanism for ResourceRetriever and improve shouldRefresh checks in ResourceRefresher Move the should refresh entirely inside of the resource refresher Move the logging in the delegate calls instead * Fix refresh logic with wrong conditions Add delegate call for cached/bundle settings Fix old tests * Remove resource retriever forced refresh when not cached and add backoff for cooldown Interval * Make condition clearer for when to use local bundle RemoteCommand config * Use commandId instead of filename for remote commands cache and asset bundle for url remote commands Create an internal bundle option just for tests * Reorganize files * Improve VisitorServiceRetriever urlSession and completion calls * Simplify Resource Refresher error handling * Improve Collect urlSession and Completion calls * Test ResourceRetriever with a new MockURLSession * Fix ResourceRefresher Cooldown logic and add some tests * Add ResourceRefresher tests and create ErrorCooldown utility to help with tests * Improve and test ErrorCooldown Make sure that when errorCooldown is nil the normal refreshInterval is used * Remove settings from bundle option * Fix old remote commands manager tests * Fix collect completion * Fix remaining old tests for remote commands Remove MockRemoteCommandsDiskStorage * Add RemoteCommands tests for bundle and refreshes * Fix TagManagement flaky tests * Reload webview after session updates * Add some documentation and improve isFileCached * Fix comment spacing * Fix inAppPurchase tests * Improve readability of dynamicTrack and fix mock webview in tests * Try to use M1 mac on CICD * Fix wrong macos specification * Reset ErrorCooldown counter on non-errors * Make publishsettings tests more reliable * Ignore 304 errors from ResourceRetriever in ResourceRefresher's ErrorCooldown * Try to make Autotracking UI tests more reliable on slow CICD
- Loading branch information
Showing
57 changed files
with
1,528 additions
and
926 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
72 changes: 72 additions & 0 deletions
72
support/tests/test_tealium_core/network/ErrorCooldownTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
Oops, something went wrong.