summaryrefslogtreecommitdiff
path: root/android/app/src/test/java/org/terst/doot/widget/SlotPackerTest.kt
blob: b6a078c00cade946ec9e7036bd73cdc832c4d4ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package org.terst.doot.widget

import org.junit.Assert.*
import org.junit.Test
import org.terst.doot.widget.data.*
import java.time.Instant
import java.time.temporal.ChronoUnit

class SlotPackerTest {

    private fun makeEvent(startIso: String, endIso: String): WidgetItem = WidgetItem(
        id = "evt-$startIso", title = "Event", source = "calendar", type = "event",
        start = startIso, end = endIso
    )

    private fun makeTask(id: String): WidgetItem = WidgetItem(
        id = id, title = "Task $id", source = "todoist", type = "task",
        completable = true
    )

    private val now = Instant.parse("2026-06-28T10:15:00Z")

    @Test
    fun `empty tasks returns empty fragments`() {
        val result = SlotPacker.pack(emptyList(), emptyList(), now)
        assertTrue(result.isEmpty())
    }

    @Test
    fun `single task gets slot starting at now`() {
        val result = SlotPacker.pack(listOf(makeTask("t1")), emptyList(), now)
        assertEquals(1, result.size)
        assertEquals(1, result[0].slots.size)
        assertEquals(now, result[0].slots[0].slotStart)
        assertEquals(now.plus(1, ChronoUnit.HOURS), result[0].slots[0].slotEnd)
    }

    @Test
    fun `three tasks with no events form one fragment`() {
        val tasks = listOf(makeTask("t1"), makeTask("t2"), makeTask("t3"))
        val result = SlotPacker.pack(tasks, emptyList(), now)
        assertEquals(1, result.size)
        assertEquals(3, result[0].slots.size)
        assertEquals(result[0].slots[0].slotEnd, result[0].slots[1].slotStart)
        assertEquals(result[0].slots[1].slotEnd, result[0].slots[2].slotStart)
    }

    @Test
    fun `event between tasks splits into two fragments`() {
        val tasks = listOf(makeTask("t1"), makeTask("t2"), makeTask("t3"))
        // Event at 11:15–12:15 falls between slot 1 (10:15–11:15) and slot 2
        val event = makeEvent("2026-06-28T11:15:00Z", "2026-06-28T12:15:00Z")
        val result = SlotPacker.pack(tasks, listOf(event), now)

        assertEquals(2, result.size)
        assertEquals(1, result[0].slots.size)  // t1 before event
        assertEquals(2, result[1].slots.size)  // t2, t3 after event
    }

    @Test
    fun `task slot jumps past overlapping event`() {
        val tasks = listOf(makeTask("t1"))
        // Event occupies 10:00–11:30, overlaps with now (10:15)
        val event = makeEvent("2026-06-28T10:00:00Z", "2026-06-28T11:30:00Z")
        val result = SlotPacker.pack(tasks, listOf(event), now)

        assertEquals(1, result.size)
        val slotStart = result[0].slots[0].slotStart
        assertEquals(Instant.parse("2026-06-28T11:30:00Z"), slotStart)
    }

    @Test
    fun `fragment startTime and endTime match first and last slot`() {
        val tasks = listOf(makeTask("t1"), makeTask("t2"))
        val result = SlotPacker.pack(tasks, emptyList(), now)
        val frag = result[0]
        assertEquals(frag.slots.first().slotStart, frag.startTime)
        assertEquals(frag.slots.last().slotEnd, frag.endTime)
    }
}