Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
Kotlin
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105package social.grain
import kotlinx.serialization.json.Jsonimport org.junit.Assert.assertEqualsimport org.junit.Assert.assertNotNullimport org.junit.Assert.assertNullimport org.junit.Assert.assertTrueimport org.junit.Testimport social.grain.data.api.GetFollowersResponseimport social.grain.data.api.GetGalleryFavoritesResponseimport social.grain.data.api.GetKnownFollowersResponse
/** * The four actor lists share one model, so a field typed wrong breaks all of * them at once — and only at runtime, as an empty list with a decode error in * the log. The follower fixture is a real response captured from the appview. */class ActorListDecodeTest {
private val json = Json { ignoreUnknownKeys = true explicitNulls = false coerceInputValues = true }
private val followersFixture = """ { "totalCount": 5, "items": [ { "did": "did:plc:bcgltzqazw5tb6k2g3ttenbj", "handle": "chadtmiller.com", "displayName": "chad", "description": "building @grain.social, suuuup", "avatar": "https://cdn.grain.social/x/avatar/plain/did:plc:bcgltzqazw5tb6k2g3ttenbj/y" }, { "did": "did:plc:z6sonfx6nicq2ndrixghcolb", "handle": "jj.mcdonough.rodeo", "displayName": "JJ", "description": "Data guy. Tryhard. VT, US. Born at 341ppm.", "avatar": "https://cdn.grain.social/z/avatar/plain/did:plc:z6sonfx6nicq2ndrixghcolb/w" } ], "cursor": "Mjo6YmFmeXJlaWJjNWVhdHIzcnJrNXVjdGhmbDZkZHB6ZHF2cng3bHRsZWRnc3p3N2gzeXlwam9scGpjeWE" } """.trimIndent()
@Test fun `a real followers response decodes`() { val response = json.decodeFromString<GetFollowersResponse>(followersFixture)
assertEquals(5, response.totalCount) assertEquals(2, response.items?.size) assertNotNull("cursor drives pagination", response.cursor)
val first = response.items!!.first() assertEquals("did:plc:bcgltzqazw5tb6k2g3ttenbj", first.did) assertEquals("chadtmiller.com", first.handle) assertEquals("chad", first.displayName) assertTrue(first.avatar!!.startsWith("https://")) }
@Test fun `a member with no display name or bio still decodes`() { // The appview omits these rather than sending null, which is the case // an over-strict model would choke on. val sparse = """{"items":[{"did":"did:plc:sparse","handle":"a.test"}]}""" val response = json.decodeFromString<GetFollowersResponse>(sparse)
val member = response.items!!.single() assertEquals("did:plc:sparse", member.did) assertNull(member.displayName) assertNull(member.description) assertNull(member.avatar) assertNull("no cursor means no further pages", response.cursor) }
@Test fun `an empty favorites list decodes rather than failing`() { val response = json.decodeFromString<GetGalleryFavoritesResponse>( """{"totalCount":0,"items":[]}""", ) assertEquals(0, response.totalCount) assertTrue(response.items!!.isEmpty()) }
@Test fun `known followers has no cursor envelope`() { val response = json.decodeFromString<GetKnownFollowersResponse>( """{"items":[{"did":"did:plc:known","handle":"b.test","displayName":"Known"}]}""", ) assertEquals("Known", response.items!!.single().displayName) }
@Test fun `a response with unknown fields still decodes`() { // The appview adds fields ahead of clients; a strict decoder would fail // the whole list on one new key. val future = """{"items":[{"did":"did:plc:x","handle":"c.test","somethingNew":42}],"newTopLevel":true}""" val response = json.decodeFromString<GetFollowersResponse>(future) assertEquals("c.test", response.items!!.single().handle) }}