Verify native event forms and record release review
Co-Authored-By: Codex <codex~paul@keymail.dev>
5 files changed,
+67
−0
internal/calendar/native_test.go+10 −0native/README.md+8 −0native/REVIEW.md+11 −0native/ios/UITests/NativeUITests.swift+20 −0native/ios/project.yml+18 −0
diff --git a/internal/calendar/native_test.go b/internal/calendar/native_test.go| index d116f35..0c847d6 100644 |
| --- a/internal/calendar/native_test.go |
| +++ b/internal/calendar/native_test.go |
| @@ -100,6 +100,16 @@ func TestNativeCalendarRoundTrip(t *testing.T) { |
| t.Fatal(err) |
| } |
| defer os.Remove(path) |
| + |
| + if os.Getenv("NATIVE_REVIEW_UI_TESTS") != "" { |
| + command := exec.CommandContext(t.Context(), "xcodebuild", "-project", "native/ios/CalendarPhone.xcodeproj", "-scheme", "CalendarReviewPhone", "-destination", "platform=iOS Simulator,id="+simulator, "-derivedDataPath", "native/build/ios", "CODE_SIGNING_ALLOWED=NO", "test") |
| + command.Dir = "../.." |
| + output, err := command.CombinedOutput() |
| + _ = os.WriteFile(filepath.Join(os.TempDir(), "calendar-native-ui-tests.log"), output, 0600) |
| + if err != nil { |
| + t.Fatal("Native UI tests failed; see temporary xcodebuild log", err) |
| + } |
| + } |
| run("launch", simulator, bundle) |
| time.Sleep(3 * time.Second) |
| run("io", simulator, "screenshot", os.Getenv("NATIVE_REVIEW_OUTPUT")) |
diff --git a/native/README.md b/native/README.md| index 6468401..7954173 100644 |
| --- a/native/README.md |
| +++ b/native/README.md |
| @@ -31,3 +31,11 @@ maximum 62-day half-open range, and POST `/api/native/events[/{id}]`. Existing |
| person, calendar-grant and event-store checks remain authoritative. Recurrence |
| expansion stays on the server. All-day ends are exclusive dates. The UI uses the |
| person's saved week start and time zone, not the device's implicit formatting zone. |
| + |
| +For XCTest interaction checks against the isolated authenticated fixture, set |
| +`NATIVE_REVIEW_SIMULATOR=<UDID> NATIVE_REVIEW_UI_TESTS=1` with a writable |
| +`NATIVE_REVIEW_OUTPUT` PNG path when running the native Go fixture test. First |
| +build/install the separate ReviewPhone target. The UI tests create and inspect |
| +fixture events and never connect to a real account. Xcode result bundles |
| +are under `native/build/ios/Logs/Test`. Review credentials enter only the isolated |
| +review app's Documents directory and are removed when the fixture exits. |
diff --git a/native/REVIEW.md b/native/REVIEW.md| index ab3772f..75df1ec 100644 |
| --- a/native/REVIEW.md |
| +++ b/native/REVIEW.md |
| @@ -25,3 +25,14 @@ carries status and labels it explicitly; regression tests pin both states. |
| A confirmed event with a failed reminder now returns its saved id and a warning, |
| so the native editor closes successfully instead of inviting a duplicate retry. |
| A database-trigger failure test verifies that persisted event and warning. |
| + |
| +Final merge `d3fedf1` reviewed against both parents (58863aa and 9c44bc1) by |
| +`/root/canary_release_review`, dispatched as `gpt-6-astra` with high reasoning. |
| +Runtime model identity was not independently verified. Code and deployed canary |
| +review approved, with no remaining findings. Direct `/api/version` and the router |
| +reported the exact reviewed version. Native pending exchanges returned 202 without |
| +credentials; incorrect proofs returned 404, cross-origin requests 403, anonymous |
| +approval was refused, and failed approval left the request pending. No email or |
| +user-data mutation was performed. Existing credits access and branding remained |
| +intact. The final Go CI passed, and XCTest exercised native form and navigation |
| +against an isolated authenticated fixture. |
diff --git a/native/ios/UITests/NativeUITests.swift b/native/ios/UITests/NativeUITests.swift| new file mode 100644 |
| index 0000000..8c13f6a |
| --- /dev/null |
| +++ b/native/ios/UITests/NativeUITests.swift |
| @@ -0,0 +1,20 @@ |
| +import XCTest |
| +@MainActor final class NativeUITests: XCTestCase { |
| + func testNativeFormAndNavigation() { |
| + let app=XCUIApplication();app.launch() |
| + XCTAssertTrue(app.buttons["New event"].waitForExistence(timeout: 10)) |
| + |
| + app.buttons["New event"].tap() |
| + let title=app.textFields["eventTitle"] |
| + XCTAssertTrue(title.waitForExistence(timeout: 5)); title.tap(); title.typeText("Native UI event") |
| + app.buttons["Save"].tap() |
| + XCTAssertTrue(app.staticTexts["Native UI event"].firstMatch.waitForExistence(timeout: 10)) |
| + app.staticTexts["Native UI event"].firstMatch.tap() |
| + XCTAssertTrue(app.buttons["Edit event"].waitForExistence(timeout: 5)) |
| + app.buttons["Edit event"].tap() |
| + XCTAssertTrue(app.textFields["eventTitle"].waitForExistence(timeout: 5)) |
| + app.buttons["Cancel"].tap() |
| + |
| + let capture=XCTAttachment(screenshot: app.screenshot());capture.lifetime = .keepAlways;add(capture) |
| + } |
| +} |
diff --git a/native/ios/project.yml b/native/ios/project.yml| index 35b76cd..f052032 100644 |
| --- a/native/ios/project.yml |
| +++ b/native/ios/project.yml |
| @@ -54,3 +54,21 @@ targets: |
| TARGETED_DEVICE_FAMILY: '1,2' |
| GENERATE_INFOPLIST_FILE: YES |
| INFOPLIST_KEY_UILaunchScreen_Generation: YES |
| + |
| + CalendarPhoneUITests: |
| + type: bundle.ui-testing |
| + platform: iOS |
| + sources: [UITests] |
| + dependencies: |
| + - target: CalendarReviewPhone |
| + settings: |
| + base: |
| + GENERATE_INFOPLIST_FILE: YES |
| + TEST_TARGET_NAME: CalendarReviewPhone |
| +schemes: |
| + CalendarReviewPhone: |
| + build: |
| + targets: |
| + CalendarReviewPhone: all |
| + test: |
| + targets: [CalendarPhoneUITests] |