app/src/test/java/dev/equwal/inkupdate/JsonTest.kt (6662 bytes)
1 // SPDX-License-Identifier: GPL-3.0-or-later 2 // Copyright (c) 2026 equwal 3 package dev.equwal.inkupdate 4 5 import org.junit.Assert.assertEquals 6 import org.junit.Assert.assertNull 7 import org.junit.Assert.assertTrue 8 import org.junit.Test 9 10 /** 11 * The two answers, as the hosts really send them. 12 * 13 * The F-Droid answers come from https://f-droid.org/api/v1/packages/. 14 * The GitHub answer keeps the shape of 15 * https://api.github.com/repos/equwal/rebind/releases?per_page=10. 16 */ 17 class JsonTest { 18 19 private val page = "https://f-droid.org/packages/org.fdroid.fdroid/" 20 21 // ---- F-Droid ----------------------------------------------------------- 22 23 /** The real answer for org.fdroid.fdroid. */ 24 private val fdroidReal = """ 25 {"packageName":"org.fdroid.fdroid","suggestedVersionCode":1023052, 26 "packages":[{"versionName":"2.0-rc1","versionCode":2000041}, 27 {"versionName":"2.0-rc0","versionCode":2000040}, 28 {"versionName":"2.0-alpha11","versionCode":2000011}, 29 {"versionName":"1.23.2","versionCode":1023052}]} 30 """.trimIndent() 31 32 @Test 33 fun readsARealFdroidAnswer() { 34 val a = Decide.parseFdroid(fdroidReal, page) 35 assertTrue(a is FdroidAnswer.Found) 36 a as FdroidAnswer.Found 37 // The suggested build, not the newest one. F-Droid suggests 1.23.2. 38 assertEquals(1023052L, a.versionCode) 39 assertEquals("1.23.2", a.versionName) 40 assertEquals(page, a.page) 41 } 42 43 /** All four watched apps get this answer today. It is not a failure. */ 44 @Test 45 fun notFoundMeansNotThere() { 46 assertEquals( 47 FdroidAnswer.NotThere, 48 Decide.parseFdroid("""{"error":"NOT_FOUND"}""", page) 49 ) 50 } 51 52 @Test 53 fun aBrokenFdroidAnswerFails() { 54 assertTrue(Decide.parseFdroid("not json", page) is FdroidAnswer.Failed) 55 assertTrue(Decide.parseFdroid("", page) is FdroidAnswer.Failed) 56 assertTrue(Decide.parseFdroid(null, page) is FdroidAnswer.Failed) 57 assertTrue(Decide.parseFdroid("""{"packageName":"a"}""", page) is FdroidAnswer.Failed) 58 assertTrue(Decide.parseFdroid("[1,2,3]", page) is FdroidAnswer.Failed) 59 } 60 61 // ---- GitHub ------------------------------------------------------------ 62 63 /** 64 * A draft first, then two pre-releases. Every release of these 65 * repositories is a pre-release, so /releases/latest would give nothing. 66 */ 67 private val githubReal = """ 68 [ 69 {"id":1,"tag_name":"v0.0.17-alpha","name":"Rebind 0.0.17-alpha", 70 "draft":true,"prerelease":true, 71 "html_url":"https://github.com/equwal/rebind/releases/tag/untagged-1", 72 "assets":[]}, 73 {"id":2,"tag_name":"v0.0.15-alpha","name":"Rebind 0.0.15-alpha", 74 "draft":false,"prerelease":true, 75 "html_url":"https://github.com/equwal/rebind/releases/tag/v0.0.15-alpha", 76 "published_at":"2026-09-20T18:04:11Z", 77 "assets":[ 78 {"name":"rebind-0.0.15-alpha-play.aab", 79 "browser_download_url":"https://github.com/equwal/rebind/releases/download/v0.0.15-alpha/rebind-0.0.15-alpha-play.aab"}, 80 {"name":"rebind-0.0.15-alpha-play.apk", 81 "browser_download_url":"https://github.com/equwal/rebind/releases/download/v0.0.15-alpha/rebind-0.0.15-alpha-play.apk"}, 82 {"name":"rebind-0.0.15-alpha-full.apk", 83 "browser_download_url":"https://github.com/equwal/rebind/releases/download/v0.0.15-alpha/rebind-0.0.15-alpha-full.apk"} 84 ]}, 85 {"id":3,"tag_name":"v0.0.14-alpha","draft":false,"prerelease":true, 86 "html_url":"https://github.com/equwal/rebind/releases/tag/v0.0.14-alpha", 87 "assets":[]} 88 ] 89 """.trimIndent() 90 91 @Test 92 fun skipsTheDraftAndTakesThePreRelease() { 93 val a = Decide.parseGithub(githubReal, "full") 94 assertTrue(a is GithubAnswer.Found) 95 a as GithubAnswer.Found 96 assertEquals("v0.0.15-alpha", a.tag) 97 assertEquals("https://github.com/equwal/rebind/releases/tag/v0.0.15-alpha", a.page) 98 assertEquals( 99 "https://github.com/equwal/rebind/releases/download/" + 100 "v0.0.15-alpha/rebind-0.0.15-alpha-full.apk", 101 a.apk 102 ) 103 } 104 105 /** Without a wanted word, the first APK wins. The .aab is not an APK. */ 106 @Test 107 fun takesTheFirstApkWhenNothingIsPreferred() { 108 val a = Decide.parseGithub(githubReal) as GithubAnswer.Found 109 assertEquals( 110 "https://github.com/equwal/rebind/releases/download/" + 111 "v0.0.15-alpha/rebind-0.0.15-alpha-play.apk", 112 a.apk 113 ) 114 } 115 116 @Test 117 fun aReleaseWithNoApkGivesNoLink() { 118 val one = """ 119 [{"tag_name":"v0.1.0","draft":false,"prerelease":false, 120 "html_url":"https://github.com/equwal/ink-dim/releases/tag/v0.1.0", 121 "assets":[{"name":"notes.txt", 122 "browser_download_url":"https://example.invalid/notes.txt"}]}] 123 """.trimIndent() 124 val a = Decide.parseGithub(one, "full") as GithubAnswer.Found 125 assertEquals("v0.1.0", a.tag) 126 assertNull(a.apk) 127 } 128 129 @Test 130 fun anEmptyArrayMeansNoRelease() { 131 assertEquals(GithubAnswer.None, Decide.parseGithub("[]")) 132 } 133 134 @Test 135 fun onlyDraftsMeanNoRelease() { 136 val drafts = """[{"tag_name":"v9.9.9","draft":true,"assets":[]}]""" 137 assertEquals(GithubAnswer.None, Decide.parseGithub(drafts)) 138 } 139 140 @Test 141 fun aBrokenGithubAnswerFails() { 142 assertTrue(Decide.parseGithub("not json") is GithubAnswer.Failed) 143 assertTrue(Decide.parseGithub("") is GithubAnswer.Failed) 144 assertTrue(Decide.parseGithub(null) is GithubAnswer.Failed) 145 // The rate limit answer is an object, not an array. 146 assertTrue( 147 Decide.parseGithub("""{"message":"API rate limit exceeded"}""") 148 is GithubAnswer.Failed 149 ) 150 assertTrue(Decide.parseGithub("""[{"draft":false}]""") is GithubAnswer.Failed) 151 } 152 153 // ---- the two together -------------------------------------------------- 154 155 /** What Rebind gets today: not on F-Droid, a newer pre-release on GitHub. */ 156 @Test 157 fun rebindToday() { 158 val f = Decide.parseFdroid("""{"error":"NOT_FOUND"}""", page) 159 val g = Decide.parseGithub(githubReal, "full") 160 val r = Decide.source(null, f, g, 14L, "0.0.14-alpha-full") 161 assertTrue(r is Result.Update) 162 r as Result.Update 163 assertEquals(Decide.GITHUB, r.source) 164 assertEquals("0.0.15-alpha", r.versionName) 165 assertTrue(r.apk!!.endsWith("-full.apk")) 166 } 167 }