From af75965a312b928f99d9153536702b2d851ff2c2 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Mon, 8 Jun 2026 17:36:39 +0200 Subject: [PATCH] =?UTF-8?q?domain:=20add=20pure-Kotlin=20models=20(Calenda?= =?UTF-8?q?rSource,=20EventInstance,=20EventDetail,=20=E2=80=A6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jeanlucmakiola/calendula/domain/Models.kt | 54 ++++++++++++++ .../calendula/domain/ModelsTest.kt | 74 +++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 app/src/main/java/de/jeanlucmakiola/calendula/domain/Models.kt create mode 100644 app/src/test/java/de/jeanlucmakiola/calendula/domain/ModelsTest.kt diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/domain/Models.kt b/app/src/main/java/de/jeanlucmakiola/calendula/domain/Models.kt new file mode 100644 index 0000000..5ccb921 --- /dev/null +++ b/app/src/main/java/de/jeanlucmakiola/calendula/domain/Models.kt @@ -0,0 +1,54 @@ +package de.jeanlucmakiola.calendula.domain + +import kotlin.time.Instant + +data class CalendarSource( + val id: Long, + val displayName: String, + val accountName: String, + val accountType: String, + val color: Int, + val isVisibleInSystem: Boolean, +) + +data class EventInstance( + val instanceId: Long, + val eventId: Long, + val calendarId: Long, + val title: String, + val start: Instant, + val end: Instant, + val isAllDay: Boolean, + val color: Int, + val location: String?, +) + +data class EventDetail( + val instance: EventInstance, + val description: String?, + val organizer: String?, + val attendees: List, + val rrule: String?, +) + +data class Attendee( + val name: String, + val email: String?, + val status: AttendeeStatus, +) + +enum class AttendeeStatus { + Accepted, + Declined, + Tentative, + NeedsAction, + Unknown, +} + +enum class FailureReason { + PermissionRevoked, + NoCalendarsConfigured, + ProviderUnavailable, + EventNotFound, + Unknown, +} diff --git a/app/src/test/java/de/jeanlucmakiola/calendula/domain/ModelsTest.kt b/app/src/test/java/de/jeanlucmakiola/calendula/domain/ModelsTest.kt new file mode 100644 index 0000000..2209173 --- /dev/null +++ b/app/src/test/java/de/jeanlucmakiola/calendula/domain/ModelsTest.kt @@ -0,0 +1,74 @@ +package de.jeanlucmakiola.calendula.domain + +import com.google.common.truth.Truth.assertThat +import kotlin.time.Instant +import org.junit.jupiter.api.Test + +class ModelsTest { + + @Test + fun `CalendarSource is a data class with structural equality`() { + val a = CalendarSource(1L, "Work", "x@y", "com.google", 0xFF112233.toInt(), true) + val b = CalendarSource(1L, "Work", "x@y", "com.google", 0xFF112233.toInt(), true) + assertThat(a).isEqualTo(b) + } + + @Test + fun `EventInstance is a data class with structural equality`() { + val start = Instant.fromEpochMilliseconds(0L) + val end = Instant.fromEpochMilliseconds(3_600_000L) + val a = EventInstance(10L, 1L, 1L, "Meet", start, end, false, 0xFF000000.toInt(), null) + val b = EventInstance(10L, 1L, 1L, "Meet", start, end, false, 0xFF000000.toInt(), null) + assertThat(a).isEqualTo(b) + } + + @Test + fun `AttendeeStatus enum has all five variants`() { + assertThat(AttendeeStatus.values().toSet()).isEqualTo( + setOf( + AttendeeStatus.Accepted, + AttendeeStatus.Declined, + AttendeeStatus.Tentative, + AttendeeStatus.NeedsAction, + AttendeeStatus.Unknown, + ) + ) + } + + @Test + fun `FailureReason enum has all five variants`() { + assertThat(FailureReason.values().toSet()).isEqualTo( + setOf( + FailureReason.PermissionRevoked, + FailureReason.NoCalendarsConfigured, + FailureReason.ProviderUnavailable, + FailureReason.EventNotFound, + FailureReason.Unknown, + ) + ) + } + + @Test + fun `EventDetail composes EventInstance plus extras`() { + val instance = EventInstance( + instanceId = 10L, + eventId = 1L, + calendarId = 1L, + title = "Meet", + start = Instant.fromEpochMilliseconds(0L), + end = Instant.fromEpochMilliseconds(60_000L), + isAllDay = false, + color = 0xFFAABBCC.toInt(), + location = null, + ) + val detail = EventDetail( + instance = instance, + description = "Brief description", + organizer = "x@y", + attendees = listOf(Attendee("Alice", "alice@x", AttendeeStatus.Accepted)), + rrule = "FREQ=WEEKLY", + ) + assertThat(detail.instance.title).isEqualTo("Meet") + assertThat(detail.attendees).hasSize(1) + } +}