@@ -343,6 +343,62 @@ final class GenerateContentResponseTests: XCTestCase {
343343 }
344344 }
345345
346+ func testDecodeGenerateContentResponse_missingCitationEndIndex_success( ) throws {
347+ let json = """
348+ {
349+ " candidates " : [
350+ {
351+ " content " : { " role " : " model " , " parts " : [ { " text " : " Some text. " } ] },
352+ " finishReason " : " STOP " ,
353+ " citationMetadata " : {
354+ " citations " : [
355+ {
356+ " uri " : " https://example.com/source "
357+ }
358+ ]
359+ }
360+ }
361+ ]
362+ }
363+ """
364+ let jsonData = try XCTUnwrap ( json. data ( using: . utf8) )
365+
366+ let response = try jsonDecoder. decode ( GenerateContentResponse . self, from: jsonData)
367+
368+ XCTAssertEqual ( response. candidates. count, 1 )
369+ let candidate = try XCTUnwrap ( response. candidates. first)
370+ let citation = try XCTUnwrap ( candidate. citationMetadata? . citations. first)
371+ XCTAssertEqual ( citation. uri, " https://example.com/source " )
372+ XCTAssertEqual ( citation. endIndex, 0 )
373+ XCTAssertEqual ( citation. startIndex, 0 )
374+ }
375+
376+ func testDecodeGenerateContentResponse_emptyCitation_success( ) throws {
377+ let json = """
378+ {
379+ " candidates " : [
380+ {
381+ " content " : { " role " : " model " , " parts " : [ { " text " : " Some text. " } ] },
382+ " finishReason " : " STOP " ,
383+ " citationMetadata " : {
384+ " citations " : [
385+ {}
386+ ]
387+ }
388+ }
389+ ]
390+ }
391+ """
392+ let jsonData = try XCTUnwrap ( json. data ( using: . utf8) )
393+
394+ let response = try jsonDecoder. decode ( GenerateContentResponse . self, from: jsonData)
395+
396+ XCTAssertEqual ( response. candidates. count, 1 )
397+ let candidate = try XCTUnwrap ( response. candidates. first)
398+ let citations = try XCTUnwrap ( candidate. citationMetadata? . citations)
399+ XCTAssertTrue ( citations. isEmpty)
400+ }
401+
346402 // MARK: - Candidate.isEmpty
347403
348404 func testCandidateIsEmpty_allEmpty_isTrue( ) throws {
0 commit comments