new app store assets ready for relese ui updates
This commit is contained in:
@@ -30,6 +30,9 @@ final class MockProtocol: URLProtocol, @unchecked Sendable {
|
||||
return data
|
||||
}
|
||||
@MainActor static func main() async throws {
|
||||
let testLogURL = URL(fileURLWithPath: ProcessInfo.processInfo.environment["TARNAX_SCRATCH_ROOT"]!).appendingPathComponent("contract-logs-" + UUID().uuidString + ".json")
|
||||
defer { try? FileManager.default.removeItem(at: testLogURL) }
|
||||
|
||||
for server in ["http://example.test", "https://u:p@example.test", "https://example.test/?password=x"] {
|
||||
do { _ = try Transport(Credentials(server: server)); fatalError("Insecure URL accepted") } catch { check(true, "Reject unsafe URL: \(server)") }
|
||||
}
|
||||
@@ -89,7 +92,7 @@ final class MockProtocol: URLProtocol, @unchecked Sendable {
|
||||
transport.session.configuration.httpCookieStorage?.setCookie(cookie)
|
||||
let another = try Transport(Credentials(server: "https://example.test"))
|
||||
check(another.session.configuration.httpCookieStorage?.cookies?.contains(where: { $0.name == "SID" }) != true, "Cookie jar isolated from other connections")
|
||||
let model = AppModel()
|
||||
let model = AppModel(logs: AppLogStore(url: testLogURL))
|
||||
model.client = transport; model.connected = true; model.locked = false
|
||||
let gate = DispatchSemaphore(value: 0)
|
||||
var preferenceRequests = 0
|
||||
@@ -132,7 +135,7 @@ final class MockProtocol: URLProtocol, @unchecked Sendable {
|
||||
check(model.error == nil, "Retired session cannot raise a global alert")
|
||||
model.disconnect()
|
||||
check(model.preferences.isEmpty && !model.preferencesLoading, "Disconnect clears session preferences")
|
||||
let startup = AppModel()
|
||||
let startup = AppModel(logs: AppLogStore(url: testLogURL))
|
||||
startup.credentials = Credentials(server: "https://example.test")
|
||||
startup.locked = false
|
||||
check(!startup.canRestoreSession, "Default server without a saved user does not auto-login")
|
||||
@@ -148,13 +151,13 @@ final class MockProtocol: URLProtocol, @unchecked Sendable {
|
||||
startup.error = nil
|
||||
await startup.restoreSessionIfNeeded()
|
||||
check(startup.error == nil, "Failed automatic login is not retried on view updates")
|
||||
let disconnected = AppModel()
|
||||
let disconnected = AppModel(logs: AppLogStore(url: testLogURL))
|
||||
disconnected.locked = false
|
||||
disconnected.credentials = Credentials(server: "http://invalid.test", username: "test-user")
|
||||
disconnected.disconnect()
|
||||
await disconnected.restoreSessionIfNeeded()
|
||||
check(disconnected.error == nil && !disconnected.connected, "Explicit disconnect suppresses automatic login for this launch")
|
||||
let protection = AppModel()
|
||||
let protection = AppModel(logs: AppLogStore(url: testLogURL))
|
||||
protection.locked = true; protection.biometric = true
|
||||
var authCalls = 0
|
||||
protection.authenticate = { _ in authCalls += 1; return true }
|
||||
@@ -198,7 +201,7 @@ final class MockProtocol: URLProtocol, @unchecked Sendable {
|
||||
}
|
||||
await protection.updateScene(.active)
|
||||
check(!protection.locked, "Face ID success while system prompt is inactive unlocks the app")
|
||||
let presentation = AppModel()
|
||||
let presentation = AppModel(logs: AppLogStore(url: testLogURL))
|
||||
presentation.biometric = true; presentation.locked = true
|
||||
check(!presentation.unlockNeedsRetry, "Fresh protected launch shows branding instead of lock fallback")
|
||||
presentation.authenticate = { _ in
|
||||
@@ -236,7 +239,7 @@ final class MockProtocol: URLProtocol, @unchecked Sendable {
|
||||
check(dense.samples.count == TransferHistory.maximumSamples, "History storage remains bounded during frequent refreshes")
|
||||
check(model.transferHistory.samples.isEmpty, "Disconnected session has no previous server history")
|
||||
let historyTransport = try Transport(Credentials(server: "https://example.test"), configuration: config)
|
||||
let liveHistory = AppModel()
|
||||
let liveHistory = AppModel(logs: AppLogStore(url: testLogURL))
|
||||
liveHistory.historyStore = HistoryStore(url: URL(fileURLWithPath: ProcessInfo.processInfo.environment["TARNAX_SCRATCH_ROOT"]!).appendingPathComponent("test-history.json"))
|
||||
defer { try? liveHistory.historyStore.clear() }
|
||||
liveHistory.client = historyTransport; liveHistory.connected = true; liveHistory.locked = false
|
||||
@@ -270,6 +273,22 @@ final class MockProtocol: URLProtocol, @unchecked Sendable {
|
||||
check(StatFormat.display(120, key: "max_seeding_time", preference: true) == "2 hr", "Seeding preferences convert API minutes correctly")
|
||||
check(StatFormat.display(42, key: "total_peers") == "42", "Unit metadata leaves counters untouched")
|
||||
check(StatFormat.display(1024, key: "dl_info_speed").hasSuffix("/s"), "Speeds retain per-second units")
|
||||
let queueJSON = "[{\"hash\":\"queued\",\"name\":\"Queued torrent\",\"state\":\"queuedDL\",\"progress\":0.5,\"size\":100,\"dlspeed\":0,\"upspeed\":0,\"eta\":10,\"ratio\":0,\"category\":\"\",\"tags\":\"\",\"priority\":3}]"
|
||||
let queue = try JSONDecoder().decode([Torrent].self, from: Data(queueJSON.utf8))
|
||||
check(queue.first?.queuePosition == 3, "Queue position decodes from server priority")
|
||||
let unnumbered = try JSONDecoder().decode([Torrent].self, from: Data(queueJSON.replacingOccurrences(of: "3}", with: "-1}").utf8))
|
||||
check(unnumbered.first?.queuePosition == nil, "Unnumbered server priority is not presented as a queue position")
|
||||
let noPriority = try JSONDecoder().decode([Torrent].self, from: Data(queueJSON.replacingOccurrences(of: ",\"priority\":3", with: "").utf8))
|
||||
check(noPriority.first?.queuePosition == nil, "Older servers without priority still decode")
|
||||
var completionFixture = queue[0]
|
||||
for state in ["uploading", "stalledUP", "forcedUP", "queuedUP", "pausedUP", "stoppedUP"] {
|
||||
completionFixture.state = state; completionFixture.progress = 0.75
|
||||
check(!completionFixture.complete, "Incomplete progress is excluded even for \(state)")
|
||||
}
|
||||
completionFixture.progress = 1
|
||||
check(completionFixture.complete, "Full measured progress is completed")
|
||||
completionFixture.progress = 0.9999
|
||||
check(!completionFixture.complete, "Rounded near-100-percent progress is not completed")
|
||||
another.close(); transport.close(); print("\(checks) contract checks passed.")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user