mirror of
https://github.com/wu736139669/hapi.git
synced 2026-10-12 20:07:31 +00:00
101 lines
4.4 KiB
Swift
101 lines
4.4 KiB
Swift
import HapiClient
|
|
import HapiProtocol
|
|
import SwiftUI
|
|
import XCTest
|
|
@testable import Hapi
|
|
|
|
@MainActor
|
|
final class SessionNavigationTests: XCTestCase {
|
|
func testColdStartAndHubReplacementHaveNoSelection() {
|
|
let navigation = SessionNavigationState()
|
|
XCTAssertNil(navigation.selectedSessionId)
|
|
XCTAssertTrue(navigation.detailPath.isEmpty)
|
|
XCTAssertEqual(navigation.columnVisibility, .all)
|
|
XCTAssertEqual(navigation.preferredCompactColumn, .sidebar)
|
|
navigation.open("a")
|
|
XCTAssertNil(SessionNavigationState().selectedSessionId)
|
|
}
|
|
|
|
func testOpenIsIdempotentAndNewSessionClearsNestedNavigation() {
|
|
let navigation = SessionNavigationState()
|
|
navigation.open("a")
|
|
navigation.detailPath.append("files")
|
|
navigation.open("a")
|
|
XCTAssertEqual(navigation.detailPath.count, 1)
|
|
navigation.open("created-before-list-refresh")
|
|
XCTAssertEqual(navigation.selectedSessionId, "created-before-list-refresh")
|
|
XCTAssertTrue(navigation.detailPath.isEmpty)
|
|
XCTAssertEqual(navigation.preferredCompactColumn, .detail)
|
|
}
|
|
|
|
func testColumnChangesDoNotDiscardSelectionOrDetailPath() {
|
|
let navigation = SessionNavigationState()
|
|
navigation.open("a")
|
|
navigation.detailPath.append("file.swift")
|
|
navigation.columnVisibility = .detailOnly
|
|
navigation.preferredCompactColumn = .sidebar
|
|
XCTAssertEqual(navigation.selectedSessionId, "a")
|
|
XCTAssertEqual(navigation.detailPath.count, 1)
|
|
navigation.open("a")
|
|
navigation.columnVisibility = .all
|
|
XCTAssertEqual(navigation.preferredCompactColumn, .detail)
|
|
XCTAssertEqual(navigation.detailPath.count, 1)
|
|
}
|
|
|
|
func testSupersedingAndRemovalCannotStealAnotherChatsFocus() {
|
|
let navigation = SessionNavigationState()
|
|
navigation.open("a")
|
|
navigation.open("b")
|
|
navigation.detailPath.append("files")
|
|
navigation.supersede("a", with: "a-resumed")
|
|
navigation.remove("a")
|
|
XCTAssertEqual(navigation.selectedSessionId, "b")
|
|
XCTAssertEqual(navigation.detailPath.count, 1)
|
|
navigation.supersede("b", with: "b-resumed")
|
|
XCTAssertEqual(navigation.selectedSessionId, "b-resumed")
|
|
XCTAssertTrue(navigation.detailPath.isEmpty)
|
|
navigation.remove("b-resumed")
|
|
XCTAssertNil(navigation.selectedSessionId)
|
|
XCTAssertEqual(navigation.preferredCompactColumn, .sidebar)
|
|
}
|
|
|
|
func testHubPublishesExplicitRemovalsEvenForAnUnlistedSession() throws {
|
|
let hub = try XCTUnwrap(HubSession(hubUrl: "http://127.0.0.1:1/ipad-removal-\(UUID())",
|
|
credentialStore: InMemoryCredentialStore()))
|
|
defer { hub.shutdown() }
|
|
hub.sessionStore.applySessionEvent(.sessionRemoved(namespace: nil, sessionId: "a"))
|
|
let first = try XCTUnwrap(hub.sessionRemoval)
|
|
XCTAssertEqual(first.sessionId, "a")
|
|
hub.sessionStore.applySessionEvent(.sessionRemoved(namespace: nil, sessionId: "a"))
|
|
XCTAssertNotEqual(hub.sessionRemoval, first)
|
|
}
|
|
|
|
func testAppUsesOneSceneWithoutRequiringFullScreen() {
|
|
let manifest = Bundle.main.object(forInfoDictionaryKey: "UIApplicationSceneManifest") as? [String: Any]
|
|
XCTAssertEqual(manifest?["UIApplicationSupportsMultipleScenes"] as? Bool, false)
|
|
XCTAssertNotEqual(Bundle.main.object(forInfoDictionaryKey: "UIRequiresFullScreen") as? Bool, true)
|
|
}
|
|
|
|
func testLastSurfaceReleaseStopsTransportBeforeModelDeallocation() async throws {
|
|
let hub = try XCTUnwrap(HubSession(hubUrl: "http://127.0.0.1:1/ipad-release-\(UUID())",
|
|
credentialStore: InMemoryCredentialStore()))
|
|
defer { hub.shutdown() }
|
|
var model: ChatModel? = ChatModel(session: hub, sessionId: "a")
|
|
weak var released = model
|
|
model?.retainSurface("chat")
|
|
for _ in 0..<100 {
|
|
if hub.openChatSessionId == "a" { break }
|
|
try await Task.sleep(for: .milliseconds(20))
|
|
}
|
|
XCTAssertEqual(hub.openChatSessionId, "a")
|
|
model?.releaseSurface("chat")
|
|
model = nil
|
|
for _ in 0..<100 {
|
|
if hub.openChatSessionId == nil && released == nil { break }
|
|
try await Task.sleep(for: .milliseconds(20))
|
|
}
|
|
XCTAssertNil(hub.openChatSessionId, "Teardown must not depend on the view retaining its old model")
|
|
XCTAssertNil(released)
|
|
}
|
|
}
|