diff --git a/Feels.xcodeproj/project.pbxproj b/Feels.xcodeproj/project.pbxproj index e7dde9b..b3c0196 100644 --- a/Feels.xcodeproj/project.pbxproj +++ b/Feels.xcodeproj/project.pbxproj @@ -64,6 +64,7 @@ C3D4E500000000E1F2A3B4C5 /* OnboardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3D4E5F6A7B8C9D0E1F2A3B4 /* OnboardingScreen.swift */; }; C5D6E7F800000000E3F4A5B6 /* AppThemeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D6E7F8A9B0C1D2E3F4A5B6 /* AppThemeTests.swift */; }; C9D0E1F200000000E7F8A9B0 /* SettingsActionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9D0E1F2A3B4C5D6E7F8A9B0 /* SettingsActionTests.swift */; }; + CB98BF0846E572188E32E945 /* YearShareTemplateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA522957654485ACBB400DD8 /* YearShareTemplateTests.swift */; }; CC33330033333300CCCCCCCC /* MoodLoggingWithDataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC33333333333333CCCCCCCC /* MoodLoggingWithDataTests.swift */; }; CFB41ED5D294B8997DB694E2 /* TrialExpirationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35AF32CC88B36CDFCB338F2C /* TrialExpirationTests.swift */; }; D0E1F2A300000000F8A9B0C1 /* CustomizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E1F2A3B4C5D6E7F8A9B0C1 /* CustomizationTests.swift */; }; @@ -71,6 +72,7 @@ D4E5F6A700000000F2A3B4C5 /* MoodReplacementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4E5F6A7B8C9D0E1F2A3B4C5 /* MoodReplacementTests.swift */; }; D6E7F8A900000000F4A5B6C7 /* IconPackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E7F8A9B0C1D2E3F4A5B6C7 /* IconPackTests.swift */; }; DD44440044444400DDDDDDDD /* EntryDetailTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD44444444444444DDDDDDDD /* EntryDetailTests.swift */; }; + DEC563826E54A3679583D3DF /* MonthShareTemplateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 552B392439D55578D7D03BC9 /* MonthShareTemplateTests.swift */; }; E0579E66FFBBF124AC625ACD /* WaitHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5354C23DD5FC67C1C97482F2 /* WaitHelpers.swift */; }; E1F2A3B400000000A9B0C1D2 /* OnboardingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F2A3B4C5D6E7F8A9B0C1D2 /* OnboardingTests.swift */; }; E3482DB0421C12E11517BDC8 /* TrialBannerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21CD463209E0909393545D62 /* TrialBannerTests.swift */; }; @@ -171,6 +173,7 @@ 469470483072085BE9E04E12 /* NoteEditTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteEditTests.swift; sourceTree = ""; }; 5354C23DD5FC67C1C97482F2 /* WaitHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitHelpers.swift; sourceTree = ""; }; 542B1A71F9990806CD88B285 /* YearViewCollapseTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = YearViewCollapseTests.swift; sourceTree = ""; }; + 552B392439D55578D7D03BC9 /* MonthShareTemplateTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MonthShareTemplateTests.swift; sourceTree = ""; }; 5566271983AEDF1D33C34FE6 /* DataControllerCRUDTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DataControllerCRUDTests.swift; sourceTree = ""; }; 7E35564DEA72EB6F8447CDAA /* EntryDetailScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryDetailScreen.swift; sourceTree = ""; }; 8114D2CE12EC5392371BB415 /* DarkModeStylesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarkModeStylesTests.swift; sourceTree = ""; }; @@ -184,6 +187,7 @@ A84D4CB70B693A6CDA212035 /* PersonalityPackTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PersonalityPackTests.swift; sourceTree = ""; }; A9B0C1D2E3F4A5B6C7D8E9FA /* DayViewGroupingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DayViewGroupingTests.swift; sourceTree = ""; }; AA11111111111111AAAAAAAA /* AppLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLaunchTests.swift; sourceTree = ""; }; + AA522957654485ACBB400DD8 /* YearShareTemplateTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = YearShareTemplateTests.swift; sourceTree = ""; }; B0C1D2E3F4A5B6C7D8E9FA0B /* AllDayViewStylesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllDayViewStylesTests.swift; sourceTree = ""; }; B2C3D4E5F6A7B8C9D0E1F2A3 /* CustomizeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomizeScreen.swift; sourceTree = ""; }; B4C5D6E7F8A9B0C1D2E3F4A5 /* PaywallGateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallGateTests.swift; sourceTree = ""; }; @@ -469,6 +473,8 @@ 8C5BA5AC63C8CC7D72D0D80F /* InsightsCollapseTests.swift */, 2FCEB60831D3AC7F1164BCF9 /* InsightsPullToRefreshTests.swift */, EEFCBB5FD6C7ACF4C7FC93F1 /* ShareNoDataTests.swift */, + AA522957654485ACBB400DD8 /* YearShareTemplateTests.swift */, + 552B392439D55578D7D03BC9 /* MonthShareTemplateTests.swift */, ); path = "Tests iOS"; sourceTree = ""; @@ -887,6 +893,8 @@ 9E3935A182AFFC51879BF014 /* InsightsCollapseTests.swift in Sources */, 809786A73B85C3E9817B2874 /* InsightsPullToRefreshTests.swift in Sources */, 3CEA4027122C070775D4B626 /* ShareNoDataTests.swift in Sources */, + CB98BF0846E572188E32E945 /* YearShareTemplateTests.swift in Sources */, + DEC563826E54A3679583D3DF /* MonthShareTemplateTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tests iOS/MonthShareTemplateTests.swift b/Tests iOS/MonthShareTemplateTests.swift new file mode 100644 index 0000000..61d47d5 --- /dev/null +++ b/Tests iOS/MonthShareTemplateTests.swift @@ -0,0 +1,88 @@ +// +// MonthShareTemplateTests.swift +// Tests iOS +// +// TC-116: This Month - Clean Calendar sharing template renders. +// TC-117: This Month - Stacked Bars sharing template renders. +// + +import XCTest + +final class MonthShareTemplateTests: BaseUITestCase { + override var seedFixture: String? { "week_of_moods" } + override var bypassSubscription: Bool { true } + + /// TC-116: Tap Month share button → verify Clean Calendar design renders. + func testMonthShare_CleanCalendarTemplate_Renders() { + let tabBar = TabBarScreen(app: app) + tabBar.tapMonth() + + // Wait for month view to load + _ = app.waitForExistence(timeout: 3) + + // Find the month share button + let shareButton = app.element(UITestID.Month.shareButton) + XCTAssertTrue( + shareButton.waitForExistence(timeout: 8), + "Month share button should exist" + ) + + shareButton.tapWhenReady() + + // Verify the SharingStylePickerView sheet appears + let exitButton = app.buttons["Exit"].firstMatch + XCTAssertTrue( + exitButton.waitForExistence(timeout: 5), + "Sharing picker Exit button should appear" + ) + + // First design should be "Clean Calendar" + let cleanCalendarLabel = app.staticTexts["Clean Calendar"].firstMatch + XCTAssertTrue( + cleanCalendarLabel.waitForExistence(timeout: 5), + "Clean Calendar design label should be visible" + ) + + captureScreenshot(name: "month_share_clean_calendar") + + // Close the picker + exitButton.tap() + } + + /// TC-117: Swipe to second design → verify Stacked Bars design renders. + func testMonthShare_StackedBarsTemplate_Renders() { + let tabBar = TabBarScreen(app: app) + tabBar.tapMonth() + + _ = app.waitForExistence(timeout: 3) + + let shareButton = app.element(UITestID.Month.shareButton) + XCTAssertTrue( + shareButton.waitForExistence(timeout: 8), + "Month share button should exist" + ) + + shareButton.tapWhenReady() + + let exitButton = app.buttons["Exit"].firstMatch + XCTAssertTrue( + exitButton.waitForExistence(timeout: 5), + "Sharing picker Exit button should appear" + ) + + // Swipe left to get to the "Stacked Bars" design + app.swipeLeft() + _ = app.waitForExistence(timeout: 1) + + let stackedBarsLabel = app.staticTexts["Stacked Bars"].firstMatch + XCTAssertTrue( + stackedBarsLabel.waitForExistence(timeout: 5), + "Stacked Bars design label should be visible after swiping" + ) + + captureScreenshot(name: "month_share_stacked_bars") + + // Close the picker + exitButton.tap() + } +} diff --git a/Tests iOS/YearShareTemplateTests.swift b/Tests iOS/YearShareTemplateTests.swift new file mode 100644 index 0000000..d9bf73e --- /dev/null +++ b/Tests iOS/YearShareTemplateTests.swift @@ -0,0 +1,85 @@ +// +// YearShareTemplateTests.swift +// Tests iOS +// +// TC-111: All Time Moods - Gradient sharing template renders. +// TC-112: All Time Moods - Color Block sharing template renders. +// + +import XCTest + +final class YearShareTemplateTests: BaseUITestCase { + override var seedFixture: String? { "week_of_moods" } + override var bypassSubscription: Bool { true } + + /// TC-111: Tap Year share button → verify Gradient design renders in SharingStylePickerView. + func testYearShare_GradientTemplate_Renders() { + let tabBar = TabBarScreen(app: app) + tabBar.tapYear() + + // Wait for year view to load and find the share button + let shareButton = app.element(UITestID.Year.shareButton) + XCTAssertTrue( + shareButton.waitForExistence(timeout: 8), + "Year share button should exist" + ) + + shareButton.tapWhenReady() + + // Verify the SharingStylePickerView sheet appears + let exitButton = app.buttons["Exit"].firstMatch + XCTAssertTrue( + exitButton.waitForExistence(timeout: 5), + "Sharing picker Exit button should appear" + ) + + // Verify the title "All Time Moods" appears (YearView sends "All Time Moods") + // Note: YearView creates SharePickerData with title based on year number, + // but the first design is "Gradient" + let gradientLabel = app.staticTexts["Gradient"].firstMatch + XCTAssertTrue( + gradientLabel.waitForExistence(timeout: 5), + "Gradient design label should be visible" + ) + + captureScreenshot(name: "year_share_gradient") + + // Close the picker + exitButton.tap() + } + + /// TC-112: Swipe to second design → verify Color Block design renders. + func testYearShare_ColorBlockTemplate_Renders() { + let tabBar = TabBarScreen(app: app) + tabBar.tapYear() + + let shareButton = app.element(UITestID.Year.shareButton) + XCTAssertTrue( + shareButton.waitForExistence(timeout: 8), + "Year share button should exist" + ) + + shareButton.tapWhenReady() + + let exitButton = app.buttons["Exit"].firstMatch + XCTAssertTrue( + exitButton.waitForExistence(timeout: 5), + "Sharing picker Exit button should appear" + ) + + // Swipe left to get to the "Color Block" design (second page in TabView pager) + app.swipeLeft() + _ = app.waitForExistence(timeout: 1) + + let colorBlockLabel = app.staticTexts["Color Block"].firstMatch + XCTAssertTrue( + colorBlockLabel.waitForExistence(timeout: 5), + "Color Block design label should be visible after swiping" + ) + + captureScreenshot(name: "year_share_color_block") + + // Close the picker + exitButton.tap() + } +} diff --git a/docs/Feels_QA_Test_Plan.xlsx b/docs/Feels_QA_Test_Plan.xlsx index c22f4fb..003a1a0 100644 Binary files a/docs/Feels_QA_Test_Plan.xlsx and b/docs/Feels_QA_Test_Plan.xlsx differ