Pin external actions, images, toolchains, native archives, and tvOS engine artifacts; enforce fail-closed CI checks and keep website privacy disclosures aligned with shipped behavior.
90 lines
3.6 KiB
Swift
90 lines
3.6 KiB
Swift
import XCTest
|
|
@testable import Runner
|
|
|
|
final class TvosEventDeliveryCoordinatorTests: XCTestCase {
|
|
func testColdLaunchTransitionsToLiveWithoutChangingFlutterEnvelope() {
|
|
var now: TimeInterval = 10
|
|
let coordinator = TvosDeepLinkDeliveryCoordinator(now: { now })
|
|
|
|
XCTAssertEqual(coordinator.receive(contentId: "server:item"), .retained)
|
|
let launchEvent = try! XCTUnwrap(coordinator.beginLiveDelivery())
|
|
XCTAssertEqual(launchEvent.contentId, "server:item")
|
|
XCTAssertEqual(launchEvent.flutterArguments, ["contentId": "server:item"])
|
|
XCTAssertNil(coordinator.complete(launchEvent, succeeded: true))
|
|
XCTAssertNil(coordinator.retainedContentId)
|
|
|
|
now += 0.5
|
|
XCTAssertEqual(coordinator.receive(contentId: "server:item"), .duplicate)
|
|
}
|
|
|
|
func testFailedLiveDeliveryRemainsRetainedAndRetryable() {
|
|
var now: TimeInterval = 20
|
|
let coordinator = TvosDeepLinkDeliveryCoordinator(now: { now })
|
|
XCTAssertNil(coordinator.beginLiveDelivery())
|
|
|
|
guard case let .deliver(first) = coordinator.receive(contentId: "server:item") else {
|
|
return XCTFail("Expected live delivery")
|
|
}
|
|
XCTAssertNil(coordinator.complete(first, succeeded: false))
|
|
XCTAssertEqual(coordinator.retainedContentId, "server:item")
|
|
|
|
now += 0.1
|
|
guard case let .deliver(retry) = coordinator.receive(contentId: "server:item") else {
|
|
return XCTFail("Expected failed delivery to retry")
|
|
}
|
|
XCTAssertEqual(retry, first)
|
|
XCTAssertNil(coordinator.complete(retry, succeeded: true))
|
|
XCTAssertNil(coordinator.retainedContentId)
|
|
}
|
|
|
|
func testDeduplicationWindowExpiresForASecondDeliberateTap() {
|
|
var now: TimeInterval = 30
|
|
let coordinator = TvosDeepLinkDeliveryCoordinator(deduplicationWindow: 2, now: { now })
|
|
XCTAssertNil(coordinator.beginLiveDelivery())
|
|
|
|
guard case let .deliver(first) = coordinator.receive(contentId: "server:item") else {
|
|
return XCTFail("Expected first delivery")
|
|
}
|
|
_ = coordinator.complete(first, succeeded: true)
|
|
|
|
now += 1.99
|
|
XCTAssertEqual(coordinator.receive(contentId: "server:item"), .duplicate)
|
|
now += 0.02
|
|
guard case let .deliver(second) = coordinator.receive(contentId: "server:item") else {
|
|
return XCTFail("Expected delivery after bounded window")
|
|
}
|
|
XCTAssertNotEqual(second, first)
|
|
}
|
|
|
|
func testInFlightDeliveryCoalescesDuplicateAndThenDeliversNewestEvent() {
|
|
var now: TimeInterval = 40
|
|
let coordinator = TvosDeepLinkDeliveryCoordinator(now: { now })
|
|
XCTAssertNil(coordinator.beginLiveDelivery())
|
|
|
|
guard case let .deliver(first) = coordinator.receive(contentId: "server:first") else {
|
|
return XCTFail("Expected first delivery")
|
|
}
|
|
now += 0.1
|
|
XCTAssertEqual(coordinator.receive(contentId: "server:first"), .duplicate)
|
|
XCTAssertEqual(coordinator.receive(contentId: "server:second"), .retained)
|
|
|
|
let second = try! XCTUnwrap(coordinator.complete(first, succeeded: true))
|
|
XCTAssertEqual(second.contentId, "server:second")
|
|
XCTAssertNil(coordinator.complete(second, succeeded: true))
|
|
XCTAssertNil(coordinator.retainedContentId)
|
|
}
|
|
|
|
func testEngineRebindRetainsLaunchEventAndRequiresInitialReadAgain() {
|
|
let coordinator = TvosDeepLinkDeliveryCoordinator(now: { 50 })
|
|
XCTAssertNil(coordinator.beginLiveDelivery())
|
|
guard case let .deliver(event) = coordinator.receive(contentId: "server:item") else {
|
|
return XCTFail("Expected live delivery")
|
|
}
|
|
XCTAssertNil(coordinator.complete(event, succeeded: false))
|
|
|
|
coordinator.bindEngine()
|
|
XCTAssertEqual(coordinator.receive(contentId: "server:item"), .duplicate)
|
|
XCTAssertEqual(coordinator.beginLiveDelivery()?.contentId, "server:item")
|
|
}
|
|
}
|