import Foundation import Testing @testable import gitbay /// Exercises a real instance. Skipped unless a token is provided: /// /// GITBAY_TEST_TOKEN=$(gitbay auth token create --name ci --scope read --ttl 1h) /// /// Optionally GITBAY_TEST_INSTANCE (defaults to gitbay.org). A read-scoped /// token is enough — nothing here writes. struct LiveInstanceTests { nonisolated private static var token: String? { ProcessInfo.processInfo.environment["GITBAY_TEST_TOKEN"] } nonisolated private struct Whoami: Decodable, Sendable { let username: String } @Test(.enabled(if: token != nil, "GITBAY_TEST_TOKEN is not set")) func secondReadOfARealInstanceRevalidatesFor304() async throws { let host = ProcessInfo.processInfo.environment["GITBAY_TEST_INSTANCE"] ?? "gitbay.org" let instance = try GitbayInstance(url: host) // A session that counts responses without touching their content, // so the 304 is observed rather than inferred. let client = GitbayClient( instance: instance, token: try #require(Self.token), session: RecordingProtocol.session() ) RecordingProtocol.reset() let first = try await client.read(["whoami"], as: Whoami.self) let second = try await client.read(["whoami"], as: Whoami.self) #expect(first.username == second.username) #expect(!first.username.isEmpty) let statuses = RecordingProtocol.statuses #expect(statuses == [200, 304]) } } /// Passes requests through to the network, recording each response status. nonisolated final class RecordingProtocol: URLProtocol, @unchecked Sendable { private static let recorded = Mutex<[Int]>([]) private static let inner = URLSession(configuration: .ephemeral) static var statuses: [Int] { recorded.withLock { $0 } } static func reset() { recorded.withLock { $0.removeAll() } } static func session() -> URLSession { let configuration = URLSessionConfiguration.ephemeral configuration.protocolClasses = [RecordingProtocol.self] return URLSession(configuration: configuration) } override static func canInit(with _: URLRequest) -> Bool { true } override static func canonicalRequest(for request: URLRequest) -> URLRequest { request } override func startLoading() { let request = self.request Task { do { let (data, response) = try await Self.inner.data(for: request) if let http = response as? HTTPURLResponse { Self.recorded.withLock { $0.append(http.statusCode) } } self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) self.client?.urlProtocol(self, didLoad: data) self.client?.urlProtocolDidFinishLoading(self) } catch { self.client?.urlProtocol(self, didFailWithError: error) } } } override func stopLoading() {} }