-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(anthropic-client): add tests for message serialization
Enhanced testing for Message and Content serialization in the anthropic-client module, including support for multiple content types like text and image. Added necessary dependencies to build configurations.
- Loading branch information
Showing
9 changed files
with
488 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
...t-core/src/commonMain/kotlin/com/tddworks/anthropic/api/messages/api/ContentSerializer.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.tddworks.anthropic.api.messages.api | ||
|
||
import kotlinx.serialization.KSerializer | ||
import kotlinx.serialization.builtins.ListSerializer | ||
import kotlinx.serialization.descriptors.SerialDescriptor | ||
import kotlinx.serialization.descriptors.buildClassSerialDescriptor | ||
import kotlinx.serialization.encoding.Decoder | ||
import kotlinx.serialization.encoding.Encoder | ||
import kotlinx.serialization.json.* | ||
|
||
object ContentSerializer : KSerializer<Content> { | ||
override val descriptor: SerialDescriptor | ||
get() = buildClassSerialDescriptor("Content") | ||
|
||
override fun deserialize(decoder: Decoder): Content { | ||
val jsonElement = decoder.decodeSerializableValue(JsonElement.serializer()) | ||
return when (jsonElement) { | ||
is JsonPrimitive -> Content.TextContent(jsonElement.content) | ||
is JsonArray -> { | ||
val items = jsonElement.map { element -> | ||
val jsonObj = element.jsonObject | ||
|
||
when (jsonObj["type"]?.jsonPrimitive?.content) { | ||
"text" -> BlockMessageContent.TextContent( | ||
text = jsonObj["text"]?.jsonPrimitive?.content | ||
?: throw IllegalArgumentException("Missing text") | ||
) | ||
|
||
"image" -> BlockMessageContent.ImageContent( | ||
source = BlockMessageContent.ImageContent.Source( | ||
mediaType = jsonObj["source"]?.jsonObject?.get("media_type")?.jsonPrimitive?.content | ||
?: throw IllegalArgumentException("Missing media_type"), | ||
data = jsonObj["source"]?.jsonObject?.get("data")?.jsonPrimitive?.content | ||
?: throw IllegalArgumentException("Missing data"), | ||
type = jsonObj["source"]?.jsonObject?.get("type")?.jsonPrimitive?.content | ||
?: throw IllegalArgumentException("Missing type") | ||
) | ||
) | ||
|
||
else -> throw IllegalArgumentException("Unsupported content block type") | ||
} | ||
|
||
} | ||
Content.BlockContent(blocks = items) | ||
} | ||
|
||
else -> throw IllegalArgumentException("Unsupported content format") | ||
} | ||
} | ||
|
||
override fun serialize(encoder: Encoder, value: Content) { | ||
when (value) { | ||
is Content.TextContent -> encoder.encodeString(value.text) | ||
is Content.BlockContent -> encoder.encodeSerializableValue( | ||
ListSerializer(BlockMessageContent.serializer()), value.blocks | ||
) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
...src/commonMain/kotlin/com/tddworks/anthropic/api/messages/api/MessageContentSerializer.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.tddworks.anthropic.api.messages.api | ||
|
||
import kotlinx.serialization.KSerializer | ||
import kotlinx.serialization.SerializationException | ||
import kotlinx.serialization.json.JsonContentPolymorphicSerializer | ||
import kotlinx.serialization.json.JsonElement | ||
import kotlinx.serialization.json.jsonObject | ||
|
||
/** | ||
* { | ||
* "role": "user", | ||
* "content": [ | ||
* { | ||
* "type": "image", | ||
* "source": { | ||
* "type": "base64", | ||
* "media_type": image1_media_type, | ||
* "data": image1_data, | ||
* }, | ||
* }, | ||
* { | ||
* "type": "text", | ||
* "text": "Describe this image." | ||
* } | ||
* ], | ||
* } | ||
*/ | ||
//internal object MessageContentSerializer : | ||
// JsonContentPolymorphicSerializer<Content>(Content::class) { | ||
// override fun selectDeserializer(element: JsonElement): KSerializer<out Content> { | ||
// val jsonObject = element.jsonObject | ||
// return when { | ||
// "source" in jsonObject -> BlockMessageContent.ImageContent.serializer() | ||
// "text" in jsonObject -> BlockMessageContent.TextContent.serializer() | ||
// else -> throw SerializationException("Unknown Content type") | ||
// } | ||
// | ||
// } | ||
//} |
68 changes: 68 additions & 0 deletions
68
...ore/src/jvmTest/kotlin/com/tddworks/anthropic/api/messages/api/BlockMessageContentTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package com.tddworks.anthropic.api.messages.api | ||
|
||
import kotlinx.serialization.json.Json | ||
import org.junit.jupiter.api.Test | ||
import org.skyscreamer.jsonassert.JSONAssert | ||
|
||
class BlockMessageContentTest { | ||
|
||
@Test | ||
fun `should serialize image message content`() { | ||
// Given | ||
val messageContent = BlockMessageContent.ImageContent( | ||
source = BlockMessageContent.ImageContent.Source( | ||
mediaType = "image1_media_type", | ||
data = "image1_data", | ||
type = "base64", | ||
), | ||
) | ||
|
||
// When | ||
val result = Json.encodeToString( | ||
BlockMessageContent.serializer(), | ||
messageContent | ||
) | ||
|
||
// Then | ||
JSONAssert.assertEquals( | ||
""" | ||
{ | ||
"type": "image", | ||
"source": { | ||
"type": "base64", | ||
"media_type": "image1_media_type", | ||
"data": "image1_data" | ||
} | ||
} | ||
""".trimIndent(), | ||
result, | ||
false | ||
) | ||
} | ||
|
||
@Test | ||
fun `should serialize message content`() { | ||
// Given | ||
val messageContent = BlockMessageContent.TextContent( | ||
text = "some-text", | ||
) | ||
|
||
// When | ||
val result = Json.encodeToString( | ||
BlockMessageContent.serializer(), | ||
messageContent | ||
) | ||
|
||
// Then | ||
JSONAssert.assertEquals( | ||
""" | ||
{ | ||
"text": "some-text", | ||
"type": "text" | ||
} | ||
""".trimIndent(), | ||
result, | ||
false | ||
) | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
...pic-client-core/src/jvmTest/kotlin/com/tddworks/anthropic/api/messages/api/ContentTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package com.tddworks.anthropic.api.messages.api | ||
|
||
import kotlinx.serialization.json.Json | ||
import org.junit.jupiter.api.Assertions.assertEquals | ||
import org.junit.jupiter.api.Test | ||
import org.skyscreamer.jsonassert.JSONAssert | ||
|
||
|
||
/** | ||
* Each input message content may be either a single string or an array of content blocks, where each block has a specific type. Using a string for content is shorthand for an array of one content block of type "text". The following input messages are equivalent: | ||
* {"role": "user", "content": "Hello, Claude"} | ||
* {"role": "user", "content": [{"type": "text", "text": "Hello, Claude"}]} | ||
*/ | ||
class ContentTest { | ||
|
||
@Test | ||
fun `should serialize multiple content`() { | ||
// Given | ||
val content = Content.BlockContent( | ||
listOf( | ||
BlockMessageContent.ImageContent( | ||
source = BlockMessageContent.ImageContent.Source( | ||
mediaType = "image1_media_type", | ||
data = "image1_data", | ||
type = "base64", | ||
), | ||
), | ||
BlockMessageContent.TextContent( | ||
text = "some-text", | ||
), | ||
) | ||
) | ||
|
||
// When | ||
val result = Json.encodeToString( | ||
Content.serializer(), | ||
content | ||
) | ||
|
||
// Then | ||
JSONAssert.assertEquals( | ||
""" | ||
[ | ||
{ | ||
"source": { | ||
"data": "image1_data", | ||
"media_type": "image1_media_type", | ||
"type": "base64" | ||
}, | ||
"type": "image" | ||
}, | ||
{ | ||
"text": "some-text", | ||
"type": "text" | ||
} | ||
] | ||
""".trimIndent(), | ||
result, | ||
false | ||
) | ||
} | ||
|
||
@Test | ||
fun `should serialize single string content`() { | ||
// Given | ||
val content = Content.TextContent("Hello, Claude") | ||
|
||
// When | ||
val result = Json.encodeToString( | ||
Content.serializer(), | ||
content | ||
) | ||
|
||
// Then | ||
assertEquals( | ||
""" | ||
"Hello, Claude" | ||
""".trimIndent(), result | ||
) | ||
} | ||
|
||
} |
Oops, something went wrong.