feat: add GhostSite model and /site/ API endpoint

Add GhostSite data class for Ghost CMS site metadata (title, description,
logo, icon, accent color, URL, version, locale). Add getSite() endpoint
to GhostApiService. Include unit tests for Gson deserialization and
version parsing.
This commit is contained in:
Paweł Orzech 2026-03-20 00:24:50 +01:00
parent 0891013df6
commit 6761eae351
3 changed files with 145 additions and 0 deletions

View file

@ -1,5 +1,6 @@
package com.swoosh.microblog.data.api
import com.swoosh.microblog.data.model.GhostSite
import com.swoosh.microblog.data.model.PostWrapper
import com.swoosh.microblog.data.model.PostsResponse
import okhttp3.MultipartBody
@ -37,6 +38,9 @@ interface GhostApiService {
@Path("id") id: String
): Response<Unit>
@GET("ghost/api/admin/site/")
suspend fun getSite(): Response<GhostSite>
@GET("ghost/api/admin/users/me/")
suspend fun getCurrentUser(): Response<UsersResponse>

View file

@ -0,0 +1,12 @@
package com.swoosh.microblog.data.model
data class GhostSite(
val title: String?,
val description: String?,
val logo: String?,
val icon: String?,
val accent_color: String?,
val url: String?,
val version: String?,
val locale: String?
)

View file

@ -0,0 +1,129 @@
package com.swoosh.microblog.data.model
import com.google.gson.Gson
import org.junit.Assert.*
import org.junit.Test
class SiteModelsTest {
private val gson = Gson()
@Test
fun `deserialize full site response`() {
val json = """
{
"title": "My Ghost Blog",
"description": "A blog about things",
"logo": "https://example.com/logo.png",
"icon": "https://example.com/icon.png",
"accent_color": "#ff1a75",
"url": "https://example.com/",
"version": "5.82.0",
"locale": "en"
}
""".trimIndent()
val site = gson.fromJson(json, GhostSite::class.java)
assertEquals("My Ghost Blog", site.title)
assertEquals("A blog about things", site.description)
assertEquals("https://example.com/logo.png", site.logo)
assertEquals("https://example.com/icon.png", site.icon)
assertEquals("#ff1a75", site.accent_color)
assertEquals("https://example.com/", site.url)
assertEquals("5.82.0", site.version)
assertEquals("en", site.locale)
}
@Test
fun `deserialize site response with null fields`() {
val json = """
{
"title": "Minimal Blog",
"url": "https://minimal.ghost.io/"
}
""".trimIndent()
val site = gson.fromJson(json, GhostSite::class.java)
assertEquals("Minimal Blog", site.title)
assertNull(site.description)
assertNull(site.logo)
assertNull(site.icon)
assertNull(site.accent_color)
assertEquals("https://minimal.ghost.io/", site.url)
assertNull(site.version)
assertNull(site.locale)
}
@Test
fun `version parsing extracts major version`() {
val site = GhostSite(
title = "Test",
description = null,
logo = null,
icon = null,
accent_color = null,
url = null,
version = "5.82.0",
locale = null
)
val majorVersion = site.version?.split(".")?.firstOrNull()?.toIntOrNull()
assertEquals(5, majorVersion)
}
@Test
fun `version parsing handles old version`() {
val site = GhostSite(
title = "Old Blog",
description = null,
logo = null,
icon = null,
accent_color = null,
url = null,
version = "4.48.9",
locale = null
)
val majorVersion = site.version?.split(".")?.firstOrNull()?.toIntOrNull()
assertEquals(4, majorVersion)
assertTrue((majorVersion ?: 0) < 5)
}
@Test
fun `version parsing handles null version`() {
val site = GhostSite(
title = "No Version",
description = null,
logo = null,
icon = null,
accent_color = null,
url = null,
version = null,
locale = null
)
val majorVersion = site.version?.split(".")?.firstOrNull()?.toIntOrNull()
assertNull(majorVersion)
}
@Test
fun `serialize and deserialize round trip`() {
val original = GhostSite(
title = "Round Trip Blog",
description = "Testing serialization",
logo = "https://example.com/logo.png",
icon = "https://example.com/icon.png",
accent_color = "#15171a",
url = "https://example.com/",
version = "5.82.0",
locale = "pl"
)
val json = gson.toJson(original)
val deserialized = gson.fromJson(json, GhostSite::class.java)
assertEquals(original, deserialized)
}
}