- Add 8 new test files: HeaderMoodLogging (TC-002), DayViewGrouping (TC-019), AllDayViewStyles (TC-021), MonthViewInteraction (TC-030), PaywallGate (TC-032/039/048), AppTheme (TC-070), IconPack (TC-072), PremiumCustomization (TC-075) - Add accessibility IDs for paywall overlays, icon packs, app theme cards, and day view section headers - Add --expire-trial launch argument to UITestMode for paywall gate testing - Update QA test plan spreadsheet with XCUITest names for 14 test cases - Include existing test infrastructure: screen objects, helpers, base class, and 19 previously written test files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
106 lines
3.6 KiB
Swift
106 lines
3.6 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.tap()
|
|
// Brief pause for theme to apply
|
|
}
|
|
}
|
|
|
|
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.tap()
|
|
} else {
|
|
// Scroll right to find it
|
|
app.swipeLeft()
|
|
if button.waitForExistence(timeout: 2) {
|
|
button.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.tap()
|
|
} else {
|
|
// Scroll to find it
|
|
app.swipeLeft()
|
|
if button.waitForExistence(timeout: 2) {
|
|
button.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")
|
|
}
|
|
}
|