App-side changes:
- Added "Get Started" / "Continue" next buttons to all onboarding pages
(Welcome, Day, Time, Style) with onboarding_next_button accessibility ID
- Added onNext callback plumbing from OnboardingMain to each page
- OnboardingMain now uses TabView(selection:) for programmatic page navigation
- Added .accessibilityElement(children: .contain) to all onboarding pages
to fix iOS 26 paged TabView not exposing child elements
- Added settings_segmented_picker accessibility ID to Settings Picker
- Reduced padding on onboarding pages to keep buttons in visible area
Test-side changes:
- OnboardingScreen: replaced unreliable swipeToNext() with tapNext()
that taps the accessibility-identified next button
- OnboardingScreen: multi-strategy skip button detection for subscription page
- SettingsScreen: scoped segment tap to picker element to avoid tab bar collision
- CustomizeScreen: simplified horizontal scroll to plain app.swipeLeft()
- OnboardingVotingTests: uses tapNext() to advance to Day page
Passing: OnboardingTests.CompleteFlow, OnboardingVotingTests
Remaining: OnboardingTests.DoesNotRepeat (session state issue),
Settings scroll (deep elements), Customize horizontal pickers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Added month_grid accessibility ID to MonthView ScrollView
- Added year_heatmap accessibility ID to YearView ScrollView
- Fixed DayScreen.assertVisible() to accept entry rows OR mood header
- Fixed DataPersistenceTests for in-memory storage (fixture re-seeds)
- Fixed AppLaunchTests to use week_of_moods fixture (empty has no grid)
- Fixed SettingsScreen segmented control tap with multi-strategy fallback
- Improved settings scroll with coordinate-based swipe for deep elements
- OnboardingScreen swipeToNext uses slow velocity for paged TabView
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrote 60+ test files to follow honeydue-style test guidelines:
- defaultTimeout=2s, navigationTimeout=5s — fail fast, no long waits
- No coordinate taps (except onboarding paged TabView swipes)
- No sleep(), no retry loops
- No guard...else { return } silent passes — XCTFail everywhere
- All elements by accessibility ID via UITestID constants
- Screen objects for all navigation/actions/assertions
- One logical assertion per test method
Added missing accessibility identifiers to app views:
- MonthView.swift: added AccessibilityID.MonthView.grid to ScrollView
- YearView.swift: added AccessibilityID.YearView.heatmap to ScrollView
Framework rewrites:
- BaseUITestCase: added session ID, localeArguments, extraLaunchArguments
- WaitHelpers: waitForExistenceOrFail, waitUntilHittableOrFail,
waitForNonExistence, scrollIntoView, forceTap
- All 7 screen objects rewritten with fail-fast semantics
- TEST_RULES.md added with non-negotiable rules
Known remaining issues:
- OnboardingTests: paged TabView swipes unreliable on iOS 26 simulator
- SettingsLegalLinksTests: EULA/Privacy buttons too deep in DEBUG scroll
- Customization horizontal picker scrolling needs further tuning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The new reflection section pushed the delete button below the fold
in the entry detail sheet, causing the tap to miss.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- AppLaunchTests/StabilityTests: Increase assertTabSelected timeout to
8s for iOS 26 Liquid Glass delayed isSelected state updates
- DeepLinkTests: Detect SubscriptionStoreView container instead of text
labels, since Apple's native view shows "Subscription Unavailable" in
test storefront
- SettingsActionTests: Check for empty state after clearing data, bump
Settings header timeout to 8s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace removePersistentDomain with key-by-key removal in resetAppState
(removePersistentDomain is unreliable on app group UserDefaults suites)
- Add explicit cache clearing in IAPManager.resetForTesting() to prevent
stale cachedSubscriptionExpiration from restoring .subscribed state
- Use descendants(matching: .any) for upgrade_banner and subscribe_button
queries (VStack may not match otherElements in SwiftUI)
- Add multiple swipe attempts for icon pack horizontal scroll
- Use coordinate-based drag for onboarding paged TabView advancement
- Add longer wait for Day view refresh after theme change
- Add multiple scroll attempts to find clear data button in Settings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- resetAppState: use correct suite name to clear group defaults (fixes stale subscription state)
- Reorder configureIfNeeded: set expireTrial before IAPManager init
- Add browse_themes_button identifier to CustomizeView Browse Themes button
- Add mood_button_* identifiers to Entry Detail mood grid in NoteEditorView
- Use coordinate-based tap throughout all test screens (iOS 26 Liquid Glass hittability)
- Fix HeaderMoodLogging date format: M/d/yyyy → yyyy/MM/dd to match entry_row identifiers
- AppLaunchTests: wait for isSelected state with NSPredicate instead of immediate check
- OnboardingTests: add waits between swipes and retry logic for skip button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
App fixes:
- Remove empty_state identifier from EmptyHomeView VStack (was overriding mood_header)
- Fix resetAppState to set needsOnboarding=true (fresh state) instead of false
- Set bypassSubscription explicitly based on launch arg presence (was defaulting to true in DEBUG)
Test fixes:
- TabBarScreen: use coordinate tap to avoid iOS 26 Liquid Glass hittability issues
- SettingsScreen: use coordinate tap for segments, handle Settings label ambiguity with tab bar
- EntryDetailScreen: use mood_button_ identifiers instead of label matching (was matching entry rows)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The screens/ gitignore rule was matching Tests iOS/Screens/ on
case-insensitive macOS. Anchored to /screens/ (repo root only) so
the 7 UI test page object files are no longer ignored.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>