Skip to content

Commit 787627c

Browse files
adding test
1 parent 6658c59 commit 787627c

File tree

10 files changed

+304
-181
lines changed

10 files changed

+304
-181
lines changed

Stanford360.xcodeproj/project.pbxproj

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
2FE5DC9C29EDD9EF004B9AB4 /* XCTHealthKit in Frameworks */ = {isa = PBXBuildFile; productRef = 2FE5DC9B29EDD9EF004B9AB4 /* XCTHealthKit */; };
5050
2FE5DCB129EE6107004B9AB4 /* AccountOnboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5DCAC29EE6107004B9AB4 /* AccountOnboarding.swift */; };
5151
2FF53D8D2A8729D600042B76 /* Stanford360Standard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FF53D8C2A8729D600042B76 /* Stanford360Standard.swift */; };
52-
45E038232D503C0F009D07E2 /* HydrationViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45E038222D503BFA009D07E2 /* HydrationViewTests.swift */; };
52+
45E2F1172D82619E0097C339 /* MilestoneTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45E2F1162D8261980097C339 /* MilestoneTests.swift */; };
5353
4D2965D82D7A8084000664B4 /* SpeziLLM in Frameworks */ = {isa = PBXBuildFile; productRef = 4D2965D72D7A8084000664B4 /* SpeziLLM */; };
5454
4D2965DA2D7A8084000664B4 /* SpeziLLMFog in Frameworks */ = {isa = PBXBuildFile; productRef = 4D2965D92D7A8084000664B4 /* SpeziLLMFog */; };
5555
4D2965DC2D7A8084000664B4 /* SpeziLLMLocal in Frameworks */ = {isa = PBXBuildFile; productRef = 4D2965DB2D7A8084000664B4 /* SpeziLLMLocal */; };
@@ -136,7 +136,7 @@
136136
2FE5DC5529EDD811004B9AB4 /* SocialSupportQuestionnaire.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = SocialSupportQuestionnaire.json; sourceTree = "<group>"; };
137137
2FE5DCAC29EE6107004B9AB4 /* AccountOnboarding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountOnboarding.swift; sourceTree = "<group>"; };
138138
2FF53D8C2A8729D600042B76 /* Stanford360Standard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stanford360Standard.swift; sourceTree = "<group>"; };
139-
45E038222D503BFA009D07E2 /* HydrationViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HydrationViewTests.swift; sourceTree = "<group>"; };
139+
45E2F1162D8261980097C339 /* MilestoneTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MilestoneTests.swift; sourceTree = "<group>"; };
140140
4FC5EF032D78162800BFDFFD /* KidsOnboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KidsOnboarding.swift; sourceTree = "<group>"; };
141141
4FCAD0582D5AAD20007324A6 /* ActivityViewUITest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityViewUITest.swift; sourceTree = "<group>"; };
142142
5680DD3D2AB8CD84004E6D4A /* ContributionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContributionsTest.swift; sourceTree = "<group>"; };
@@ -166,6 +166,7 @@
166166

167167
/* Begin PBXFileSystemSynchronizedRootGroup section */
168168
45E2F0FC2D82132B0097C339 /* HydrationTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = HydrationTests; sourceTree = "<group>"; };
169+
45E2F12D2D8291E30097C339 /* HydrationUITests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = HydrationUITests; sourceTree = "<group>"; };
169170
4DB472D62D80459F005E895E /* ProteinTest */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = ProteinTest; sourceTree = "<group>"; };
170171
4F8EA0B92D680A4400A94137 /* Activity */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Activity; sourceTree = "<group>"; };
171172
4FF18DDD2D5FAB5E00E13832 /* ActivityTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = ActivityTests; sourceTree = "<group>"; };
@@ -353,6 +354,7 @@
353354
653A256028338800005D4D48 /* Stanford360Tests */ = {
354355
isa = PBXGroup;
355356
children = (
357+
45E2F1162D8261980097C339 /* MilestoneTests.swift */,
356358
45E2F0FC2D82132B0097C339 /* HydrationTests */,
357359
4DB472D62D80459F005E895E /* ProteinTest */,
358360
4FF18DDD2D5FAB5E00E13832 /* ActivityTests */,
@@ -364,7 +366,7 @@
364366
653A256A28338800005D4D48 /* Stanford360UITests */ = {
365367
isa = PBXGroup;
366368
children = (
367-
45E038222D503BFA009D07E2 /* HydrationViewTests.swift */,
369+
45E2F12D2D8291E30097C339 /* HydrationUITests */,
368370
2F4E237D2989A2FE0013F3D9 /* OnboardingTests.swift */,
369371
653A256B28338800005D4D48 /* SchedulerTests.swift */,
370372
2F4E23862989DB360013F3D9 /* ContactsTests.swift */,
@@ -512,6 +514,9 @@
512514
A9E1D3482C67B0A700CED217 /* PBXTargetDependency */,
513515
653A256928338800005D4D48 /* PBXTargetDependency */,
514516
);
517+
fileSystemSynchronizedGroups = (
518+
45E2F12D2D8291E30097C339 /* HydrationUITests */,
519+
);
515520
name = Stanford360UITests;
516521
packageProductDependencies = (
517522
2FE5DC9829EDD9D9004B9AB4 /* XCTestExtensions */,
@@ -666,6 +671,7 @@
666671
buildActionMask = 2147483647;
667672
files = (
668673
653A256228338800005D4D48 /* Stanford360Tests.swift in Sources */,
674+
45E2F1172D82619E0097C339 /* MilestoneTests.swift in Sources */,
669675
);
670676
runOnlyForDeploymentPostprocessing = 0;
671677
};
@@ -674,7 +680,6 @@
674680
buildActionMask = 2147483647;
675681
files = (
676682
5680DD3E2AB8CD84004E6D4A /* ContributionsTest.swift in Sources */,
677-
45E038232D503C0F009D07E2 /* HydrationViewTests.swift in Sources */,
678683
2F4E23872989DB360013F3D9 /* ContactsTests.swift in Sources */,
679684
2F4E237E2989A2FE0013F3D9 /* OnboardingTests.swift in Sources */,
680685
653A256C28338800005D4D48 /* SchedulerTests.swift in Sources */,

Stanford360/Hydration/View/HydrationAddView.swift

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ struct HydrationAddView: View {
1717
var body: some View {
1818
ZStack {
1919
VStack(spacing: 20) {
20-
// motivationText
21-
2220
PercentageRing(
2321
currentValue: Int(hydrationManager.getTodayTotalOunces()),
2422
maxValue: 60,
@@ -36,20 +34,6 @@ struct HydrationAddView: View {
3634
Text.goalMessage(current: hydrationManager.getTodayTotalOunces(), goal: 60, unit: "oz")
3735
.padding(.top, 10)
3836

39-
// TODO() - make into reusable component to share with activity view // swiftlint:disable:this todo
40-
// HydrationControlPanel()
41-
// .contentShape(Rectangle()) // Ensure the gesture recognizer covers the whole area
42-
// .simultaneousGesture(
43-
// DragGesture(minimumDistance: 5)
44-
// .onChanged { value in
45-
// // Only block if it's more horizontal than vertical
46-
// let isHorizontalDrag = abs(value.translation.width) > abs(value.translation.height)
47-
// if isHorizontalDrag {
48-
// // Do nothing - just preventing the swipe from propagating
49-
// }
50-
// }
51-
// )
52-
5337
Spacer()
5438
}
5539

@@ -58,19 +42,6 @@ struct HydrationAddView: View {
5842
.offset(y: -100)
5943
}
6044
}
61-
62-
/*
63-
private var motivationText: some View {
64-
Text(hydrationManager.triggerMotivation())
65-
.font(.headline)
66-
.foregroundColor(.blue)
67-
.padding()
68-
.background(
69-
RoundedRectangle(cornerRadius: 15)
70-
.fill(Color.blue.opacity(0.1))
71-
)
72-
}
73-
*/
7445
}
7546

7647
#Preview {

Stanford360/Hydration/View/HydrationCardView.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
import SwiftUI
1313

14-
// TODO - align with dashboard cards + add swipe actions // swiftlint:disable:this todo
1514
struct HydrationCardView: View {
1615
let hydrationLog: HydrationLog
1716

@@ -22,7 +21,6 @@ struct HydrationCardView: View {
2221

2322
Spacer()
2423

25-
// Minutes with emphasis
2624
Text("\(Int(hydrationLog.hydrationOunces)) oz")
2725
.font(.title3)
2826
.foregroundStyle(.blue)
@@ -31,6 +29,7 @@ struct HydrationCardView: View {
3129
.background(Color.cardBackground)
3230
.cornerRadius(15)
3331
.shadow(color: Color.black.opacity(0.1), radius: 4, x: 0, y: 4)
32+
.accessibilityIdentifier("hydrationLogEntry")
3433
}
3534
}
3635

Stanford360/Hydration/View/HydrationControlPanel.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ struct HydrationControlPanel: View {
1818
@State var milestoneMessage: String?
1919
@State var isSpecialMilestone: Bool = false
2020
@State var selectedAmount: Double?
21-
@State var streak: Int?
2221

2322
var body: some View {
2423
VStack(spacing: 10) {
@@ -100,7 +99,6 @@ struct HydrationControlPanel: View {
10099
let updatedStreak = hydrationManager.streak
101100

102101
errorMessage = nil
103-
streak = hydrationManager.streak
104102
await scheduler.rescheduleHydrationNotifications()
105103
hydrationManager.milestoneManager.displayMilestoneMessage(
106104
newTotal: hydrationManager.getTodayTotalOunces(),

Stanford360/Hydration/View/HydrationHistoryView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct HydrationHistoryView: View {
2424
Text("No hydration logged")
2525
.foregroundColor(.gray)
2626
.padding()
27+
.accessibilityIdentifier("noHydrationLogs")
2728
}
2829
.listStyle(PlainListStyle())
2930
} else {
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//
2+
// SPDX-FileCopyrightText: 2025 Stanford University
3+
//
4+
// SPDX-License-Identifier: MIT
5+
//
6+
7+
@testable import Stanford360
8+
import XCTest
9+
10+
final class MilestoneManagerTests: XCTestCase {
11+
var milestoneManager: MilestoneManager? // ✅ Correct Optional Syntax
12+
13+
override func setUp() {
14+
super.setUp()
15+
milestoneManager = MilestoneManager()
16+
}
17+
18+
override func tearDown() {
19+
milestoneManager = nil
20+
super.tearDown()
21+
}
22+
23+
@MainActor
24+
func testRegularMilestoneMessage() {
25+
guard let milestoneManager = milestoneManager else {
26+
XCTFail("MilestoneManager is nil in testRegularMilestoneMessage")
27+
return
28+
}
29+
30+
let milestoneData = milestoneManager.checkMilestones(
31+
newTotal: 40,
32+
lastMilestone: 20,
33+
unit: "oz",
34+
streak: 3
35+
)
36+
37+
XCTAssertEqual(milestoneData.message, "Great job! You've reached 40 oz today!")
38+
XCTAssertFalse(milestoneData.isSpecial)
39+
}
40+
41+
@MainActor
42+
func testSpecialMilestoneMessage() {
43+
guard let milestoneManager = milestoneManager else {
44+
XCTFail("MilestoneManager is nil in testSpecialMilestoneMessage")
45+
return
46+
}
47+
48+
let milestoneData = milestoneManager.checkMilestones(
49+
newTotal: 60,
50+
lastMilestone: 40,
51+
unit: "oz",
52+
streak: 5
53+
)
54+
55+
XCTAssertEqual(milestoneData.message, "Amazing! You've reached 60 oz today! 5 days in a row! Keep it going!")
56+
XCTAssertTrue(milestoneData.isSpecial)
57+
}
58+
59+
@MainActor
60+
func testMilestoneMessageDisplay() {
61+
guard let milestoneManager = milestoneManager else {
62+
XCTFail("MilestoneManager is nil in testMilestoneMessageDisplay")
63+
return
64+
}
65+
66+
milestoneManager.displayMilestoneMessage(
67+
newTotal: 60,
68+
lastMilestone: 40,
69+
unit: "oz",
70+
streak: 7
71+
)
72+
73+
XCTAssertNotNil(milestoneManager.milestoneMessage)
74+
XCTAssertTrue(milestoneManager.isSpecialMilestone)
75+
76+
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
77+
XCTAssertNil(milestoneManager.milestoneMessage)
78+
XCTAssertFalse(milestoneManager.isSpecialMilestone)
79+
}
80+
}
81+
82+
@MainActor
83+
func testGetLatestMilestone() {
84+
guard let milestoneManager = milestoneManager else {
85+
XCTFail("MilestoneManager is nil in testGetLatestMilestone")
86+
return
87+
}
88+
89+
XCTAssertEqual(milestoneManager.getLatestMilestone(total: 35), 20)
90+
XCTAssertEqual(milestoneManager.getLatestMilestone(total: 60), 60)
91+
}
92+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//
2+
// This source file is part of the Stanford 360 based on the Stanford Spezi Template Application project
3+
//
4+
// SPDX-FileCopyrightText: 2025 Stanford University
5+
//
6+
// SPDX-License-Identifier: MIT
7+
//
8+
9+
import XCTest
10+
11+
final class HydrationHistoryViewTests: XCTestCase {
12+
@MainActor
13+
override func setUp() async throws {
14+
continueAfterFailure = false
15+
let app = XCUIApplication()
16+
app.launchArguments = ["--skipOnboarding"]
17+
app.launch()
18+
19+
let dontAllowIdentifier = app.buttons["UIA.Health.AuthSheet.CancelButton"]
20+
if dontAllowIdentifier.waitForExistence(timeout: 5) {
21+
dontAllowIdentifier.tap()
22+
}
23+
}
24+
25+
// Test Hydration History Displays Entries
26+
@MainActor
27+
func testHydrationHistoryDisplaysLogs() throws {
28+
let app = XCUIApplication()
29+
30+
XCTAssertTrue(app.wait(for: .runningForeground, timeout: 5))
31+
32+
XCTAssertTrue(app.tabBars["Tab Bar"].buttons["Hydration"].exists)
33+
app.tabBars["Tab Bar"].buttons["Hydration"].tap()
34+
35+
let historyButton = app.segmentedControls.buttons["History"]
36+
XCTAssertTrue(historyButton.waitForExistence(timeout: 2), "History tab should exist")
37+
historyButton.tap()
38+
39+
let addButton = app.buttons["Add"]
40+
addButton.tap()
41+
42+
let logButton = app.buttons["logWaterIntakeButton"]
43+
XCTAssertTrue(app.staticTexts["20 oz"].waitForExistence(timeout: 2), "Preset button for 20 oz should exist")
44+
app.staticTexts["20 oz"].tap()
45+
logButton.tap()
46+
47+
// let historyButton = app.buttons["History"]
48+
historyButton.tap()
49+
50+
let hydrationLogEntry = app.staticTexts["hydrationLogEntry"]
51+
XCTAssertTrue(hydrationLogEntry.waitForExistence(timeout: 2), "Hydration log entry should be displayed if logs exist.")
52+
}
53+
}

0 commit comments

Comments
 (0)