From 6761eae351252ec402c1e06c7a6a86c59ab4e490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Orzech?= Date: Fri, 20 Mar 2026 00:24:50 +0100 Subject: [PATCH] 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. --- .../microblog/data/api/GhostApiService.kt | 4 + .../swoosh/microblog/data/model/SiteModels.kt | 12 ++ .../microblog/data/model/SiteModelsTest.kt | 129 ++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 app/src/main/java/com/swoosh/microblog/data/model/SiteModels.kt create mode 100644 app/src/test/java/com/swoosh/microblog/data/model/SiteModelsTest.kt diff --git a/app/src/main/java/com/swoosh/microblog/data/api/GhostApiService.kt b/app/src/main/java/com/swoosh/microblog/data/api/GhostApiService.kt index cd41155..6cbef43 100644 --- a/app/src/main/java/com/swoosh/microblog/data/api/GhostApiService.kt +++ b/app/src/main/java/com/swoosh/microblog/data/api/GhostApiService.kt @@ -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 + @GET("ghost/api/admin/site/") + suspend fun getSite(): Response + @GET("ghost/api/admin/users/me/") suspend fun getCurrentUser(): Response diff --git a/app/src/main/java/com/swoosh/microblog/data/model/SiteModels.kt b/app/src/main/java/com/swoosh/microblog/data/model/SiteModels.kt new file mode 100644 index 0000000..e6c33f9 --- /dev/null +++ b/app/src/main/java/com/swoosh/microblog/data/model/SiteModels.kt @@ -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? +) diff --git a/app/src/test/java/com/swoosh/microblog/data/model/SiteModelsTest.kt b/app/src/test/java/com/swoosh/microblog/data/model/SiteModelsTest.kt new file mode 100644 index 0000000..201825d --- /dev/null +++ b/app/src/test/java/com/swoosh/microblog/data/model/SiteModelsTest.kt @@ -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) + } +}