Skip to content

Commit 158fcf8

Browse files
kieran-osgood-shopifymarkmur
authored andcommitted
Add cursor rules for development / testing (#337)
* feat: add cursor rules for improving usage on swift * Apply suggestions from code review Co-authored-by: Mark Murray <[email protected]> * fix: update mdc files to add more context and refactor wording * refactor: add more examples for cursor rules and move dev descriptions to dev.yml --------- Co-authored-by: Mark Murray <[email protected]>
1 parent 7bfe03b commit 158fcf8

File tree

3 files changed

+161
-7
lines changed

3 files changed

+161
-7
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
description: Swift development workflow and language server workarounds
3+
globs: ["**/*.swift"]
4+
alwaysApply: true
5+
---
6+
7+
# SWIFT DEVELOPMENT WORKFLOW
8+
9+
## ⚠️ IMPORTANT: Language Server Issues
10+
11+
**IGNORE ALL LANGUAGE SERVER ERRORS IN SWIFT FILES**
12+
- The language server reports errors erroneously while code compiles fine
13+
- Do NOT trust red squiggles or inline error messages
14+
- Always verify issues using the commands below instead
15+
16+
## Verification Commands
17+
18+
### Check your work systematically:
19+
1. **Lint & Format** → `dev lint` (or `dev style`) - Checks for linting and stylistic errors
20+
2. **Build Issues** → `dev build` - Checks for compilation issues
21+
3. **Test Issues** → `dev test` - Checks for failing tests
22+
23+
### Available dev commands:
24+
**See `dev.yml` in project root for complete list of commands and descriptions.**
25+
26+
Key commands for verification:
27+
- `dev lint` (alias: `dev style`) - Check format & lint issues
28+
- `dev fix` - Auto-fix formatting and linting issues
29+
- `dev build packages` - Build both packages
30+
- `dev test packages` - Run all tests
31+
32+
## Concurrency Best Practices
33+
34+
### DO: Use actors for thread-safe shared state
35+
```swift
36+
actor QueryCache {
37+
private var cache: [String: Any] = [:]
38+
private var inflightRequests: [String: Any] = [:]
39+
40+
func loadCached<T>(...) async throws -> T {
41+
// Safe concurrent access to shared state
42+
}
43+
}
44+
```
45+
46+
## Workflow Best Practices
47+
48+
### When you see errors:
49+
❌ DON'T: Trust language server errors in Xcode/editor
50+
✅ DO: Run the appropriate dev command to verify
51+
52+
### After making changes:
53+
- ALWAYS run `dev fix && dev lint` to check your code is formatted and written in our style.
54+
55+
## Example Workflow
56+
57+
```bash
58+
# Make your Swift changes...
59+
60+
# Fix any auto-fixable issues
61+
dev fix
62+
63+
# Check for any remaining lint issues
64+
dev lint
65+
66+
# Verify it compiles
67+
dev build
68+
69+
# Run tests if needed
70+
dev test packages
71+
```

.cursor/rules/swift-test.mdc

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
description: Swift testing best practices and requirements
3+
globs: ["Tests/**/*.swift"]
4+
alwaysApply: true
5+
---
6+
7+
# SWIFT TESTING RULES
8+
9+
## Test Structure Requirements
10+
11+
### DO:
12+
- Create separate test methods for each test case
13+
- Use `guard` statements with `XCTFail` for unwrapping optionals
14+
```swift
15+
func testSomething() {
16+
guard let result = someOptionalValue else {
17+
XCTFail("Expected non-nil value")
18+
return
19+
}
20+
XCTAssertEqual(result, expectedValue)
21+
}
22+
```
23+
- Write focused tests that test one thing at a time
24+
- Use descriptive test method names in the format `test_<methodName>_<withCircumstances>_<shouldExpectation>`
25+
```
26+
func test_canTransition_fromAppleSheetPresentedState_shouldAllowPaymentAuthorizationAndInterruptAndCompleted()
27+
func test_ensureCurrencyNotChanged_withNoInitialCurrency_shouldNotThrow()
28+
```
29+
30+
- If a function may throw multiple types of errors, write multiple tests to capture them in isolation
31+
```
32+
func throwingFunction() {
33+
if someCondition {
34+
throw Error.foo
35+
} else
36+
throw Error.bar
37+
}
38+
39+
func test_throwingFunction_whenSomeConditionTrue_shouldThrowFoo() {
40+
do {
41+
_ = try await storefront.createCart()
42+
XCTFail("Expected error to be thrown")
43+
} catch {
44+
guard case let error = Error.foo else {
45+
XCTFail("Expected .foo")
46+
}
47+
}
48+
}
49+
func test_throwingFunction_whenSomeConditionTrue_shouldThrowBar(){
50+
do {
51+
_ = try await storefront.createCart()
52+
XCTFail("Expected error to be thrown")
53+
} catch {
54+
guard case let error = Error.foo else {
55+
XCTFail("Expected .foo")
56+
}
57+
}
58+
}
59+
```
60+
61+
## Code Examples
62+
63+
### ✅ CORRECT: Unwrapping optionals
64+
```swift
65+
func testSomething() {
66+
guard let result = someOptionalValue else {
67+
XCTFail("Expected non-nil value")
68+
return
69+
}
70+
XCTAssertEqual(result, expectedValue)
71+
}
72+
```
73+
74+
### DON'T:
75+
- Use typed catches when testing throwing expressions
76+
- Delete and recreate test files when debugging
77+
- Add boilerplate comments like "// Given", "// When", "// Then"
78+
79+
## Comments
80+
81+
- Use comments ONLY to explain non-obvious side effects or complex reasoning
82+
- Keep comments minimal and purposeful
83+
- Focus on WHY something is done, not WHAT is being done

dev.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,29 +30,29 @@ check:
3030
commands:
3131
lint:
3232
aliases: [style]
33-
desc: Check Format & Lint issues
33+
desc: Check format and lint issues across all Swift files using SwiftLint and SwiftFormat
3434
run: scripts/lint
3535
fix:
36-
desc: Autofix Format & Lint issues
36+
desc: Automatically fix format and lint issues where possible
3737
run: scripts/lint fix
3838
build:
3939
subcommands:
4040
packages:
41-
desc: Build the Package
41+
desc: Build both ShopifyCheckoutSheetKit and ShopifyAcceleratedCheckouts packages
4242
run: |
4343
./scripts/xcode_run build ShopifyCheckoutSheetKit
4444
./scripts/xcode_run build ShopifyAcceleratedCheckouts
4545
samples:
46-
desc: Build the Samples
46+
desc: Build all sample applications to verify integration
4747
run: ./scripts/build_samples
4848
test:
4949
subcommands:
5050
packages:
51-
desc: Test the Packages
51+
desc: Run all unit and integration tests for the packages
5252
run: |
5353
./scripts/xcode_run test ShopifyCheckoutSheetKit-Package
5454
samples:
55-
desc: Test the Samples
55+
desc: Run tests for sample applications
5656
run: ./scripts/test_samples
5757

5858
apollo:
@@ -68,7 +68,7 @@ commands:
6868
rover graph introspect https://$DOMAIN/api/$API_VERSION/graphql --header="X-Shopify-Storefront-Access-Token: $TOKEN" --output schema.$API_VERSION.graphqls
6969
7070
codegen:
71-
desc: Generate Apollo Client
71+
desc: Generate Apollo Client models and request functions for sample app
7272
run: |
7373
cd ./Samples/ShopifyAcceleratedCheckoutsApp/
7474
./apollo-ios-cli generate

0 commit comments

Comments
 (0)