Skip to content
Snippets Groups Projects
Commit 1c7ebf45 authored by nezhyborets's avatar nezhyborets
Browse files

Write a failing test

parent 525c34e5
No related branches found
No related tags found
No related merge requests found
......@@ -86,18 +86,26 @@ struct ServerSentEventsStreamInterpreterTests {
}
// Chunk with 3 objects. I captured it from a real response. It's a very short response that contains just "Hi"
private func chatCompletionChunk() -> Data {
static func chatCompletionChunk() -> Data {
"data: {\"id\":\"chatcmpl-AwnboO5ZnaUyii9xxC5ZVmM5vGark\",\"object\":\"chat.completion.chunk\",\"created\":1738577084,\"model\":\"gpt-4-0613\",\"service_tier\":\"default\",\"system_fingerprint\":\"sysfig\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"refusal\":null},\"logprobs\":null,\"finish_reason\":null}]}\n\ndata: {\"id\":\"chatcmpl-AwnboO5ZnaUyii9xxC5ZVmM5vGark\",\"object\":\"chat.completion.chunk\",\"created\":1738577084,\"model\":\"gpt-4-0613\",\"service_tier\":\"default\",\"system_fingerprint\":\"sysfig\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"Hi\"},\"logprobs\":null,\"finish_reason\":null}]}\n\ndata: {\"id\":\"chatcmpl-AwnboO5ZnaUyii9xxC5ZVmM5vGark\",\"object\":\"chat.completion.chunk\",\"created\":1738577084,\"model\":\"gpt-4-0613\",\"service_tier\":\"default\",\"system_fingerprint\":\"sysfig\",\"choices\":[{\"index\":0,\"delta\":{},\"logprobs\":null,\"finish_reason\":\"stop\"}]}\n\n".data(using: .utf8)!
}
private func chatCompletionChunk() -> Data {
type(of: self).chatCompletionChunk()
}
private func chatCompletionChunkWithComment() -> Data {
": OPENROUTER PROCESSING\n\ndata: {\"id\":\"chatcmpl-AwnboO5ZnaUyii9xxC5ZVmM5vGark\",\"object\":\"chat.completion.chunk\",\"created\":1738577084,\"model\":\"gpt-4-0613\",\"service_tier\":\"default\",\"system_fingerprint\":\"sysfig\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"refusal\":null},\"logprobs\":null,\"finish_reason\":null}]}\n\n".data(using: .utf8)!
}
private func chatCompletionChunkTermination() -> Data {
static func chatCompletionChunkTermination() -> Data {
"data: [DONE]\n\n".data(using: .utf8)!
}
private func chatCompletionChunkTermination() -> Data {
type(of: self).chatCompletionChunkTermination()
}
// Copied from an actual reponse that was an input to inreptreter
private func chatCompletionError() -> Data {
"{\n \"error\": {\n \"message\": \"The model `o3-mini` does not exist or you do not have access to it.\",\n \"type\": \"invalid_request_error\",\n \"param\": null,\n \"code\": \"model_not_found\"\n }\n}\n".data(using: .utf8)!
......
//
// StreamingSessionIntegrationTests.swift
// OpenAI
//
// Created by Oleksii Nezhyborets on 31.03.2025.
//
import XCTest
@testable import OpenAI
final class StreamingSessionIntegrationTests: XCTestCase {
private enum Call {
case content
case complete
}
private let urlSessionFactory = MockURLSessionFactory()
private let streamInterpreter = ServerSentEventsStreamInterpreter<ChatStreamResult>(parsingOptions: [])
private var calls: [Call] = []
private lazy var expectation: XCTestExpectation = {
let expectation = self.expectation(description: "3 content and 1 finish happened")
expectation.expectedFulfillmentCount = 4
return expectation
}()
private lazy var streamingSession = StreamingSession(
urlSessionFactory: urlSessionFactory,
urlRequest: .init(url: .init(string: "/")!),
interpreter: streamInterpreter,
sslDelegate: nil,
middlewares: [],
onReceiveContent: { _, _ in
Task {
await MainActor.run {
self.calls.append(.content)
self.expectation.fulfill()
}
}
},
onProcessingError: { _, _ in },
onComplete: { _,_ in
Task {
await MainActor.run {
self.calls.append(.complete)
self.expectation.fulfill()
}
}
}
)
@MainActor
func testCompleteCalledAfterAllEvents() {
_ = streamingSession
let cancellable = streamingSession.makeSession()
let dataEvent = ServerSentEventsStreamInterpreterTests.chatCompletionChunk()
streamInterpreter.processData(dataEvent)
let doneEvent = ServerSentEventsStreamInterpreterTests.chatCompletionChunkTermination()
streamInterpreter.processData(doneEvent)
let urlSession = urlSessionFactory.urlSession
urlSession.delegate!.urlSession(urlSession, task: DataTaskMock(), didCompleteWithError: nil)
wait(for: [expectation])
XCTAssertEqual(calls[0], .content)
XCTAssertEqual(calls[1], .content)
XCTAssertEqual(calls[2], .content)
XCTAssertEqual(calls[3], .complete)
cancellable.invalidateAndCancel() // just to hold a reference
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment