Skip to content

Commit 77d143d

Browse files
sumeruchatsumchatteringcursoragent
authored
Expand CLAUDE.md with comprehensive inline documentation (#1007)
Co-authored-by: Sumeru Chatterjee <sumeru.chatterjee@me.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 0b5f228 commit 77d143d

3 files changed

Lines changed: 341 additions & 2 deletions

File tree

CLAUDE.md

Lines changed: 163 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,167 @@
22

33
🤖 **AI Agent Instructions**
44

5-
Please read the `AGENT_README.md` file for comprehensive project information, development workflow, and testing procedures.
5+
## Project Overview
6+
This is the **Iterable Swift SDK** for iOS/macOS integration. The SDK provides:
7+
- Push notification handling
8+
- In-app messaging
9+
- Event tracking
10+
- User management
11+
- Unknown user tracking
612

7-
All the information you need to work on this Iterable Swift SDK project is documented there.
13+
## Key Architecture
14+
- **Core SDK**: `swift-sdk/` - Main SDK implementation
15+
- **Sample Apps**: `sample-apps/` - Example integrations
16+
- **Tests**: `tests/` - Unit tests, UI tests, and integration tests
17+
- **Notification Extension**: `notification-extension/` - Rich push support
18+
19+
## Development Workflow
20+
21+
### 🔨 Building the SDK
22+
```bash
23+
./agent_build.sh
24+
```
25+
- Validates compilation on iOS Simulator
26+
- Shows build errors with context
27+
- Requires macOS with Xcode
28+
29+
### Listing All Available Tests
30+
31+
# List all available test suites
32+
```bash
33+
./agent_test.sh --list
34+
```
35+
36+
### 🧪 Running Tests
37+
```bash
38+
# Run all tests
39+
./agent_test.sh
40+
41+
# Run specific test suite
42+
./agent_test.sh IterableApiCriteriaFetchTests
43+
44+
# Run specific unit test (dot notation - recommended)
45+
./agent_test.sh "IterableApiCriteriaFetchTests.testForegroundCriteriaFetchWhenConditionsMet"
46+
47+
# Run any specific test with path
48+
./agent_test.sh "unit-tests/IterableApiCriteriaFetchTests/testForegroundCriteriaFetchWhenConditionsMet"
49+
```
50+
- Executes on iOS Simulator with accurate pass/fail reporting
51+
- Returns exit code 0 for success, 1 for failures
52+
- Shows detailed test counts and failure information
53+
- `--list` shows all test suites with test counts
54+
- Requires password for xcpretty installation (first run)
55+
56+
## Project Structure
57+
```
58+
swift-sdk/
59+
├── swift-sdk/ # Main SDK source
60+
│ ├── Core/ # Public APIs and models
61+
│ ├── Internal/ # Internal implementation
62+
│ ├── SDK/ # Main SDK entry points
63+
│ └── ui-components/ # SwiftUI/UIKit components
64+
├── tests/ # Test suites
65+
│ ├── unit-tests/ # Unit tests
66+
│ ├── ui-tests/ # UI automation tests
67+
│ └── endpoint-tests/ # API endpoint tests
68+
├── sample-apps/ # Example applications
69+
└── notification-extension/ # Push notification extension
70+
```
71+
72+
## Key Classes
73+
- **IterableAPI**: Main SDK interface
74+
- **IterableConfig**: Configuration management
75+
- **InternalIterableAPI**: Core implementation
76+
- **UnknownUserManager**: Unknown user tracking
77+
- **LocalStorage**: Data persistence
78+
79+
## Common Tasks
80+
81+
### Adding New Features
82+
1. Build first: `./agent_build.sh`
83+
2. Implement in `swift-sdk/Internal/` or `swift-sdk/SDK/`
84+
3. Add tests in `tests/unit-tests/`
85+
4. Verify: `./agent_test.sh` (all tests) or `./agent_test.sh YourTestSuite` (specific suite)
86+
87+
### Debugging Build Issues
88+
- Build script shows compilation errors with file paths
89+
- Check Xcode project references in `swift-sdk.xcodeproj/project.pbxproj`
90+
- Verify file renames are reflected in project file
91+
92+
### Test Failures
93+
- Test script shows specific failures with line numbers and detailed error messages
94+
- Run failing tests individually: `./agent_test.sh "TestSuite.testMethod"`
95+
- Mock classes available in `tests/common/`
96+
- Update parameter names when refactoring APIs
97+
98+
## Requirements
99+
- **macOS**: Required for Xcode builds
100+
- **Xcode**: Latest stable version
101+
- **Ruby**: For xcpretty (auto-installed)
102+
- **iOS Simulator**: For testing
103+
104+
## Quick Start for AI Agents
105+
1. Run `./agent_build.sh` to verify project builds
106+
2. Run `./agent_test.sh` to check test health (or `./agent_test.sh TestSuite` for specific suite)
107+
3. Make changes to source files
108+
4. Re-run both scripts to validate
109+
5. Debug failing tests: `./agent_test.sh "TestSuite.testMethod"`
110+
6. Commit when both pass ✅
111+
112+
## Test Filtering Examples
113+
```bash
114+
# Debug specific failing tests
115+
./agent_test.sh "IterableApiCriteriaFetchTests.testForegroundCriteriaFetchWhenConditionsMet"
116+
117+
# Run a problematic test suite
118+
./agent_test.sh ValidateCustomEventUserUpdateAPITest
119+
120+
# Check auth-related tests
121+
./agent_test.sh AuthTests
122+
```
123+
124+
## AI Agent Memory System
125+
126+
### 🧠 Update Instructions for AI Agents
127+
**IMPORTANT**: When you discover something useful while working on this codebase, update this README to help future AI agents. Add learnings to the sections below.
128+
129+
### 📍 Code Location Map
130+
- **Auth Logic**: `swift-sdk/Internal/AuthManager.swift` (main auth manager), `swift-sdk/Internal/Auth.swift` (auth models)
131+
- **API Calls**: `swift-sdk/Internal/api-client/ApiClient.swift` (main client), `swift-sdk/Internal/Network/NetworkHelper.swift` (networking)
132+
- **Models**: `swift-sdk/Core/Models/` (all data structures - CommerceItem, IterableInAppMessage, etc.)
133+
- **Main Entry**: `swift-sdk/SDK/IterableAPI.swift` (public-facing methods), `swift-sdk/Internal/InternalIterableAPI.swift` (core implementation) — note: public API surface lives in `IterableAPI.swift`, implementation details in `ApiClient.swift`
134+
- **Request Handling**: `swift-sdk/Internal/api-client/Request/` (online/offline processors)
135+
136+
### 🛠️ Common Task Recipes
137+
138+
**Add New API Endpoint:**
139+
1. Add path constant to `swift-sdk/Core/Constants.swift` in `Const.Path`
140+
2. Add method to `ApiClientProtocol.swift` and implement in `ApiClient.swift`
141+
3. Create request in `swift-sdk/Internal/api-client/Request/RequestCreator.swift`
142+
4. Add to `RequestHandlerProtocol.swift` and `RequestHandler.swift`
143+
144+
**Modify Auth Logic:**
145+
- Main logic: `swift-sdk/Internal/AuthManager.swift`
146+
- Token storage: `swift-sdk/Internal/Utilities/Keychain/IterableKeychain.swift`
147+
- Auth failures: Handle in `RequestProcessorUtil.swift`
148+
149+
**Add New Model:**
150+
- Create in `swift-sdk/Core/Models/YourModel.swift`
151+
- Make it `@objcMembers public class` for Objective-C compatibility
152+
- Implement `Codable` if it needs JSON serialization
153+
154+
### 🐛 Common Failure Solutions
155+
156+
**"Test X failed"** → Check test file in `tests/unit-tests/` - often parameter name mismatches after refactoring
157+
158+
**"Build failed: file not found"** → Update `swift-sdk.xcodeproj/project.pbxproj` to include new/renamed files
159+
160+
**"Auth token issues"** → Check `AuthManager.swift` and ensure JWT format is correct in tests
161+
162+
**"Network request fails"** → Check endpoint in `Constants.swift` and request creation in `RequestCreator.swift`
163+
164+
## Notes
165+
- Always test builds after refactoring
166+
- Parameter name changes require test file updates
167+
- Project file (`*.pbxproj`) may need manual updates for file renames
168+
- Sample apps demonstrate SDK usage patterns

agent_build.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/bash
2+
3+
# This script is to be used by LLMs and AI agents to build the Iterable Swift SDK on macOS.
4+
# It uses xcpretty to format the build output and only shows errors.
5+
# It also checks if the build is successful and exits with the correct status.
6+
7+
# Check if running on macOS
8+
if [[ "$(uname)" != "Darwin" ]]; then
9+
echo "❌ This script requires macOS to run Xcode builds"
10+
exit 1
11+
fi
12+
13+
# Make sure xcpretty is installed
14+
if ! command -v xcpretty &> /dev/null; then
15+
echo "xcpretty not found, installing via gem..."
16+
sudo gem install xcpretty
17+
fi
18+
19+
echo "Building Iterable Swift SDK..."
20+
21+
# Create a temporary file for the build output
22+
TEMP_OUTPUT=$(mktemp)
23+
24+
# Run the build and capture all output
25+
xcodebuild \
26+
-project swift-sdk.xcodeproj \
27+
-scheme "swift-sdk" \
28+
-configuration Debug \
29+
-sdk iphonesimulator \
30+
build > $TEMP_OUTPUT 2>&1
31+
32+
# Check the exit status
33+
BUILD_STATUS=$?
34+
35+
# Show errors and warnings if build failed
36+
if [ $BUILD_STATUS -eq 0 ]; then
37+
echo "✅ Iterable SDK build succeeded!"
38+
else
39+
echo "❌ Iterable SDK build failed with status $BUILD_STATUS"
40+
echo ""
41+
echo "🔍 Build errors:"
42+
grep -E 'error:|fatal:' $TEMP_OUTPUT | head -10
43+
echo ""
44+
echo "⚠️ Build warnings:"
45+
grep -E 'warning:' $TEMP_OUTPUT | head -5
46+
fi
47+
48+
# Remove the temporary file
49+
rm $TEMP_OUTPUT
50+
51+
exit $BUILD_STATUS

agent_test.sh

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/bin/bash
2+
3+
# Check if running on macOS
4+
if [[ "$(uname)" != "Darwin" ]]; then
5+
echo "❌ This script requires macOS to run Xcode tests"
6+
exit 1
7+
fi
8+
9+
# Parse command line arguments
10+
FILTER=""
11+
LIST_TESTS=false
12+
13+
if [[ $# -eq 1 ]]; then
14+
if [[ "$1" == "--list" ]]; then
15+
LIST_TESTS=true
16+
else
17+
FILTER="$1"
18+
echo "🎯 Running tests with filter: $FILTER"
19+
fi
20+
elif [[ $# -gt 1 ]]; then
21+
echo "❌ Usage: $0 [filter|--list]"
22+
echo " filter: Test suite name (e.g., 'IterableApiCriteriaFetchTests')"
23+
echo " or specific test (e.g., 'IterableApiCriteriaFetchTests.testForegroundCriteriaFetchWhenConditionsMet')"
24+
echo " or full path (e.g., 'unit-tests/IterableApiCriteriaFetchTests/testForegroundCriteriaFetchWhenConditionsMet')"
25+
echo " --list: List all available test suites and tests"
26+
exit 1
27+
fi
28+
29+
# Handle test listing
30+
if [[ "$LIST_TESTS" == true ]]; then
31+
echo "📋 Listing available test suites..."
32+
33+
# Use grep to extract test class names from source files
34+
echo "📦 Available Test Suites:"
35+
find tests/unit-tests -name "*.swift" -exec basename {} .swift \; | sort | while read test_file; do
36+
# Count test methods in each file
37+
test_count=$(grep -c "func test" "tests/unit-tests/$test_file.swift" 2>/dev/null || echo "0")
38+
echo "$test_file ($test_count tests)"
39+
done
40+
41+
echo ""
42+
echo "🔍 Example Usage:"
43+
echo " ./agent_test.sh AuthTests"
44+
echo " ./agent_test.sh \"AuthTests.testAsyncAuthTokenRetrieval\""
45+
echo ""
46+
echo "💡 To see specific test methods in a suite, check the source file:"
47+
echo " grep 'func test' tests/unit-tests/AuthTests.swift"
48+
49+
exit 0
50+
fi
51+
52+
# Make sure xcpretty is installed
53+
if ! command -v xcpretty &> /dev/null; then
54+
echo "xcpretty not found, installing via gem..."
55+
sudo gem install xcpretty
56+
fi
57+
58+
echo "Running Iterable Swift SDK unit tests..."
59+
60+
# Create a temporary file for the test output
61+
TEMP_OUTPUT=$(mktemp)
62+
63+
# Build the xcodebuild command
64+
XCODEBUILD_CMD="xcodebuild test \
65+
-project swift-sdk.xcodeproj \
66+
-scheme swift-sdk \
67+
-sdk iphonesimulator \
68+
-destination 'platform=iOS Simulator,name=iPhone 16 Pro,OS=18.2' \
69+
-enableCodeCoverage YES \
70+
-skipPackagePluginValidation \
71+
CODE_SIGNING_REQUIRED=NO"
72+
73+
# Add filter if specified
74+
if [[ -n "$FILTER" ]]; then
75+
# If filter contains a slash, use it as-is (already in unit-tests/TestSuite/testMethod format)
76+
if [[ "$FILTER" == *"/"* ]]; then
77+
XCODEBUILD_CMD="$XCODEBUILD_CMD -only-testing:$FILTER"
78+
# If filter contains a dot, convert TestSuite.testMethod to unit-tests/TestSuite/testMethod
79+
elif [[ "$FILTER" == *"."* ]]; then
80+
TEST_SUITE=$(echo "$FILTER" | cut -d'.' -f1)
81+
TEST_METHOD=$(echo "$FILTER" | cut -d'.' -f2)
82+
XCODEBUILD_CMD="$XCODEBUILD_CMD -only-testing:unit-tests/$TEST_SUITE/$TEST_METHOD"
83+
# Otherwise, assume it's just a test suite name and add the target
84+
else
85+
XCODEBUILD_CMD="$XCODEBUILD_CMD -only-testing:unit-tests/$FILTER"
86+
fi
87+
fi
88+
89+
# Run the tests with xcpretty for clean output (incremental - skips rebuild if possible)
90+
eval $XCODEBUILD_CMD 2>&1 | tee $TEMP_OUTPUT | xcpretty
91+
92+
# Check the exit status
93+
TEST_STATUS=$?
94+
95+
# Parse the "Executed X test(s), with Y failure(s)" line
96+
EXECUTED_LINE=$(grep "Executed.*test.*with.*failure" $TEMP_OUTPUT | tail -1)
97+
if [[ -n "$EXECUTED_LINE" ]]; then
98+
TOTAL_TESTS=$(echo "$EXECUTED_LINE" | sed -n 's/.*Executed \([0-9][0-9]*\) test.*/\1/p')
99+
FAILED_TESTS=$(echo "$EXECUTED_LINE" | sed -n 's/.*with \([0-9][0-9]*\) failure.*/\1/p')
100+
101+
# Ensure we have valid numbers
102+
if [[ -z "$TOTAL_TESTS" ]]; then TOTAL_TESTS=0; fi
103+
if [[ -z "$FAILED_TESTS" ]]; then FAILED_TESTS=0; fi
104+
105+
PASSED_TESTS=$(($TOTAL_TESTS - $FAILED_TESTS))
106+
else
107+
TOTAL_TESTS=0
108+
FAILED_TESTS=0
109+
PASSED_TESTS=0
110+
fi
111+
112+
# Show test results
113+
if [ "$FAILED_TESTS" -eq 0 ] && [ "$TOTAL_TESTS" -gt 0 ]; then
114+
echo "✅ All tests passed! ($TOTAL_TESTS tests)"
115+
FINAL_STATUS=0
116+
elif [ "$FAILED_TESTS" -gt 0 ]; then
117+
echo "❌ Tests failed: $FAILED_TESTS failed, $PASSED_TESTS passed ($TOTAL_TESTS total)"
118+
FINAL_STATUS=1
119+
else
120+
echo "⚠️ No test results found"
121+
FINAL_STATUS=$TEST_STATUS
122+
fi
123+
124+
# Remove the temporary file
125+
rm $TEMP_OUTPUT
126+
127+
exit $FINAL_STATUS

0 commit comments

Comments
 (0)