spb/ka-android
Public
Kotlin 100%
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// AdapterTests.kt — tests des parcours critiques hors réseau : mapping JSON →3// KAItem pour chaque adaptateur d'univers (mêmes échantillons réels que la4// suite iOS KATests.swift), construction des URL de liste, favoris/collections.5package com.groupeka.ka67import com.groupeka.ka.core.Ecosystem8import com.groupeka.ka.core.FavoritesStore9import com.groupeka.ka.core.KAItem10import com.groupeka.ka.core.UniverseService11import kotlinx.serialization.json.Json12import kotlinx.serialization.json.JsonObject13import org.junit.Assert.assertEquals14import org.junit.Assert.assertFalse15import org.junit.Assert.assertNotNull16import org.junit.Assert.assertNull17import org.junit.Assert.assertTrue18import org.junit.Test19import java.io.File2021class AdapterTests {2223 private fun decode(json: String): JsonObject =24 Json.parseToJsonElement(json) as JsonObject2526 @Test27 fun louKaMapping() {28 val u = Ecosystem.universe("lou-ka")!!29 val o = decode("""{"uid":"a:1","title":"4½ Limoilou","city":"Québec","unit_type":"4½","price":1200,"url":"https://x.com/a","lat":46.8,"lng":-71.2,"address":"12 rue X"}""")30 val item = u.map!!(o)!!31 assertEquals("lou-ka", item.universeID)32 assertEquals("4½ Limoilou", item.title)33 assertTrue(item.priceLabel!!.contains("1"))34 assertEquals("Québec", item.city)35 assertNotNull(item.latitude)36 assertTrue(item.facts.any { it.label == "Taille" && it.value == "4½" })37 }3839 @Test40 fun autoKaMapping() {41 val u = Ecosystem.universe("auto-ka")!!42 val o = decode("""{"uid":"v:1","title":"Kia Forte 2010","make":"Kia","model":"Forte","year":2010,"price":1595,"price_label":"1 595 ${'$'}","mileage_label":"260 789 km","url":"https://x.com/v"}""")43 val item = u.map!!(o)!!44 assertEquals("1 595 $", item.priceLabel)45 assertTrue(item.subtitle!!.contains("2010"))46 assertTrue(item.facts.any { it.label == "Marque" && it.value == "Kia" })47 }4849 @Test50 fun jobKaSalary() {51 val u = Ecosystem.universe("job-ka")!!52 val o = decode("""{"uid":"j:1","title":"Analyste","employer":"TD","city":"Montréal","salary_year_min":65000}""")53 val item = u.map!!(o)!!54 assertTrue(item.priceLabel!!.contains("/an"))55 assertTrue(item.subtitle!!.contains("TD"))56 }5758 @Test59 fun trouveKaStripsHTML() {60 val u = Ecosystem.universe("trouve-ka")!!61 val o = decode("""{"url":"https://y.qc","title":"La <em>poutine</em>","snippet":"un plat & une légende","domain":"y.qc"}""")62 val item = u.map!!(o)!!63 assertEquals("La poutine", item.title)64 assertEquals("un plat & une légende", item.subtitle)65 }6667 @Test68 fun foodKaIgnoresPlaceholderPrice() {69 val u = Ecosystem.universe("food-ka")!!70 val o = decode("""{"uid":"p:1","name":"Prunes","price":0.01,"brand":"PA"}""")71 val item = u.map!!(o)!!72 assertNull("un prix placeholder (0,01 $) ne doit pas s'afficher", item.priceLabel)73 }7475 @Test76 fun foodKaShowsSalePrice() {77 val u = Ecosystem.universe("food-ka")!!78 val o = decode("""{"uid":"p:2","name":"Beurre","price":4.99,"regular_price":6.49,"on_sale":true,"brand":"Natrel"}""")79 val item = u.map!!(o)!!80 assertTrue("prix barré attendu", item.priceLabel!!.contains("rég."))81 assertTrue(item.facts.any { it.label == "Solde" })82 }8384 @Test85 fun creaKaPlatformsAndLinks() {86 val u = Ecosystem.universe("crea-ka")!!87 val o = decode("""{"cid":"c:1","display_name":"Créateur QC","niches":["humour"],"platforms":[{"platform":"youtube","url":"https://youtube.com/@qc","followers":120000,"handle":"qc"},{"platform":"tiktok","url":"https://tiktok.com/@qc","followers":50000}]}""")88 val item = u.map!!(o)!!89 assertTrue("abonnés cumulés attendus dans le sous-titre", item.subtitle!!.contains("abonnés"))90 assertEquals("https://youtube.com/@qc", item.url)91 assertTrue(item.links.any { it.label == "Youtube" && it.value == "https://youtube.com/@qc" })92 assertTrue(item.facts.any { it.label == "Youtube" })93 }9495 @Test96 fun firstUsableImageFromImagesArray() {97 val u = Ecosystem.universe("lou-ka")!!98 val o = decode("""{"uid":"a:2","title":"3½","images":["pas-une-url","https://cdn.x.com/1.jpg","https://cdn.x.com/2.jpg"]}""")99 val item = u.map!!(o)!!100 assertEquals("https://cdn.x.com/1.jpg", item.imageURL)101 }102103 @Test104 fun everyUniverseHasDistinctAccent() {105 val accents = Ecosystem.all.map { it.accentHex }106 assertEquals("chaque univers doit avoir un accent unique", accents.size, accents.toSet().size)107 // 12 univers — Groupe-KA (portail mère) est l'app elle-même, pas un univers listé108 assertEquals(12, Ecosystem.all.size)109 }110111 @Test112 fun listURLBuilding() {113 val sorti = Ecosystem.universe("sorti-ka")!!114 val url = UniverseService.listURL(sorti, query = "jazz", limit = 10)!!115 assertTrue("la query embarquée du listPath doit survivre", url.contains("upcoming=true"))116 assertTrue(url.contains("q=jazz"))117 assertTrue(url.contains("limit=10"))118 assertTrue(url.startsWith("https://www.sorti-ka.com/api/events"))119 }120121 @Test122 fun favoritesToggleAndCollections() {123 val file = File.createTempFile("ka-favoris", ".json").also { it.delete() }124 val store = FavoritesStore(file)125 val item = KAItem(id = "t:1", universeID = "lou-ka", title = "Test")126 assertFalse(store.isFavorite(item))127 store.toggle(item)128 assertTrue(store.isFavorite(item))129 store.addCollection("Week-end")130 val dest = store.collections.value.last()131 store.move(item, dest.id)132 assertTrue(store.collections.value.last().items.any { it.id == item.id })133 store.toggle(item)134 assertFalse(store.isFavorite(item))135 file.delete()136 }137138 @Test139 fun favoritesPersistAcrossInstances() {140 val file = File.createTempFile("ka-favoris", ".json").also { it.delete() }141 val store = FavoritesStore(file)142 store.toggle(KAItem(id = "t:2", universeID = "auto-ka", title = "Corolla"))143 val reloaded = FavoritesStore(file)144 assertTrue(reloaded.isFavorite(KAItem(id = "t:2", universeID = "auto-ka", title = "Corolla")))145 file.delete()146 }147}148