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)
}
}
|