ProjetDetailNotesViewModelTest.swift 78 lignes · 3027 octets
import XCTest
@testable import Card2vcf

/// Preuve de rougeur (exigence du plan `docs/plans/rattrapage-ios-et-tests.md`, § 1b) :
/// en remplaçant le tri dans `ProjetDetailViewModel.refresh` par `notesProjet = rawNotes`,
/// le test `testNotesTrieesParDateDecroissante` échoue avec :
///   XCTAssertEqual failed: ("Optional("n2")") is not equal to ("Optional("n1")")
/// Ce test détecte donc réellement l'absence de tri par date décroissante.
@MainActor
final class ProjetDetailNotesViewModelTest: XCTestCase {
    private var db: InMemoryCrmDatabase!

    override func setUp() {
        super.setUp()
        db = InMemoryCrmDatabase()
    }

    func testNotesTrieesParDateDecroissante() async throws {
        // Note n1 (insérée en 1re) : updatedAt = 1500 → date effective intermédiaire
        var note1 = NoteProjetEntity()
        note1.serverId = "n1"
        note1.projetServerId = "p1"
        note1.titre = "Note intermédiaire"
        note1.texte = "contenu 1"
        note1.auteur = "alice"
        note1.createdAt = 1000
        note1.updatedAt = 1500
        try await db.noteProjetDaoImpl.upsert(note1)

        // Note n2 (insérée en 2e) : updatedAt = 3000 → date effective la plus récente
        var note2 = NoteProjetEntity()
        note2.serverId = "n2"
        note2.projetServerId = "p1"
        note2.titre = "Note la plus récente"
        note2.texte = "contenu 2"
        note2.auteur = "bob"
        note2.createdAt = 2000
        note2.updatedAt = 3000
        try await db.noteProjetDaoImpl.upsert(note2)

        // Note n3 (insérée en 3e) : updatedAt nil → date effective = createdAt = 500
        var note3 = NoteProjetEntity()
        note3.serverId = "n3"
        note3.projetServerId = "p1"
        note3.titre = "Note la plus ancienne"
        note3.texte = "contenu 3"
        note3.auteur = "carol"
        note3.createdAt = 500
        note3.updatedAt = nil
        try await db.noteProjetDaoImpl.upsert(note3)

        let viewModel = ProjetDetailViewModel(projetServerId: "p1", database: db)
        await viewModel.refresh()

        XCTAssertEqual(3, viewModel.notesProjet.count)
        // Ordre attendu (décroissant) : n2 (3000) > n1 (1500) > n3 (500)
        // Sans tri (ordre d'insertion) : n1, n2, n3 → échoue sur [0]
        XCTAssertEqual("n2", viewModel.notesProjet[0].serverId)
        XCTAssertEqual("n1", viewModel.notesProjet[1].serverId)
        XCTAssertEqual("n3", viewModel.notesProjet[2].serverId)
    }

    func testNotesAutreProjetNonExposees() async throws {
        var note = NoteProjetEntity()
        note.serverId = "n-autre"
        note.projetServerId = "p-autre"
        note.titre = "Note d'un autre projet"
        note.texte = ""
        note.auteur = "dave"
        note.createdAt = 1000
        try await db.noteProjetDaoImpl.upsert(note)

        let viewModel = ProjetDetailViewModel(projetServerId: "p1", database: db)
        await viewModel.refresh()

        XCTAssertEqual(0, viewModel.notesProjet.count)
    }
}