import XCTest @testable import iPodderX /// The event stream, against a real daemon. Asking it to scan is the cheapest way to make it /// say something, and scan_done is terminal, so the test has a definite end rather than a sleep. final class EventsTests: XCTestCase { func testAScanIsReportedOnTheStream() async throws { let env = ProcessInfo.processInfo.environment let server = env["IPX_SERVER"] ?? "" try XCTSkipIf(server.isEmpty, "set IPX_SERVER to a fixture daemon") ServerSettings.base = try XCTUnwrap(ServerSettings.parse(server)) if let token = env["IPX_TOKEN"], !token.isEmpty, let url = ServerSettings.base { let cookie = try XCTUnwrap(HTTPCookie(properties: [ .name: "ipx_token", .value: token, .path: "/", .domain: url.host ?? "127.0.0.1", ])) HTTPCookieStorage.shared.setCookie(cookie) } let events = await Events() let sawScanDone = expectation(description: "scan_done arrives") sawScanDone.assertForOverFulfill = false await MainActor.run { events.onEvent { event in if case .scanDone = event { sawScanDone.fulfill() } } events.start() } // Connect before asking for work, or the answer arrives before anyone is listening. try await Task.sleep(nanoseconds: 1_500_000_000) try await API().fetch(feed: "test-show") await fulfillment(of: [sawScanDone], timeout: 30) await MainActor.run { events.stop() } } /// An event this build has never heard of must not stop the stream. func testAnUnknownEventDecodesRatherThanThrowing() throws { let data = Data(#"{"ev":"something_new","feed":"x"}"#.utf8) let event = try JSONDecoder().decode(IPXEvent.self, from: data) guard case .other(let name) = event else { return XCTFail("expected .other, got \(event)") } XCTAssertEqual(name, "something_new") } /// Progress without a total happens: a server that sends no Content-Length. func testProgressDecodesWithoutATotal() throws { let data = Data(#"{"ev":"progress","feed":"f","enclosure":7,"url":"u","file":"a.mp3","done":10}"#.utf8) guard case .progress(_, let enclosure, _, let done, let total) = try JSONDecoder().decode(IPXEvent.self, from: data) else { return XCTFail("did not decode as progress") } XCTAssertEqual(enclosure, 7) XCTAssertEqual(done, 10) XCTAssertNil(total) } }