NoteVocaleSuppressionRelanceTest.kt
269 lignes · 9305 octets
package fr.ebii.card2vcf.sync import android.content.Context import androidx.room.Room import androidx.test.core.app.ApplicationProvider import fr.ebii.card2vcf.data.CrmDatabase import fr.ebii.card2vcf.data.InteractionEntity import fr.ebii.card2vcf.data.NoteProjetEntity import kotlinx.coroutines.runBlocking import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config @RunWith(RobolectricTestRunner::class) @Config(sdk = [31]) class NoteVocaleSuppressionRelanceTest { private lateinit var db: CrmDatabase private lateinit var api: FakeAilianceApi private lateinit var engine: SyncEngine @Before fun setUp() { val ctx = ApplicationProvider.getApplicationContext<Context>() db = Room.inMemoryDatabaseBuilder(ctx, CrmDatabase::class.java) .allowMainThreadQueries() .build() api = FakeAilianceApi() engine = SyncEngine(api, db) } @After fun tearDown() = db.close() // ---- Push interaction delete ---- @Test fun push_interactionDelete_appelApiEtOpConsommee() = runBlocking { db.interactionDao().upsert( InteractionEntity( serverId = "iid-srv-1", contactServerId = "contact-srv-1", type = "note_vocale", sujet = "Note à supprimer", createdAt = 1L, ), ) db.syncOpDao().insert( SyncOpEntity( entityType = "interaction", op = "delete", payloadJson = "{}", serverId = "iid-srv-1", createdAt = 1L, ), ) engine.syncNow() assertEquals(1, api.deleteInteractionCalls.size) assertEquals("iid-srv-1", api.deleteInteractionCalls[0]) assertEquals(0, db.syncOpDao().listAll().size) } @Test fun push_interactionDelete_sansSrvId_opConservee() = runBlocking { db.syncOpDao().insert( SyncOpEntity( entityType = "interaction", op = "delete", payloadJson = "{}", serverId = null, createdAt = 1L, ), ) engine.syncNow() assertEquals(0, api.deleteInteractionCalls.size) // op sans serverId : abandon sans consommation assertEquals(1, db.syncOpDao().listAll().size) } @Test fun push_interactionDelete_echecApi_opConservee() = runBlocking { api.deleteInteractionResult = AilianceApiClient.ApiResult.Err(503, "Service indisponible") db.syncOpDao().insert( SyncOpEntity( entityType = "interaction", op = "delete", payloadJson = "{}", serverId = "iid-srv-2", createdAt = 1L, ), ) engine.syncNow() assertEquals(1, api.deleteInteractionCalls.size) assertEquals(1, db.syncOpDao().listAll().size) } // ---- Pull interaction avec transcriptionErreur ---- @Test fun pull_interaction_avecTranscriptionErreur_stockeChamp() = runBlocking { api.pullResult = AilianceApiClient.ApiResult.Ok( SyncPullResponse( serverTime = "2026-09-15T10:00:00Z", interactions = listOf( InteractionDto( id = "int-err-1", contactId = "contact-srv-1", typeInteraction = "note_vocale", sujet = "Note en échec", creeLe = "2026-09-14T08:00:00Z", transcription = "echec", transcriptionErreur = "délai de 30 s dépassé", ), ), ), ) engine.syncNow() val stored = db.interactionDao().getByServerId("int-err-1") assertNotNull(stored) assertEquals("echec", stored?.transcriptionStatut) assertEquals("délai de 30 s dépassé", stored?.transcriptionErreur) } @Test fun pull_interaction_transcriptionErreur_misAJourSurExistant() = runBlocking { db.interactionDao().upsert( InteractionEntity( serverId = "int-err-2", contactServerId = "contact-srv-1", type = "note_vocale", sujet = "Note", transcriptionStatut = "en_attente", transcriptionErreur = null, createdAt = parseIsoToEpochMs("2026-09-14T08:00:00Z"), updatedAt = parseIsoToEpochMs("2026-09-14T08:00:00Z"), ), ) api.pullResult = AilianceApiClient.ApiResult.Ok( SyncPullResponse( serverTime = "2026-09-15T10:00:00Z", interactions = listOf( InteractionDto( id = "int-err-2", contactId = "contact-srv-1", typeInteraction = "note_vocale", sujet = "Note", creeLe = "2026-09-14T08:00:00Z", misAJourLe = "2026-09-15T09:00:00Z", transcription = "echec", transcriptionErreur = "modèle introuvable", ), ), ), ) engine.syncNow() val updated = db.interactionDao().getByServerId("int-err-2") assertEquals("echec", updated?.transcriptionStatut) assertEquals("modèle introuvable", updated?.transcriptionErreur) } // ---- Pull note_projet avec transcriptionErreur ---- @Test fun pull_noteProjet_avecTranscriptionErreur_stockeChamp() = runBlocking { api.pullResult = AilianceApiClient.ApiResult.Ok( SyncPullResponse( serverTime = "2026-09-15T10:00:00Z", notes = listOf( NoteProjetDto( id = "note-err-1", projetId = "projet-srv-1", titre = "Note en échec", contenu = "", auteur = "alice", creeLe = "2026-09-14T08:00:00Z", transcription = "echec", transcriptionErreur = "audio corrompu", ), ), ), ) engine.syncNow() val stored = db.noteProjetDao().getByServerId("note-err-1") assertNotNull(stored) assertEquals("echec", stored?.transcriptionStatut) assertEquals("audio corrompu", stored?.transcriptionErreur) } @Test fun pull_noteProjet_transcriptionTerminee_erreurEffacee() = runBlocking { db.noteProjetDao().upsert( NoteProjetEntity( serverId = "note-err-2", projetServerId = "projet-srv-1", titre = "Note", texte = "", auteur = "alice", transcriptionStatut = "echec", transcriptionErreur = "ancienne erreur", createdAt = parseIsoToEpochMs("2026-09-14T08:00:00Z"), updatedAt = parseIsoToEpochMs("2026-09-14T08:00:00Z"), ), ) api.pullResult = AilianceApiClient.ApiResult.Ok( SyncPullResponse( serverTime = "2026-09-15T10:00:00Z", notes = listOf( NoteProjetDto( id = "note-err-2", projetId = "projet-srv-1", titre = "Note", contenu = "Transcription OK.", auteur = "alice", creeLe = "2026-09-14T08:00:00Z", majLe = "2026-09-15T09:00:00Z", transcription = "terminee", transcriptionErreur = null, ), ), ), ) engine.syncNow() val updated = db.noteProjetDao().getByServerId("note-err-2") assertEquals("terminee", updated?.transcriptionStatut) assertNull(updated?.transcriptionErreur) } // ---- FakeAilianceApi relance (smoke tests) ---- @Test fun fake_relancerTranscriptionInteraction_enregistreAppel() { val result = api.relancerTranscriptionInteraction("contact-srv-1", "iid-srv-1") assertEquals(AilianceApiClient.ApiResult.Ok(Unit), result) assertEquals(1, api.relancerTranscriptionInteractionCalls.size) assertEquals("contact-srv-1" to "iid-srv-1", api.relancerTranscriptionInteractionCalls[0]) } @Test fun fake_relancerTranscriptionNote_enregistreAppel() { val result = api.relancerTranscriptionNote("projet-srv-1", "note-srv-1") assertEquals(AilianceApiClient.ApiResult.Ok(Unit), result) assertEquals(1, api.relancerTranscriptionNoteCalls.size) assertEquals("projet-srv-1" to "note-srv-1", api.relancerTranscriptionNoteCalls[0]) } }
GitRust