← All repositories

listless

A simple list app for Apple platforms

git clone https://code.inqk.net/listless.git


Tests/Unit/ItemStoreTests.swift (6377B)

1import Foundation
2import Testing
3
4#if os(macOS)
5@testable import Listless
6#else
7@testable import Listless_iOS
8#endif
9
10@Suite("ItemStore CRUD Operations", .serialized)
11@MainActor
12struct ItemStoreTests {
13
14    // MARK: - Creation Tests
15
16    @Test("Create item with empty title")
17    func createItemWithEmptyTitle() async throws {
18        let store = makeTestStore()
19
20        let item = try store.createItem()
21
22        #expect(item.title == "")
23        #expect(item.id != UUID(uuidString: "00000000-0000-0000-0000-000000000000")!)
24        #expect(item.isCompleted == false)
25        #expect(item.createdAt.timeIntervalSinceNow > -1.0)
26    }
27
28    @Test("Create item with title")
29    func createItemWithTitle() async throws {
30        let store = makeTestStore()
31
32        let item = try store.createItem(title: "Buy groceries")
33
34        #expect(item.title == "Buy groceries")
35        #expect(item.id != UUID(uuidString: "00000000-0000-0000-0000-000000000000")!)
36    }
37
38    @Test("Create multiple items with unique IDs")
39    func createMultipleItemsWithUniqueIDs() async throws {
40        let store = makeTestStore()
41
42        let item1 = try store.createItem(title: "Item 1")
43        let item2 = try store.createItem(title: "Item 2")
44        let item3 = try store.createItem(title: "Item 3")
45
46        #expect(item1.id != item2.id)
47        #expect(item2.id != item3.id)
48        #expect(item1.id != item3.id)
49    }
50
51    @Test("Created item has timestamps")
52    func createdItemHasTimestamps() async throws {
53        let store = makeTestStore()
54
55        let beforeCreate = Date()
56        let item = try store.createItem(title: "Test")
57        let afterCreate = Date()
58
59        #expect(item.createdAt >= beforeCreate)
60        #expect(item.createdAt <= afterCreate)
61        #expect(item.updatedAt >= beforeCreate)
62        #expect(item.updatedAt <= afterCreate)
63    }
64
65    @Test("Create item at beginning prepends to active items")
66    func createItemAtBeginningPrepends() async throws {
67        let store = makeTestStore()
68
69        let first = try store.createItem(title: "First")
70        let second = try store.createItem(title: "Second")
71        let prepended = try store.createItem(title: "Prepended", atBeginning: true)
72
73        let items = try store.fetchItems().filter { !$0.isCompleted }
74
75        #expect(items.map(\.title) == ["Prepended", "First", "Second"])
76        #expect(prepended.sortOrder < first.sortOrder)
77        #expect(first.sortOrder < second.sortOrder)
78    }
79
80    // MARK: - Fetch Tests
81
82    @Test("Fetch items from empty store")
83    func fetchItemsFromEmptyStore() async throws {
84        let store = makeTestStore()
85
86        let items = try store.fetchItems()
87
88        #expect(items.isEmpty)
89    }
90
91    @Test("Fetch items returns created items")
92    func fetchItemsReturnsCreatedItems() async throws {
93        let store = makeTestStore()
94        _ = try store.createItem(title: "Item 1")
95        _ = try store.createItem(title: "Item 2")
96
97        let items = try store.fetchItems()
98
99        #expect(items.count == 2)
100        #expect(items[0].title == "Item 1")
101        #expect(items[1].title == "Item 2")
102    }
103
104    // MARK: - Update Tests
105
106    @Test("Update item title")
107    func updateItemTitle() async throws {
108        let store = makeTestStore()
109        let item = try store.createItem(title: "Original")
110
111        try store.update(itemID: item.id, title: "Updated")
112
113        let items = try store.fetchItems()
114        #expect(items.first?.title == "Updated")
115    }
116
117    @Test("Update item title without saving")
118    func updateItemTitleWithoutSaving() async throws {
119        let store = makeTestStore()
120        let item = try store.createItem(title: "Original")
121
122        try store.updateWithoutSaving(itemID: item.id, title: "Updated")
123
124        let items = try store.fetchItems()
125        #expect(items.first?.title == "Updated")
126    }
127
128    @Test("Update with invalid ID does nothing")
129    func updateWithInvalidIDDoesNothing() async throws {
130        let store = makeTestStore()
131        _ = try store.createItem(title: "Item 1")
132        let invalidID = UUID()
133
134        try store.update(itemID: invalidID, title: "Should not exist")
135
136        let items = try store.fetchItems()
137        #expect(items.count == 1)
138        #expect(items.first?.title == "Item 1")
139    }
140
141    // MARK: - Delete Tests
142
143    @Test("Delete item")
144    func deleteItem() async throws {
145        let store = makeTestStore()
146        let item1 = try store.createItem(title: "Item 1")
147        let item2 = try store.createItem(title: "Item 2")
148
149        try store.delete(itemID: item1.id)
150
151        let items = try store.fetchItems()
152        #expect(items.count == 1)
153        #expect(items.first?.id == item2.id)
154    }
155
156    @Test("Delete all items")
157    func deleteAllItems() async throws {
158        let store = makeTestStore()
159        let item1 = try store.createItem(title: "Item 1")
160        let item2 = try store.createItem(title: "Item 2")
161
162        try store.delete(itemID: item1.id)
163        try store.delete(itemID: item2.id)
164
165        let items = try store.fetchItems()
166        #expect(items.isEmpty)
167    }
168
169    @Test("Delete with invalid ID does nothing")
170    func deleteWithInvalidIDDoesNothing() async throws {
171        let store = makeTestStore()
172        _ = try store.createItem(title: "Item 1")
173        let invalidID = UUID()
174
175        try store.delete(itemID: invalidID)
176
177        let items = try store.fetchItems()
178        #expect(items.count == 1)
179    }
180
181    // MARK: - Edge Cases
182
183    @Test("Task IDs persist across fetches")
184    func itemIDsPersistAcrossFetches() async throws {
185        let store = makeTestStore()
186        let item = try store.createItem(title: "Test")
187        let originalID = item.id
188
189        let fetchedItems = try store.fetchItems()
190        let fetchedID = fetchedItems.first?.id
191
192        #expect(fetchedID == originalID)
193    }
194
195    @Test("Create item increments sortOrder")
196    func createItemIncrementsSortOrder() async throws {
197        let store = makeTestStore()
198
199        let item1 = try store.createItem(title: "Item 1")
200        let item2 = try store.createItem(title: "Item 2")
201        let item3 = try store.createItem(title: "Item 3")
202
203        #expect(item2.sortOrder > item1.sortOrder)
204        #expect(item3.sortOrder > item2.sortOrder)
205        #expect(item2.sortOrder - item1.sortOrder == 1000)
206        #expect(item3.sortOrder - item2.sortOrder == 1000)
207    }
208}