Files
Reflect/Tests iOS/CustomizationTests.swift
Trey t 224341fd98 Fix remaining 17 UI test failures: group defaults, identifiers, hittability, date format
- 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>
2026-02-17 16:46:18 -06:00

105 lines
3.8 KiB
Swift

//
// CustomizationTests.swift
// Tests iOS
//
// Customization tests: theme modes, voting layouts, day view styles.
//
import XCTest
final class CustomizationTests: BaseUITestCase {
override var seedFixture: String? { "single_mood" }
override var bypassSubscription: Bool { true }
/// TC-071: Switch between all 4 theme modes without crashing.
func testThemeModes_AllSelectable() {
let tabBar = TabBarScreen(app: app)
let settingsScreen = tabBar.tapSettings()
settingsScreen.assertVisible()
// Should already be on Customize sub-tab
// Theme buttons are: System, iFeel, Dark, Light
let themeNames = ["System", "iFeel", "Dark", "Light"]
for themeName in themeNames {
let button = app.buttons["customize_theme_\(themeName.lowercased())"]
if button.waitForExistence(timeout: 3) {
button.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
}
}
captureScreenshot(name: "theme_modes_cycled")
}
/// TC-073: Switch between all 6 voting layouts without crashing.
func testVotingLayouts_AllSelectable() {
let tabBar = TabBarScreen(app: app)
let settingsScreen = tabBar.tapSettings()
settingsScreen.assertVisible()
// Voting layout names (from VotingLayoutStyle enum)
let layouts = ["Horizontal", "Cards", "Stacked", "Aura", "Orbit", "Neon"]
for layout in layouts {
let button = app.buttons["customize_voting_\(layout.lowercased())"]
if button.waitForExistence(timeout: 2) {
button.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
} else {
// Scroll right to find it
app.swipeLeft()
if button.waitForExistence(timeout: 2) {
button.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
}
}
}
captureScreenshot(name: "voting_layouts_cycled")
// Navigate to Day tab to verify the voting layout renders
tabBar.tapDay()
let moodHeader = app.otherElements["mood_header"]
// Header may or may not be visible depending on whether today has been voted
// Either way, no crash is the main assertion
captureScreenshot(name: "day_view_after_layout_change")
}
/// TC-074: Switch between several day view styles without crashing.
func testDayViewStyles_MultipleSelectable() {
let tabBar = TabBarScreen(app: app)
let settingsScreen = tabBar.tapSettings()
settingsScreen.assertVisible()
// Test a representative sample of day view styles (testing all 20+ would be slow)
let styles = ["Classic", "Minimal", "Compact", "Bubble", "Grid", "Neon"]
for style in styles {
let button = app.buttons["customize_daystyle_\(style.lowercased())"]
if button.waitForExistence(timeout: 2) {
button.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
} else {
// Scroll to find it
app.swipeLeft()
if button.waitForExistence(timeout: 2) {
button.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
}
}
}
captureScreenshot(name: "day_styles_cycled")
// Navigate to Day tab to verify the style renders with data
tabBar.tapDay()
let entryRow = app.descendants(matching: .any)
.matching(NSPredicate(format: "identifier BEGINSWITH %@", "entry_row_"))
.firstMatch
XCTAssertTrue(
entryRow.waitForExistence(timeout: 5),
"Entry row should be visible with the new style"
)
captureScreenshot(name: "day_view_after_style_change")
}
}