SPB Git forge

spb/ka-android

Public
4commits 1branches 0releases
1.6 MBsize
maindefault branch
1 mo agolast push
Kotlin 100%
6.1 KB · 162 lines kotlin
Raw Blame History
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// RefonteTests.kt — tests de la refonte v2 : clustering par grille (miroir3// iOS), historique consulté (dédupliqué, plafond 30), alertes honnêtes4// (markSeen), galerie multi-photos, garde Trouve-Ka (q obligatoire).5package com.groupeka.ka67import com.groupeka.ka.core.ClusterEngine8import com.groupeka.ka.core.Ecosystem9import com.groupeka.ka.core.KAItem10import com.groupeka.ka.core.RecentsStore11import com.groupeka.ka.core.SavedSearch12import com.groupeka.ka.core.UniverseService13import kotlinx.coroutines.runBlocking14import kotlinx.serialization.json.Json15import kotlinx.serialization.json.JsonObject16import org.junit.Assert.assertEquals17import org.junit.Assert.assertNull18import org.junit.Assert.assertTrue19import org.junit.Test20import java.io.File2122class RefonteTests {2324    private fun item(id: String, lat: Double, lon: Double) =25        KAItem(id = id, universeID = "lou-ka", title = id, latitude = lat, longitude = lon)2627    // MARK: clustering (miroir des 2 tests iOS)2829    @Test30    fun clusteringGroupsNearbyAndKeepsSingles() {31        val items = listOf(32            item("a", 46.805, -71.205),33            item("b", 46.806, -71.206),   // même cellule que a34            item("c", 46.90, -71.40),     // loin → seul35        )36        val clusters = ClusterEngine.clusterize(items, latSpan = 0.3, lonSpan = 0.3)37        assertEquals(2, clusters.size)38        val group = clusters.first { it.items.size == 2 }39        assertTrue(group.items.map { it.id }.containsAll(listOf("a", "b")))40        assertTrue(clusters.any { it.isSingle && it.item.id == "c" })41        // centroïde du groupe42        assertEquals(46.8055, group.latitude, 0.001)43    }4445    @Test46    fun clusteringCapsAt150Renderables() {47        val many = (0 until 400).map { i ->48            item("i$i", 40.0 + i * 0.5, -70.0 - i * 0.5) // tous éloignés → 400 cellules49        }50        val clusters = ClusterEngine.clusterize(many, latSpan = 250.0, lonSpan = 250.0)51        assertTrue("plafond de rendu 150", clusters.size <= 150)52    }5354    @Test55    fun clusteringIgnoresItemsWithoutCoordinates() {56        val items = listOf(57            KAItem(id = "x", universeID = "lou-ka", title = "sans coord"),58            item("y", 46.8, -71.2),59        )60        val clusters = ClusterEngine.clusterize(items, latSpan = 0.3, lonSpan = 0.3)61        assertEquals(1, clusters.size)62        assertEquals("y", clusters[0].item.id)63    }6465    // MARK: historique consulté6667    @Test68    fun historyDeduplicatesAndCapsAt30() {69        val file = File.createTempFile("ka-recents", ".json").also { it.delete() }70        val store = RecentsStore(file)71        for (i in 0 until 40) {72            store.record(KAItem(id = "it$i", universeID = "lou-ka", title = "It $i"))73        }74        // re-consulter un ancien → remonte en tête, sans doublon75        store.record(KAItem(id = "it35", universeID = "lou-ka", title = "It 35"))76        val viewed = store.viewed.value77        assertEquals(30, viewed.size)78        assertEquals("it35", viewed.first().id)79        assertEquals(1, viewed.count { it.id == "it35" })80        file.delete()81    }8283    @Test84    fun historyPersistsAcrossInstances() {85        val file = File.createTempFile("ka-recents", ".json").also { it.delete() }86        RecentsStore(file).record(KAItem(id = "p:1", universeID = "auto-ka", title = "Corolla"))87        val reloaded = RecentsStore(file)88        assertEquals("p:1", reloaded.viewed.value.first().id)89        file.delete()90    }9192    // MARK: alertes honnêtes9394    @Test95    fun markSeenFoldsDeltaIntoTotal() {96        val file = File.createTempFile("ka-recents", ".json").also { it.delete() }97        // injecter une recherche « déjà comptée » via la persistance98        file.writeText(99            """{"viewed":[],"searches":[{"id":"s1","name":"4½ Québec","universeID":"lou-ka","query":"4½","alertsOn":true,"lastTotal":100,"newCount":12}]}""",100        )101        val store2 = RecentsStore(file)102        assertEquals(12, store2.alertCount)103        store2.markSeen("s1")104        val s = store2.savedSearches.value.first()105        assertEquals(112, s.lastTotal)106        assertEquals(0, s.newCount)107        assertEquals(0, store2.alertCount)108        file.delete()109    }110111    @Test112    fun alertCountSumsOnlyEnabledAlerts() {113        val file = File.createTempFile("ka-recents", ".json").also { it.delete() }114        file.writeText(115            """{"viewed":[],"searches":[116                {"id":"a","name":"A","universeID":"lou-ka","query":"a","alertsOn":true,"newCount":5},117                {"id":"b","name":"B","universeID":"auto-ka","query":"b","alertsOn":false,"newCount":9}118            ]}""",119        )120        val store = RecentsStore(file)121        assertEquals(5, store.alertCount)122        file.delete()123    }124125    // MARK: galerie multi-photos126127    @Test128    fun galleryKeepsUpTo10HttpImages() {129        val u = Ecosystem.universe("auto-ka")!!130        val imgs = (1..14).joinToString(",") { "\"https://cdn.x.com/$it.jpg\"" }131        val o = Json.parseToJsonElement(132            """{"uid":"v:9","title":"Mazda 3","images":[$imgs,"pas-une-url"]}""",133        ) as JsonObject134        val item = u.map!!(o)!!135        assertEquals(10, item.imageURLs.size)136        assertEquals("https://cdn.x.com/1.jpg", item.imageURL)137        assertEquals(item.imageURL, item.imageURLs.first())138    }139140    // MARK: Trouve-Ka — recherche d'abord (l'API exige q, 422 sinon)141142    @Test143    fun trouveKaFetchWithoutQueryReturnsEmptyWithoutNetwork() = runBlocking {144        val u = Ecosystem.universe("trouve-ka")!!145        // pas de cacheDir ni de réseau nécessaire : la garde répond avant146        val items = UniverseService.fetch(u, query = null)147        assertTrue(items.isEmpty())148        assertNull(UniverseService.total(u, query = ""))149    }150151    // MARK: éditorial = requêtes réelles vers de vrais univers152153    @Test154    fun editorialCollectionsPointToRealUniverses() {155        val cols = com.groupeka.ka.core.Editorial.collections156        assertEquals(4, cols.size)157        cols.forEach { c ->158            assertTrue("univers inconnu ${c.universeID}", Ecosystem.universe(c.universeID) != null)159        }160    }161}162