Skip to content

Commit 4cc91cf

Browse files
leogdionclaude
andcommitted
Add CLI subcommands and comprehensive integration tests for issue #199
Implements proper CLI subcommand architecture and integration tests that demonstrate the three new CloudKit operations (lookupZones, fetchRecordChanges, uploadAssets) working together in realistic workflows. New CLI Subcommands: - upload-asset: Upload binary assets to CloudKit - lookup-zones: Look up specific zones by name - fetch-changes: Fetch record changes with incremental sync - test-integration: Run comprehensive 8-phase integration tests Integration Test Suite (8 Phases): 1. Zone verification with lookupZones 2. Asset upload with uploadAssets (programmatic PNG generation) 3. Record creation with uploaded assets 4. Initial sync with fetchRecordChanges 5. Record modifications 6. Incremental sync demonstrating sync token usage 7. Final zone verification 8. Automatic cleanup Infrastructure: - CloudKitCommand protocol for shared functionality across subcommands - IntegrationTestRunner orchestrates all test phases - IntegrationTestData generates test PNG images programmatically - IntegrationTestError provides typed error handling - schema.ckdb defines MistKitIntegrationTest record type Architecture Changes: - Converted MistDemo from flag-based to subcommand architecture - Added Commands/ directory for subcommand implementations - Added Integration/ directory for test infrastructure - CloudKitCommand protocol resolves API tokens from env or options Documentation: - README-INTEGRATION-TESTS.md with complete usage guide - Schema deployment instructions - Troubleshooting guide - Example outputs for all commands All subcommands support: - API token from --api-token or CLOUDKIT_API_TOKEN env var - Container identifier configuration - Development/production environment selection Test integration features: - Configurable record count (--record-count) - Configurable asset size (--asset-size) - Verbose mode for detailed output (--verbose) - Skip cleanup flag for manual inspection (--skip-cleanup) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 1d0b348 commit 4cc91cf

10 files changed

Lines changed: 1670 additions & 0 deletions
Lines changed: 380 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
# MistDemo Integration Tests - Issue #199
2+
3+
This document describes the comprehensive integration test suite for the three new CloudKit operations added in issue #199: `lookupZones`, `fetchRecordChanges`, and `uploadAssets`.
4+
5+
## Overview
6+
7+
MistDemo has been enhanced with a proper CLI subcommand architecture and comprehensive integration tests that demonstrate all three new operations working together in realistic workflows.
8+
9+
## Available Commands
10+
11+
```bash
12+
# Show all available subcommands
13+
mistdemo --help
14+
15+
# Get help for a specific command
16+
mistdemo test-integration --help
17+
mistdemo upload-asset --help
18+
mistdemo lookup-zones --help
19+
mistdemo fetch-changes --help
20+
```
21+
22+
## Quick Start
23+
24+
### 1. Deploy CloudKit Schema (One-Time Setup)
25+
26+
Before running integration tests, deploy the schema to CloudKit:
27+
28+
```bash
29+
# Save your CloudKit management token
30+
xcrun cktool save-token
31+
32+
# Import the schema to development environment
33+
xcrun cktool import-schema \
34+
--team-id YOUR_TEAM_ID \
35+
--container-id iCloud.com.brightdigit.MistDemo \
36+
--environment development \
37+
--file schema.ckdb
38+
```
39+
40+
### 2. Run Integration Tests
41+
42+
```bash
43+
# Basic integration test
44+
swift run mistdemo test-integration --api-token YOUR_TOKEN
45+
46+
# Verbose mode with more records
47+
swift run mistdemo test-integration \
48+
--api-token YOUR_TOKEN \
49+
--record-count 20 \
50+
--verbose
51+
52+
# Skip cleanup to inspect records in CloudKit Console
53+
swift run mistdemo test-integration \
54+
--api-token YOUR_TOKEN \
55+
--skip-cleanup
56+
```
57+
58+
## Individual Operation Commands
59+
60+
### Upload Asset
61+
62+
Upload a binary file to CloudKit:
63+
64+
```bash
65+
# Upload a file
66+
swift run mistdemo upload-asset photo.jpg --api-token YOUR_TOKEN
67+
68+
# Upload and create a record
69+
swift run mistdemo upload-asset document.pdf \
70+
--create-record Document \
71+
--api-token YOUR_TOKEN
72+
```
73+
74+
**Features:**
75+
- Validates file existence
76+
- Displays upload progress
77+
- Returns asset tokens
78+
- Optionally creates a record with the asset
79+
80+
### Lookup Zones
81+
82+
Fetch detailed information about specific zones:
83+
84+
```bash
85+
# Lookup default zone
86+
swift run mistdemo lookup-zones "_defaultZone" --api-token YOUR_TOKEN
87+
88+
# Lookup multiple zones
89+
swift run mistdemo lookup-zones "Photos,Documents,Articles" --api-token YOUR_TOKEN
90+
```
91+
92+
**Features:**
93+
- Supports comma-separated zone names
94+
- Displays zone capabilities
95+
- Shows owner information
96+
97+
### Fetch Changes
98+
99+
Fetch record changes with incremental sync:
100+
101+
```bash
102+
# Initial fetch
103+
swift run mistdemo fetch-changes --api-token YOUR_TOKEN
104+
105+
# Incremental fetch with sync token
106+
swift run mistdemo fetch-changes \
107+
--sync-token "abc123..." \
108+
--api-token YOUR_TOKEN
109+
110+
# Fetch all with automatic pagination
111+
swift run mistdemo fetch-changes --fetch-all --api-token YOUR_TOKEN
112+
113+
# Custom zone and limit
114+
swift run mistdemo fetch-changes \
115+
--zone MyZone \
116+
--limit 50 \
117+
--api-token YOUR_TOKEN
118+
```
119+
120+
**Features:**
121+
- Supports sync tokens for incremental sync
122+
- Automatic pagination with `--fetch-all`
123+
- Displays sync tokens for next fetch
124+
- Shows `moreComing` flag
125+
126+
## Integration Test Suite
127+
128+
The `test-integration` command runs a comprehensive 8-phase workflow:
129+
130+
### Phase 1: Zone Verification
131+
- Uses `lookupZones(zoneIDs: [.defaultZone])`
132+
- Verifies zone exists before testing
133+
- Displays zone capabilities
134+
135+
### Phase 2: Asset Upload
136+
- Generates test PNG image programmatically
137+
- Uploads using `uploadAssets(data:)`
138+
- Configurable size via `--asset-size` (default: 100 KB)
139+
140+
### Phase 3: Create Records with Assets
141+
- Creates N test records (default: 10)
142+
- Each record includes: title, index, image asset, timestamp
143+
- Uses record type: `MistKitIntegrationTest`
144+
145+
### Phase 4: Initial Sync
146+
- Fetches all records with `fetchRecordChanges()`
147+
- Saves sync token
148+
- Verifies test records are included
149+
150+
### Phase 5: Modify Records
151+
- Updates first 3 records
152+
- Adds "modified" boolean field
153+
- Changes title field
154+
155+
### Phase 6: Incremental Sync
156+
- Uses saved sync token
157+
- Fetches only modified records
158+
- Demonstrates incremental sync efficiency
159+
160+
### Phase 7: Final Zone Verification
161+
- Re-verifies zone state
162+
- Ensures operations didn't corrupt zone
163+
164+
### Phase 8: Cleanup
165+
- Deletes all test records
166+
- Skip with `--skip-cleanup` flag
167+
- Partial cleanup on errors
168+
169+
## Command Options
170+
171+
### Common Options
172+
173+
All subcommands support:
174+
175+
```bash
176+
--api-token <token> # CloudKit API token (or set CLOUDKIT_API_TOKEN env var)
177+
--container-identifier <id> # Container ID (default: iCloud.com.brightdigit.MistDemo)
178+
--environment <env> # development or production (default: development)
179+
```
180+
181+
### Test Integration Options
182+
183+
```bash
184+
--record-count <N> # Number of test records (default: 10)
185+
--asset-size <KB> # Asset size in KB (default: 100)
186+
--skip-cleanup # Leave test records in CloudKit
187+
--verbose # Show detailed progress
188+
```
189+
190+
## CloudKit Schema
191+
192+
The integration tests use a custom record type defined in `schema.ckdb`:
193+
194+
```
195+
RECORD TYPE MistKitIntegrationTest (
196+
"title" STRING QUERYABLE SORTABLE SEARCHABLE,
197+
"index" INT64 QUERYABLE SORTABLE,
198+
"image" ASSET,
199+
"createdAt" TIMESTAMP QUERYABLE SORTABLE,
200+
"modified" INT64 QUERYABLE,
201+
202+
GRANT READ, CREATE, WRITE TO "_creator",
203+
GRANT READ, CREATE, WRITE TO "_icloud",
204+
GRANT READ TO "_world"
205+
);
206+
```
207+
208+
**Field Descriptions:**
209+
- `title` - Test record title
210+
- `index` - Sequential number for ordering
211+
- `image` - Uploaded test asset
212+
- `createdAt` - Record creation timestamp
213+
- `modified` - Boolean flag (0/1) set during updates
214+
215+
## Example Output
216+
217+
```
218+
================================================================================
219+
🧪 Integration Test Suite: CloudKit Operations
220+
================================================================================
221+
Container: iCloud.com.brightdigit.MistDemo
222+
Environment: development
223+
Database: public
224+
Record Count: 10
225+
Asset Size: 100 KB
226+
================================================================================
227+
228+
📋 Phase 1: Verify zone exists
229+
✅ Found zone: _defaultZone
230+
231+
📤 Phase 2: Upload test assets
232+
✅ Uploaded asset: 102400 bytes
233+
234+
📝 Phase 3: Create records with assets
235+
✅ Created 10 records
236+
237+
🔄 Phase 4: Initial sync (fetch all changes)
238+
✅ Fetched 45 records
239+
Found 10 of our test records
240+
241+
✏️ Phase 5: Modify some records
242+
✅ Updated 3 records
243+
244+
🔄 Phase 6: Incremental sync (fetch only changes)
245+
✅ Fetched 3 changed records
246+
Found 3 of our modified records
247+
248+
🔍 Phase 7: Lookup zone details
249+
✅ Zone verification complete
250+
251+
🧹 Phase 8: Cleanup test records
252+
✅ Deleted 10 test records
253+
254+
================================================================================
255+
✅ Integration Test Complete!
256+
================================================================================
257+
258+
Phases Completed:
259+
✅ Zone verification with lookupZones
260+
✅ Asset upload with uploadAssets
261+
✅ Record creation with assets
262+
✅ Initial sync with fetchRecordChanges
263+
✅ Record modifications
264+
✅ Incremental sync with sync token
265+
✅ Final zone verification
266+
✅ Cleanup completed
267+
```
268+
269+
## Troubleshooting
270+
271+
### Schema Not Found
272+
273+
If you see errors about `MistKitIntegrationTest` not existing:
274+
275+
1. Verify schema was deployed: Check CloudKit Console → Schema
276+
2. Re-import schema using `cktool import-schema`
277+
3. Ensure you're using the correct environment (`--environment development`)
278+
279+
### Authentication Failed
280+
281+
If you see authentication errors:
282+
283+
1. Verify your API token: https://icloud.developer.apple.com/dashboard/
284+
2. Check token has permissions for the container
285+
3. Ensure token hasn't expired
286+
4. Try setting `CLOUDKIT_API_TOKEN` environment variable
287+
288+
### No Records Found
289+
290+
If integration tests report no records found:
291+
292+
1. Records may not be immediately available after creation
293+
2. Try running the test again
294+
3. Use `--skip-cleanup` and check CloudKit Console
295+
4. Verify you're using the correct database (public vs private)
296+
297+
## Architecture
298+
299+
### File Structure
300+
301+
```
302+
Examples/MistDemo/
303+
├── schema.ckdb # CloudKit schema
304+
├── Sources/MistDemo/
305+
│ ├── MistDemo.swift # Command group + CloudKitCommand protocol
306+
│ ├── Commands/
307+
│ │ ├── Auth.swift # Legacy auth server
308+
│ │ ├── UploadAsset.swift # Upload asset command
309+
│ │ ├── LookupZones.swift # Lookup zones command
310+
│ │ ├── FetchChanges.swift # Fetch changes command
311+
│ │ └── TestIntegration.swift # Integration test command
312+
│ ├── Integration/
313+
│ │ ├── IntegrationTestRunner.swift # 8-phase test orchestration
314+
│ │ ├── IntegrationTestData.swift # Test data generation
315+
│ │ └── IntegrationTestError.swift # Error types
316+
│ ├── Models/
317+
│ ├── Utilities/
318+
│ └── Resources/
319+
```
320+
321+
### CloudKitCommand Protocol
322+
323+
All subcommands conform to the `CloudKitCommand` protocol:
324+
325+
```swift
326+
protocol CloudKitCommand {
327+
var containerIdentifier: String { get }
328+
var apiToken: String { get }
329+
var environment: String { get }
330+
}
331+
332+
extension CloudKitCommand {
333+
func resolvedApiToken() -> String
334+
func cloudKitEnvironment() -> MistKit.Environment
335+
}
336+
```
337+
338+
## Testing with Live CloudKit
339+
340+
To test against your own CloudKit container:
341+
342+
1. Create a container at https://icloud.developer.apple.com/
343+
2. Generate an API token
344+
3. Deploy the schema to your container
345+
4. Update the default container ID or use `--container-identifier`
346+
5. Run tests:
347+
348+
```bash
349+
swift run mistdemo test-integration \
350+
--container-identifier iCloud.com.yourcompany.YourApp \
351+
--api-token YOUR_TOKEN \
352+
--environment development
353+
```
354+
355+
## Future Enhancements
356+
357+
Documented in the plan:
358+
359+
1. **Custom Zone Support** - Add `modifyZones` wrapper to test multi-zone scenarios
360+
2. **Pagination Testing** - Create 50+ records to trigger pagination
361+
3. **Error Scenario Testing** - Test invalid zones, corrupted tokens, oversized assets
362+
4. **Concurrent Operations** - Test parallel uploads and modifications
363+
5. **Performance Metrics** - Track timing for each phase
364+
6. **JSON Output** - Machine-readable results for CI/CD integration
365+
366+
## Contributing
367+
368+
When adding new CloudKit operations:
369+
370+
1. Create a subcommand in `Commands/`
371+
2. Implement the `CloudKitCommand` protocol
372+
3. Add to the `MistDemo.configuration.subcommands` array
373+
4. Update integration tests if needed
374+
5. Document usage in this README
375+
376+
## References
377+
378+
- Issue #199: CloudKit API Coverage
379+
- Commit: 1d0b348 - Add lookupZones, fetchRecordChanges, and uploadAssets operations
380+
- Plan: `/Users/leo/.claude/plans/eager-roaming-rainbow.md`

0 commit comments

Comments
 (0)