diff --git a/app/src/main/java/com/swoosh/microblog/data/MobiledocBuilder.kt b/app/src/main/java/com/swoosh/microblog/data/MobiledocBuilder.kt index 6fd2c79..1a8f627 100644 --- a/app/src/main/java/com/swoosh/microblog/data/MobiledocBuilder.kt +++ b/app/src/main/java/com/swoosh/microblog/data/MobiledocBuilder.kt @@ -62,6 +62,24 @@ object MobiledocBuilder { linkTitle: String?, linkDescription: String?, imageAlt: String? + ): String { + return build(text, imageUrls, linkUrl, linkTitle, linkDescription, imageAlt, null, null) + } + + /** + * Builds mobiledoc JSON with support for images, video, audio, and bookmark cards. + * + * Card order: images -> video -> audio -> bookmark + */ + fun build( + text: String, + imageUrls: List, + linkUrl: String?, + linkTitle: String?, + linkDescription: String?, + imageAlt: String?, + videoUrl: String?, + audioUrl: String? ): String { val escapedText = escapeForJson(text).replace("\n", "\\n") @@ -77,6 +95,20 @@ object MobiledocBuilder { cardSections.add("[10,${cards.size - 1}]") } + // Add video card if present + if (videoUrl != null) { + val escapedUrl = escapeForJson(videoUrl) + cards.add("""["video",{"src":"$escapedUrl","loop":false}]""") + cardSections.add("[10,${cards.size - 1}]") + } + + // Add audio card if present + if (audioUrl != null) { + val escapedUrl = escapeForJson(audioUrl) + cards.add("""["audio",{"src":"$escapedUrl"}]""") + cardSections.add("[10,${cards.size - 1}]") + } + // Add bookmark card if link is present if (linkUrl != null) { val escapedUrl = escapeForJson(linkUrl) diff --git a/app/src/test/java/com/swoosh/microblog/data/MobiledocBuilderTest.kt b/app/src/test/java/com/swoosh/microblog/data/MobiledocBuilderTest.kt index 97ba7c3..5bc3799 100644 --- a/app/src/test/java/com/swoosh/microblog/data/MobiledocBuilderTest.kt +++ b/app/src/test/java/com/swoosh/microblog/data/MobiledocBuilderTest.kt @@ -597,4 +597,131 @@ class MobiledocBuilderTest { val secondCard = cards.get(1).asJsonArray.get(1).asJsonObject assertEquals("", secondCard.get("alt").asString) } + + // --- Video card tests --- + + @Test + fun `build with video only produces valid JSON with video card`() { + val result = MobiledocBuilder.build( + "Check this video", emptyList(), null, null, null, null, + "https://example.com/video.mp4", null + ) + val json = JsonParser.parseString(result).asJsonObject + assertNotNull(json) + + val cards = json.getAsJsonArray("cards") + assertEquals(1, cards.size()) + val card = cards.get(0).asJsonArray + assertEquals("video", card.get(0).asString) + val cardData = card.get(1).asJsonObject + assertEquals("https://example.com/video.mp4", cardData.get("src").asString) + assertFalse(cardData.get("loop").asBoolean) + } + + @Test + fun `build with video has correct sections`() { + val result = MobiledocBuilder.build( + "Text", emptyList(), null, null, null, null, + "https://example.com/video.mp4", null + ) + val json = JsonParser.parseString(result).asJsonObject + val sections = json.getAsJsonArray("sections") + assertEquals("Should have text section + video card section", 2, sections.size()) + + val videoSection = sections.get(1).asJsonArray + assertEquals(10, videoSection.get(0).asInt) + assertEquals(0, videoSection.get(1).asInt) + } + + // --- Audio card tests --- + + @Test + fun `build with audio only produces valid JSON with audio card`() { + val result = MobiledocBuilder.build( + "Listen to this", emptyList(), null, null, null, null, + null, "https://example.com/audio.mp3" + ) + val json = JsonParser.parseString(result).asJsonObject + assertNotNull(json) + + val cards = json.getAsJsonArray("cards") + assertEquals(1, cards.size()) + val card = cards.get(0).asJsonArray + assertEquals("audio", card.get(0).asString) + val cardData = card.get(1).asJsonObject + assertEquals("https://example.com/audio.mp3", cardData.get("src").asString) + } + + @Test + fun `build with audio has correct sections`() { + val result = MobiledocBuilder.build( + "Text", emptyList(), null, null, null, null, + null, "https://example.com/audio.mp3" + ) + val json = JsonParser.parseString(result).asJsonObject + val sections = json.getAsJsonArray("sections") + assertEquals("Should have text section + audio card section", 2, sections.size()) + } + + // --- Combined: text + images + video + audio + bookmark --- + + @Test + fun `build with all media types produces valid JSON with correct card order`() { + val images = listOf("https://example.com/img1.jpg", "https://example.com/img2.jpg") + val result = MobiledocBuilder.build( + "Full post", images, + "https://link.com", "Link Title", "Link Desc", + "Alt text", + "https://example.com/video.mp4", + "https://example.com/audio.mp3" + ) + val json = JsonParser.parseString(result).asJsonObject + assertNotNull(json) + + val cards = json.getAsJsonArray("cards") + // 2 images + 1 video + 1 audio + 1 bookmark = 5 cards + assertEquals(5, cards.size()) + + // Verify card order: image, image, video, audio, bookmark + assertEquals("image", cards.get(0).asJsonArray.get(0).asString) + assertEquals("image", cards.get(1).asJsonArray.get(0).asString) + assertEquals("video", cards.get(2).asJsonArray.get(0).asString) + assertEquals("audio", cards.get(3).asJsonArray.get(0).asString) + assertEquals("bookmark", cards.get(4).asJsonArray.get(0).asString) + + // Verify sections: 1 text + 5 card sections = 6 + val sections = json.getAsJsonArray("sections") + assertEquals(6, sections.size()) + + // Verify card section indices are sequential + for (i in 0 until 5) { + val cardSection = sections.get(i + 1).asJsonArray + assertEquals(10, cardSection.get(0).asInt) + assertEquals(i, cardSection.get(1).asInt) + } + } + + @Test + fun `build with video and audio but no images produces correct cards`() { + val result = MobiledocBuilder.build( + "Media post", emptyList(), null, null, null, null, + "https://example.com/video.mp4", + "https://example.com/audio.mp3" + ) + val json = JsonParser.parseString(result).asJsonObject + val cards = json.getAsJsonArray("cards") + assertEquals(2, cards.size()) + assertEquals("video", cards.get(0).asJsonArray.get(0).asString) + assertEquals("audio", cards.get(1).asJsonArray.get(0).asString) + } + + @Test + fun `build with video URL containing special chars produces valid JSON`() { + val result = MobiledocBuilder.build( + "Text", emptyList(), null, null, null, null, + "https://example.com/video?id=1&name=\"test\"", null + ) + val json = JsonParser.parseString(result).asJsonObject + assertNotNull(json) + } }