opencodekit 0.16.15 → 0.16.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -242
- package/dist/index.js +19 -6
- package/dist/template/.opencode/AGENTS.md +72 -236
- package/dist/template/.opencode/README.md +49 -482
- package/dist/template/.opencode/agent/build.md +71 -345
- package/dist/template/.opencode/agent/explore.md +47 -139
- package/dist/template/.opencode/agent/general.md +61 -172
- package/dist/template/.opencode/agent/looker.md +65 -161
- package/dist/template/.opencode/agent/painter.md +46 -200
- package/dist/template/.opencode/agent/plan.md +37 -220
- package/dist/template/.opencode/agent/review.md +72 -153
- package/dist/template/.opencode/agent/scout.md +44 -486
- package/dist/template/.opencode/agent/vision.md +63 -178
- package/dist/template/.opencode/command/create.md +75 -307
- package/dist/template/.opencode/command/design.md +53 -589
- package/dist/template/.opencode/command/handoff.md +76 -180
- package/dist/template/.opencode/command/init.md +45 -211
- package/dist/template/.opencode/command/plan.md +62 -514
- package/dist/template/.opencode/command/pr.md +56 -226
- package/dist/template/.opencode/command/research.md +55 -266
- package/dist/template/.opencode/command/resume.md +33 -138
- package/dist/template/.opencode/command/review-codebase.md +54 -202
- package/dist/template/.opencode/command/ship.md +78 -127
- package/dist/template/.opencode/command/start.md +47 -577
- package/dist/template/.opencode/command/status.md +60 -353
- package/dist/template/.opencode/command/ui-review.md +52 -298
- package/dist/template/.opencode/command/verify.md +36 -250
- package/dist/template/.opencode/memory.db-shm +0 -0
- package/dist/template/.opencode/memory.db-wal +0 -0
- package/dist/template/.opencode/opencode.json +133 -35
- package/dist/template/.opencode/plugin/README.md +40 -166
- package/dist/template/.opencode/plugin/compaction.ts +162 -131
- package/dist/template/.opencode/plugin/lib/memory-db.ts +112 -0
- package/dist/template/.opencode/plugin/swarm-enforcer.ts +182 -27
- package/dist/template/.opencode/skill/augment-context-engine/SKILL.md +112 -0
- package/dist/template/.opencode/skill/augment-context-engine/mcp.json +6 -0
- package/dist/template/.opencode/skill/core-data-expert/SKILL.md +82 -0
- package/dist/template/.opencode/skill/core-data-expert/references/batch-operations.md +543 -0
- package/dist/template/.opencode/skill/core-data-expert/references/cloudkit-integration.md +259 -0
- package/dist/template/.opencode/skill/core-data-expert/references/concurrency.md +522 -0
- package/dist/template/.opencode/skill/core-data-expert/references/fetch-requests.md +643 -0
- package/dist/template/.opencode/skill/core-data-expert/references/glossary.md +233 -0
- package/dist/template/.opencode/skill/core-data-expert/references/migration.md +393 -0
- package/dist/template/.opencode/skill/core-data-expert/references/model-configuration.md +597 -0
- package/dist/template/.opencode/skill/core-data-expert/references/performance.md +300 -0
- package/dist/template/.opencode/skill/core-data-expert/references/persistent-history.md +553 -0
- package/dist/template/.opencode/skill/core-data-expert/references/project-audit.md +60 -0
- package/dist/template/.opencode/skill/core-data-expert/references/saving.md +574 -0
- package/dist/template/.opencode/skill/core-data-expert/references/stack-setup.md +625 -0
- package/dist/template/.opencode/skill/core-data-expert/references/testing.md +300 -0
- package/dist/template/.opencode/skill/core-data-expert/references/threading.md +589 -0
- package/dist/template/.opencode/skill/swift-concurrency/SKILL.md +246 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/actors.md +640 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/async-algorithms.md +822 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/async-await-basics.md +249 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/async-sequences.md +670 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/core-data.md +533 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/glossary.md +128 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/linting.md +142 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/memory-management.md +542 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/migration.md +1076 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/performance.md +574 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/sendable.md +578 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/tasks.md +604 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/testing.md +565 -0
- package/dist/template/.opencode/skill/swift-concurrency/references/threading.md +452 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/SKILL.md +290 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-advanced.md +351 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-basics.md +284 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-transitions.md +326 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/image-optimization.md +286 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/layout-best-practices.md +312 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/liquid-glass.md +377 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/list-patterns.md +153 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/modern-apis.md +400 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/performance-patterns.md +377 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/scroll-patterns.md +305 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/sheet-navigation-patterns.md +292 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/state-management.md +447 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/text-formatting.md +285 -0
- package/dist/template/.opencode/skill/swiftui-expert-skill/references/view-structure.md +276 -0
- package/dist/template/.opencode/tool/action-queue.ts +308 -0
- package/dist/template/.opencode/tool/swarm.ts +65 -40
- package/package.json +16 -3
- package/dist/template/.opencode/.agents/skills/context7/SKILL.md +0 -88
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# Testing Core Data
|
|
2
|
+
|
|
3
|
+
Testing Core Data requires special setup to avoid conflicts and ensure fast, reliable tests.
|
|
4
|
+
|
|
5
|
+
## In-Memory Stores
|
|
6
|
+
|
|
7
|
+
Use in-memory stores for fast, isolated tests:
|
|
8
|
+
|
|
9
|
+
```swift
|
|
10
|
+
class CoreDataTestCase: XCTestCase {
|
|
11
|
+
var container: NSPersistentContainer!
|
|
12
|
+
var context: NSManagedObjectContext!
|
|
13
|
+
|
|
14
|
+
override func setUp() {
|
|
15
|
+
super.setUp()
|
|
16
|
+
|
|
17
|
+
container = NSPersistentContainer(name: "Model", managedObjectModel: Self.sharedModel)
|
|
18
|
+
|
|
19
|
+
let description = NSPersistentStoreDescription()
|
|
20
|
+
description.type = NSInMemoryStoreType
|
|
21
|
+
container.persistentStoreDescriptions = [description]
|
|
22
|
+
|
|
23
|
+
container.loadPersistentStores { description, error in
|
|
24
|
+
XCTAssertNil(error)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
context = container.viewContext
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
override func tearDown() {
|
|
31
|
+
context = nil
|
|
32
|
+
container = nil
|
|
33
|
+
super.tearDown()
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Shared Model Pattern
|
|
39
|
+
|
|
40
|
+
**Problem:** Multiple model instances cause entity description conflicts.
|
|
41
|
+
|
|
42
|
+
**Error:**
|
|
43
|
+
```
|
|
44
|
+
Failed to find a unique match for an NSEntityDescription
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Solution:** Use shared model instance:
|
|
48
|
+
|
|
49
|
+
```swift
|
|
50
|
+
extension NSManagedObjectModel {
|
|
51
|
+
static let shared: NSManagedObjectModel = {
|
|
52
|
+
guard let modelURL = Bundle.main.url(forResource: "Model", withExtension: "momd"),
|
|
53
|
+
let model = NSManagedObjectModel(contentsOf: modelURL) else {
|
|
54
|
+
fatalError("Failed to load model")
|
|
55
|
+
}
|
|
56
|
+
return model
|
|
57
|
+
}()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Use in tests
|
|
61
|
+
container = NSPersistentContainer(name: "Model", managedObjectModel: .shared)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Data Generators
|
|
65
|
+
|
|
66
|
+
Create reproducible test data:
|
|
67
|
+
|
|
68
|
+
```swift
|
|
69
|
+
class TestDataGenerator {
|
|
70
|
+
static func createArticle(
|
|
71
|
+
name: String = "Test Article",
|
|
72
|
+
views: Int = 0,
|
|
73
|
+
in context: NSManagedObjectContext
|
|
74
|
+
) -> Article {
|
|
75
|
+
let article = Article(context: context)
|
|
76
|
+
article.name = name
|
|
77
|
+
article.views = Int64(views)
|
|
78
|
+
article.creationDate = Date()
|
|
79
|
+
return article
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static func createArticles(
|
|
83
|
+
count: Int,
|
|
84
|
+
in context: NSManagedObjectContext
|
|
85
|
+
) -> [Article] {
|
|
86
|
+
return (0..<count).map { i in
|
|
87
|
+
createArticle(name: "Article \(i)", in: context)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Usage
|
|
93
|
+
func testFetchArticles() throws {
|
|
94
|
+
let articles = TestDataGenerator.createArticles(count: 10, in: context)
|
|
95
|
+
try context.save()
|
|
96
|
+
|
|
97
|
+
let fetchRequest = Article.fetchRequest()
|
|
98
|
+
let results = try context.fetch(fetchRequest)
|
|
99
|
+
|
|
100
|
+
XCTAssertEqual(results.count, 10)
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Testing Fetch Requests
|
|
105
|
+
|
|
106
|
+
```swift
|
|
107
|
+
func testFetchWithPredicate() throws {
|
|
108
|
+
// Setup
|
|
109
|
+
TestDataGenerator.createArticle(name: "Swift", views: 100, in: context)
|
|
110
|
+
TestDataGenerator.createArticle(name: "iOS", views: 50, in: context)
|
|
111
|
+
try context.save()
|
|
112
|
+
|
|
113
|
+
// Test
|
|
114
|
+
let fetchRequest = Article.fetchRequest()
|
|
115
|
+
fetchRequest.predicate = NSPredicate(format: "views > %d", 75)
|
|
116
|
+
|
|
117
|
+
let results = try context.fetch(fetchRequest)
|
|
118
|
+
|
|
119
|
+
// Verify
|
|
120
|
+
XCTAssertEqual(results.count, 1)
|
|
121
|
+
XCTAssertEqual(results.first?.name, "Swift")
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Testing Saves
|
|
126
|
+
|
|
127
|
+
```swift
|
|
128
|
+
func testSaveArticle() throws {
|
|
129
|
+
let article = TestDataGenerator.createArticle(in: context)
|
|
130
|
+
|
|
131
|
+
XCTAssertTrue(context.hasChanges)
|
|
132
|
+
|
|
133
|
+
try context.save()
|
|
134
|
+
|
|
135
|
+
XCTAssertFalse(context.hasChanges)
|
|
136
|
+
|
|
137
|
+
// Verify persistence
|
|
138
|
+
let fetchRequest = Article.fetchRequest()
|
|
139
|
+
let results = try context.fetch(fetchRequest)
|
|
140
|
+
|
|
141
|
+
XCTAssertEqual(results.count, 1)
|
|
142
|
+
XCTAssertEqual(results.first?.name, "Test Article")
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Testing Validation
|
|
147
|
+
|
|
148
|
+
```swift
|
|
149
|
+
func testValidation() {
|
|
150
|
+
let article = Article(context: context)
|
|
151
|
+
article.name = "" // Invalid
|
|
152
|
+
|
|
153
|
+
XCTAssertThrowsError(try context.save()) { error in
|
|
154
|
+
let nsError = error as NSError
|
|
155
|
+
XCTAssertEqual(nsError.domain, NSCocoaErrorDomain)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Testing Relationships
|
|
161
|
+
|
|
162
|
+
```swift
|
|
163
|
+
func testArticleCategoryRelationship() throws {
|
|
164
|
+
let category = Category(context: context)
|
|
165
|
+
category.name = "Swift"
|
|
166
|
+
|
|
167
|
+
let article = Article(context: context)
|
|
168
|
+
article.name = "Test"
|
|
169
|
+
article.category = category
|
|
170
|
+
|
|
171
|
+
try context.save()
|
|
172
|
+
|
|
173
|
+
XCTAssertEqual(article.category?.name, "Swift")
|
|
174
|
+
XCTAssertTrue(category.articles?.contains(article) ?? false)
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Testing Threading
|
|
179
|
+
|
|
180
|
+
```swift
|
|
181
|
+
func testBackgroundContext() {
|
|
182
|
+
let expectation = XCTestExpectation(description: "Background save")
|
|
183
|
+
|
|
184
|
+
let backgroundContext = container.newBackgroundContext()
|
|
185
|
+
backgroundContext.perform {
|
|
186
|
+
let article = Article(context: backgroundContext)
|
|
187
|
+
article.name = "Background Article"
|
|
188
|
+
|
|
189
|
+
do {
|
|
190
|
+
try backgroundContext.save()
|
|
191
|
+
expectation.fulfill()
|
|
192
|
+
} catch {
|
|
193
|
+
XCTFail("Save failed: \(error)")
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
wait(for: [expectation], timeout: 5.0)
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Testing CloudKit Sync
|
|
202
|
+
|
|
203
|
+
```swift
|
|
204
|
+
func testCloudKitExport() {
|
|
205
|
+
let expectation = XCTestExpectation(description: "Export")
|
|
206
|
+
|
|
207
|
+
let observer = NotificationCenter.default.addObserver(
|
|
208
|
+
forName: NSPersistentCloudKitContainer.eventChangedNotification,
|
|
209
|
+
object: container,
|
|
210
|
+
queue: nil
|
|
211
|
+
) { notification in
|
|
212
|
+
guard let event = notification.userInfo?[NSPersistentCloudKitContainer.eventNotificationUserInfoKey]
|
|
213
|
+
as? NSPersistentCloudKitContainer.Event else {
|
|
214
|
+
return
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if event.type == .export && event.endDate != nil {
|
|
218
|
+
expectation.fulfill()
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
let article = Article(context: context)
|
|
223
|
+
article.name = "Test"
|
|
224
|
+
try? context.save()
|
|
225
|
+
|
|
226
|
+
wait(for: [expectation], timeout: 60)
|
|
227
|
+
NotificationCenter.default.removeObserver(observer)
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Performance Testing
|
|
232
|
+
|
|
233
|
+
```swift
|
|
234
|
+
func testBatchInsertPerformance() {
|
|
235
|
+
measure {
|
|
236
|
+
let context = container.newBackgroundContext()
|
|
237
|
+
context.performAndWait {
|
|
238
|
+
var index = 0
|
|
239
|
+
let batchInsert = NSBatchInsertRequest(entity: Article.entity()) { object in
|
|
240
|
+
guard index < 1000 else { return true }
|
|
241
|
+
guard let article = object as? Article else { return true }
|
|
242
|
+
article.name = "Article \(index)"
|
|
243
|
+
index += 1
|
|
244
|
+
return false
|
|
245
|
+
}
|
|
246
|
+
try? context.execute(batchInsert)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Test Utilities
|
|
253
|
+
|
|
254
|
+
```swift
|
|
255
|
+
extension XCTestCase {
|
|
256
|
+
func createTestContainer() -> NSPersistentContainer {
|
|
257
|
+
let container = NSPersistentContainer(
|
|
258
|
+
name: "Model",
|
|
259
|
+
managedObjectModel: .shared
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
let description = NSPersistentStoreDescription()
|
|
263
|
+
description.type = NSInMemoryStoreType
|
|
264
|
+
container.persistentStoreDescriptions = [description]
|
|
265
|
+
|
|
266
|
+
let expectation = self.expectation(description: "Load store")
|
|
267
|
+
container.loadPersistentStores { _, error in
|
|
268
|
+
XCTAssertNil(error)
|
|
269
|
+
expectation.fulfill()
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
waitForExpectations(timeout: 5.0)
|
|
273
|
+
return container
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Best Practices
|
|
279
|
+
|
|
280
|
+
1. **Use in-memory stores** - Fast, isolated tests
|
|
281
|
+
2. **Use shared model** - Avoid entity description conflicts
|
|
282
|
+
3. **Create data generators** - Reproducible test data
|
|
283
|
+
4. **Test on background contexts** - Verify threading
|
|
284
|
+
5. **Use expectations** - For asynchronous operations
|
|
285
|
+
6. **Measure performance** - Use `measure` blocks
|
|
286
|
+
7. **Clean up** - Reset context between tests
|
|
287
|
+
8. **Test validation** - Verify business rules
|
|
288
|
+
9. **Test relationships** - Ensure integrity
|
|
289
|
+
10. **Test migrations** - Verify upgrade paths
|
|
290
|
+
|
|
291
|
+
## Summary
|
|
292
|
+
|
|
293
|
+
- Use in-memory stores for fast tests
|
|
294
|
+
- Share model instance to avoid conflicts
|
|
295
|
+
- Create data generators for reproducible tests
|
|
296
|
+
- Test fetch requests, saves, validation, and relationships
|
|
297
|
+
- Use expectations for async operations
|
|
298
|
+
- Measure performance with `measure` blocks
|
|
299
|
+
- Test threading with background contexts
|
|
300
|
+
- Test CloudKit sync with event notifications
|