InMemoryCrmDatabase.swift
513 lignes · 15304 octets
import Foundation @testable import Card2vcf /// In-memory `CrmDatabase` double (Android tests used a Room in-memory database). /// Reproduces the Room semantics documented on each DAO port. final class InMemoryCrmDatabase: CrmDatabase { let contactDaoImpl = InMemoryCrmContactDao() let entrepriseDaoImpl = InMemoryEntrepriseDao() let projetDaoImpl = InMemoryProjetDao() let tacheDaoImpl = InMemoryTacheDao() let interactionDaoImpl = InMemoryInteractionDao() let workflowDaoImpl = InMemoryWorkflowDao() let rdvDaoImpl = InMemoryRdvDao() let reservationDaoImpl = InMemoryReservationDao() let indisponibiliteDaoImpl = InMemoryIndisponibiliteDao() let syncMetaDaoImpl = InMemorySyncMetaDao() let syncOpDaoImpl = InMemorySyncOpDao() let noteProjetDaoImpl = InMemoryNoteProjetDao() var crmContactDao: CrmContactDao { contactDaoImpl } var entrepriseDao: EntrepriseDao { entrepriseDaoImpl } var projetDao: ProjetDao { projetDaoImpl } var tacheDao: TacheDao { tacheDaoImpl } var interactionDao: InteractionDao { interactionDaoImpl } var workflowDao: WorkflowDao { workflowDaoImpl } var rdvDao: RdvDao { rdvDaoImpl } var reservationDao: ReservationDao { reservationDaoImpl } var indisponibiliteDao: IndisponibiliteDao { indisponibiliteDaoImpl } var syncMetaDao: SyncMetaDao { syncMetaDaoImpl } var syncOpDao: SyncOpDao { syncOpDaoImpl } var noteProjetDao: NoteProjetDao { noteProjetDaoImpl } } final class InMemoryCrmContactDao: CrmContactDao { private var rows: [CrmContactEntity] = [] private var exclusions: [DuplicateExclusionEntity] = [] private var nextId: Int64 = 1 @discardableResult func insert(_ entity: CrmContactEntity) async throws -> Int64 { var row = entity if row.id == 0 { row.id = nextId nextId += 1 } else { rows.removeAll { $0.id == row.id } nextId = max(nextId, row.id + 1) } rows.append(row) return row.id } func update(_ entity: CrmContactEntity) async throws { if let index = rows.firstIndex(where: { $0.id == entity.id }) { rows[index] = entity } } func deleteById(_ id: Int64) async throws { rows.removeAll { $0.id == id } } func getById(_ id: Int64) async throws -> CrmContactEntity? { rows.first { $0.id == id } } func getByServerId(_ serverId: String) async throws -> CrmContactEntity? { rows.first { $0.serverId == serverId } } func deleteByServerId(_ serverId: String) async throws { rows.removeAll { $0.serverId == serverId } } func fetchAll() async throws -> [CrmContactEntity] { rows.sorted { $0.createdAt > $1.createdAt } } func getAll() async throws -> [CrmContactEntity] { try await fetchAll() } func searchIds(_ query: String) async throws -> [Int64] { [] } @discardableResult func insertExclusion(_ ex: DuplicateExclusionEntity) async throws -> Int64 { if exclusions.contains(where: { $0.idA == ex.idA && $0.idB == ex.idB }) { return -1 } var row = ex row.id = nextId nextId += 1 exclusions.append(row) return row.id } func getExclusions() async throws -> [DuplicateExclusionEntity] { exclusions } func deleteExclusionsFor(_ id: Int64) async throws { exclusions.removeAll { $0.idA == id || $0.idB == id } } } final class InMemoryEntrepriseDao: EntrepriseDao { private var rows: [EntrepriseEntity] = [] private var nextId: Int64 = 1 @discardableResult func upsert(_ entity: EntrepriseEntity) async throws -> Int64 { var row = entity if row.localId == 0 { row.localId = nextId nextId += 1 } else { rows.removeAll { $0.localId == row.localId } nextId = max(nextId, row.localId + 1) } rows.append(row) return row.localId } func getByServerId(_ serverId: String) async throws -> EntrepriseEntity? { rows.first { $0.serverId == serverId } } func getByLocalId(_ localId: Int64) async throws -> EntrepriseEntity? { rows.first { $0.localId == localId } } func deleteByServerId(_ serverId: String) async throws { rows.removeAll { $0.serverId == serverId } } func listAll() async throws -> [EntrepriseEntity] { rows } } final class InMemoryProjetDao: ProjetDao { private var rows: [ProjetEntity] = [] private var nextId: Int64 = 1 @discardableResult func upsert(_ entity: ProjetEntity) async throws -> Int64 { var row = entity if row.localId == 0 { row.localId = nextId nextId += 1 } else { rows.removeAll { $0.localId == row.localId } nextId = max(nextId, row.localId + 1) } rows.append(row) return row.localId } func getByServerId(_ serverId: String) async throws -> ProjetEntity? { rows.first { $0.serverId == serverId } } func getByLocalId(_ localId: Int64) async throws -> ProjetEntity? { rows.first { $0.localId == localId } } func deleteByServerId(_ serverId: String) async throws { rows.removeAll { $0.serverId == serverId } } func listAll() async throws -> [ProjetEntity] { rows } func fetchAll() async throws -> [ProjetEntity] { rows.sorted { $0.nom < $1.nom } } } final class InMemoryTacheDao: TacheDao { private var rows: [TacheEntity] = [] private var nextId: Int64 = 1 @discardableResult func upsert(_ entity: TacheEntity) async throws -> Int64 { var row = entity if row.localId == 0 { row.localId = nextId nextId += 1 } else { rows.removeAll { $0.localId == row.localId } nextId = max(nextId, row.localId + 1) } rows.append(row) return row.localId } func getByServerId(_ serverId: String) async throws -> TacheEntity? { rows.first { $0.serverId == serverId } } func getByLocalId(_ localId: Int64) async throws -> TacheEntity? { rows.first { $0.localId == localId } } func deleteByServerId(_ serverId: String) async throws { rows.removeAll { $0.serverId == serverId } } func deleteByLocalId(_ localId: Int64) async throws { rows.removeAll { $0.localId == localId } } func listByProjetServerId(_ projetServerId: String) async throws -> [TacheEntity] { rows.filter { $0.projetServerId == projetServerId } } func fetchByProjetServerId(_ projetServerId: String) async throws -> [TacheEntity] { rows.filter { $0.projetServerId == projetServerId }.sorted { $0.ordre < $1.ordre } } func listAll() async throws -> [TacheEntity] { rows } } final class InMemoryInteractionDao: InteractionDao { private var rows: [InteractionEntity] = [] private var nextId: Int64 = 1 @discardableResult func upsert(_ entity: InteractionEntity) async throws -> Int64 { var row = entity if row.localId == 0 { row.localId = nextId nextId += 1 } else { rows.removeAll { $0.localId == row.localId } nextId = max(nextId, row.localId + 1) } rows.append(row) return row.localId } func getByServerId(_ serverId: String) async throws -> InteractionEntity? { rows.first { $0.serverId == serverId } } func getByLocalId(_ localId: Int64) async throws -> InteractionEntity? { rows.first { $0.localId == localId } } func deleteByServerId(_ serverId: String) async throws { rows.removeAll { $0.serverId == serverId } } func deleteByLocalId(_ localId: Int64) async throws { rows.removeAll { $0.localId == localId } } func listByContactServerId(_ contactServerId: String) async throws -> [InteractionEntity] { rows.filter { $0.contactServerId == contactServerId } } func fetchByContactServerId(_ contactServerId: String) async throws -> [InteractionEntity] { rows.filter { $0.contactServerId == contactServerId }.sorted { $0.createdAt > $1.createdAt } } func listAll() async throws -> [InteractionEntity] { rows } } final class InMemoryWorkflowDao: WorkflowDao { private var rows: [String: WorkflowEntity] = [:] func upsert(_ entity: WorkflowEntity) async throws { rows[entity.serverId] = entity } func getByServerId(_ serverId: String) async throws -> WorkflowEntity? { rows[serverId] } func deleteByServerId(_ serverId: String) async throws { rows.removeValue(forKey: serverId) } func listAll() async throws -> [WorkflowEntity] { Array(rows.values) } } final class InMemoryRdvDao: RdvDao { private var rows: [RdvEntity] = [] private var nextId: Int64 = 1 @discardableResult func upsert(_ entity: RdvEntity) async throws -> Int64 { var row = entity if row.localId == 0 { row.localId = nextId nextId += 1 } else { rows.removeAll { $0.localId == row.localId } nextId = max(nextId, row.localId + 1) } rows.append(row) return row.localId } func getByServerId(_ serverId: String) async throws -> RdvEntity? { rows.first { $0.serverId == serverId } } func getByLocalId(_ localId: Int64) async throws -> RdvEntity? { rows.first { $0.localId == localId } } func getByCalendarEventId(_ calendarEventId: Int64) async throws -> RdvEntity? { rows.first { $0.calendarEventId == calendarEventId } } func listDirty() async throws -> [RdvEntity] { rows.filter { $0.dirtyLocal } } func deleteByServerId(_ serverId: String) async throws { rows.removeAll { $0.serverId == serverId } } func deleteByLocalId(_ localId: Int64) async throws { rows.removeAll { $0.localId == localId } } func listAll() async throws -> [RdvEntity] { rows } } final class InMemoryReservationDao: ReservationDao { private var rows: [ReservationEntity] = [] private var nextId: Int64 = 1 @discardableResult func upsert(_ entity: ReservationEntity) async throws -> Int64 { var row = entity if row.localId == 0 { row.localId = nextId nextId += 1 } else { rows.removeAll { $0.localId == row.localId } nextId = max(nextId, row.localId + 1) } rows.append(row) return row.localId } func getByServerId(_ serverId: String) async throws -> ReservationEntity? { rows.first { $0.serverId == serverId } } func getByLocalId(_ localId: Int64) async throws -> ReservationEntity? { rows.first { $0.localId == localId } } func getByCalendarEventId(_ calendarEventId: Int64) async throws -> ReservationEntity? { rows.first { $0.calendarEventId == calendarEventId } } func listDirty() async throws -> [ReservationEntity] { rows.filter { $0.dirtyLocal } } func deleteByServerId(_ serverId: String) async throws { rows.removeAll { $0.serverId == serverId } } func deleteByLocalId(_ localId: Int64) async throws { rows.removeAll { $0.localId == localId } } func listByCible(cibleType: String, cibleId: String) async throws -> [ReservationEntity] { rows.filter { $0.cibleType == cibleType && $0.cibleId == cibleId } } func listAll() async throws -> [ReservationEntity] { rows } } final class InMemoryIndisponibiliteDao: IndisponibiliteDao { private var rows: [IndisponibiliteEntity] = [] private var nextId: Int64 = 1 @discardableResult func upsert(_ entity: IndisponibiliteEntity) async throws -> Int64 { var row = entity if row.localId == 0 { row.localId = nextId nextId += 1 } else { rows.removeAll { $0.localId == row.localId } nextId = max(nextId, row.localId + 1) } rows.append(row) return row.localId } func getByServerId(_ serverId: String) async throws -> IndisponibiliteEntity? { rows.first { $0.serverId == serverId } } func deleteByServerId(_ serverId: String) async throws { rows.removeAll { $0.serverId == serverId } } func listByCible(cibleType: String, cibleId: String) async throws -> [IndisponibiliteEntity] { rows.filter { $0.cibleType == cibleType && $0.cibleId == cibleId } } func listAll() async throws -> [IndisponibiliteEntity] { rows } } final class InMemorySyncMetaDao: SyncMetaDao { private var rows: [String: SyncMetaEntity] = [:] func upsert(_ entity: SyncMetaEntity) async throws { rows[entity.key] = entity } func get(_ key: String) async throws -> SyncMetaEntity? { rows[key] } } final class InMemorySyncOpDao: SyncOpDao { private var rows: [SyncOpEntity] = [] private var nextId: Int64 = 1 @discardableResult func insert(_ entity: SyncOpEntity) async throws -> Int64 { var row = entity if row.id == 0 { row.id = nextId nextId += 1 } else { rows.removeAll { $0.id == row.id } nextId = max(nextId, row.id + 1) } rows.append(row) return row.id } func listAll() async throws -> [SyncOpEntity] { rows.sorted { $0.createdAt < $1.createdAt } } func getById(_ id: Int64) async throws -> SyncOpEntity? { rows.first { $0.id == id } } func markFailure(id: Int64, error: String?) async throws { guard let index = rows.firstIndex(where: { $0.id == id }) else { return } rows[index].attempts += 1 rows[index].lastError = error } func deleteById(_ id: Int64) async throws { rows.removeAll { $0.id == id } } } final class InMemoryNoteProjetDao: NoteProjetDao { private var rows: [NoteProjetEntity] = [] private var nextId: Int64 = 1 @discardableResult func upsert(_ entity: NoteProjetEntity) async throws -> Int64 { var row = entity if row.localId == 0 { row.localId = nextId nextId += 1 } else { rows.removeAll { $0.localId == row.localId } nextId = max(nextId, row.localId + 1) } rows.append(row) return row.localId } func getByServerId(_ serverId: String) async throws -> NoteProjetEntity? { rows.first { $0.serverId == serverId } } func deleteByServerId(_ serverId: String) async throws { rows.removeAll { $0.serverId == serverId } } func deleteByLocalId(_ localId: Int64) async throws { rows.removeAll { $0.localId == localId } } func listByProjetServerId(_ projetServerId: String) async throws -> [NoteProjetEntity] { rows.filter { $0.projetServerId == projetServerId } } func listAll() async throws -> [NoteProjetEntity] { rows } }
GitRust