Complete rename across all bundle IDs, App Groups, CloudKit containers, StoreKit product IDs, data store filenames, URL schemes, logger subsystems, Swift identifiers, user-facing strings (7 languages), file names, directory names, Xcode project, schemes, assets, and documentation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
158 lines
6.5 KiB
Swift
158 lines
6.5 KiB
Swift
//
|
|
// VoteLogicsTests.swift
|
|
// ReflectTests
|
|
//
|
|
// Tests for ShowBasedOnVoteLogics vote status and timing.
|
|
//
|
|
|
|
import XCTest
|
|
import SwiftData
|
|
@testable import Reflect
|
|
|
|
@MainActor
|
|
final class VoteLogicsTests: XCTestCase {
|
|
|
|
// MARK: - Phase 7: passedTodaysVotingUnlock Tests
|
|
|
|
func test_passedVotingUnlock_beforeTime() {
|
|
// Voting unlock set to 6:00 PM, current time is 2:00 PM
|
|
let voteDate = makeDateWithTime(hour: 18, minute: 0)
|
|
let now = makeDateWithTime(hour: 14, minute: 0)
|
|
|
|
let result = ShowBasedOnVoteLogics.passedTodaysVotingUnlock(voteDate: voteDate, now: now)
|
|
XCTAssertFalse(result, "Should not have passed unlock when current time is before vote time")
|
|
}
|
|
|
|
func test_passedVotingUnlock_afterTime() {
|
|
// Voting unlock set to 6:00 PM, current time is 8:00 PM
|
|
let voteDate = makeDateWithTime(hour: 18, minute: 0)
|
|
let now = makeDateWithTime(hour: 20, minute: 0)
|
|
|
|
let result = ShowBasedOnVoteLogics.passedTodaysVotingUnlock(voteDate: voteDate, now: now)
|
|
XCTAssertTrue(result, "Should have passed unlock when current time is after vote time")
|
|
}
|
|
|
|
func test_passedVotingUnlock_exactTime() {
|
|
// Voting unlock set to 6:00 PM, current time is exactly 6:00 PM
|
|
let voteDate = makeDateWithTime(hour: 18, minute: 0)
|
|
let now = makeDateWithTime(hour: 18, minute: 0)
|
|
|
|
let result = ShowBasedOnVoteLogics.passedTodaysVotingUnlock(voteDate: voteDate, now: now)
|
|
XCTAssertTrue(result, "Should have passed unlock at exact vote time (uses >=)")
|
|
}
|
|
|
|
// MARK: - Phase 7: getCurrentVotingDate Tests
|
|
|
|
func test_votingDate_today_beforeTime() {
|
|
let onboarding = OnboardingData()
|
|
onboarding.inputDay = .Today
|
|
onboarding.date = makeDateWithTime(hour: 18, minute: 0)
|
|
|
|
let now = makeDateWithTime(hour: 14, minute: 0) // before 6pm
|
|
let result = ShowBasedOnVoteLogics.getCurrentVotingDate(onboardingData: onboarding, now: now)
|
|
|
|
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: now)!
|
|
XCTAssertTrue(Calendar.current.isDate(result, inSameDayAs: yesterday),
|
|
"Today mode, before unlock: should return yesterday")
|
|
}
|
|
|
|
func test_votingDate_today_afterTime() {
|
|
let onboarding = OnboardingData()
|
|
onboarding.inputDay = .Today
|
|
onboarding.date = makeDateWithTime(hour: 18, minute: 0)
|
|
|
|
let now = makeDateWithTime(hour: 20, minute: 0) // after 6pm
|
|
let result = ShowBasedOnVoteLogics.getCurrentVotingDate(onboardingData: onboarding, now: now)
|
|
|
|
XCTAssertTrue(Calendar.current.isDate(result, inSameDayAs: now),
|
|
"Today mode, after unlock: should return today")
|
|
}
|
|
|
|
func test_votingDate_previous_beforeTime() {
|
|
let onboarding = OnboardingData()
|
|
onboarding.inputDay = .Previous
|
|
onboarding.date = makeDateWithTime(hour: 18, minute: 0)
|
|
|
|
let now = makeDateWithTime(hour: 14, minute: 0) // before 6pm
|
|
let result = ShowBasedOnVoteLogics.getCurrentVotingDate(onboardingData: onboarding, now: now)
|
|
|
|
let twoDaysAgo = Calendar.current.date(byAdding: .day, value: -2, to: now)!
|
|
XCTAssertTrue(Calendar.current.isDate(result, inSameDayAs: twoDaysAgo),
|
|
"Previous mode, before unlock: should return 2 days ago")
|
|
}
|
|
|
|
func test_votingDate_previous_afterTime() {
|
|
let onboarding = OnboardingData()
|
|
onboarding.inputDay = .Previous
|
|
onboarding.date = makeDateWithTime(hour: 18, minute: 0)
|
|
|
|
let now = makeDateWithTime(hour: 20, minute: 0) // after 6pm
|
|
let result = ShowBasedOnVoteLogics.getCurrentVotingDate(onboardingData: onboarding, now: now)
|
|
|
|
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: now)!
|
|
XCTAssertTrue(Calendar.current.isDate(result, inSameDayAs: yesterday),
|
|
"Previous mode, after unlock: should return yesterday")
|
|
}
|
|
|
|
// MARK: - Phase 7: Vote Needed Tests (exercising the same logic as isMissingCurrentVote)
|
|
// Note: isMissingCurrentVote uses DataController.shared (singleton) internally,
|
|
// so we test the equivalent logic using a testable DataController instance.
|
|
|
|
func test_voteNeeded_noEntry() {
|
|
let sut = makeTestDataController()
|
|
let onboarding = OnboardingData()
|
|
onboarding.inputDay = .Today
|
|
onboarding.date = makeDateWithTime(hour: 0, minute: 1)
|
|
|
|
let votingDate = ShowBasedOnVoteLogics.getCurrentVotingDate(onboardingData: onboarding)
|
|
let entry = sut.getEntry(byDate: votingDate.startOfDay)
|
|
let isMissing = entry == nil || entry?.mood == .missing
|
|
XCTAssertTrue(isMissing, "Should need a vote when no entry exists")
|
|
}
|
|
|
|
func test_voteNeeded_validEntry() {
|
|
let sut = makeTestDataController()
|
|
let onboarding = OnboardingData()
|
|
onboarding.inputDay = .Today
|
|
onboarding.date = makeDateWithTime(hour: 0, minute: 1)
|
|
|
|
let votingDate = ShowBasedOnVoteLogics.getCurrentVotingDate(onboardingData: onboarding)
|
|
sut.add(mood: .great, forDate: votingDate, entryType: .listView)
|
|
|
|
let entry = sut.getEntry(byDate: votingDate.startOfDay)
|
|
let isMissing = entry == nil || entry?.mood == .missing
|
|
XCTAssertFalse(isMissing, "Should not need a vote when valid entry exists")
|
|
}
|
|
|
|
func test_voteNeeded_missingEntry() {
|
|
let sut = makeTestDataController()
|
|
let onboarding = OnboardingData()
|
|
onboarding.inputDay = .Today
|
|
onboarding.date = makeDateWithTime(hour: 0, minute: 1)
|
|
|
|
let votingDate = ShowBasedOnVoteLogics.getCurrentVotingDate(onboardingData: onboarding)
|
|
sut.add(mood: .missing, forDate: votingDate, entryType: .filledInMissing)
|
|
|
|
let entry = sut.getEntry(byDate: votingDate.startOfDay)
|
|
let isMissing = entry == nil || entry?.mood == .missing
|
|
XCTAssertTrue(isMissing, "Should need a vote when entry is .missing")
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
private func makeTestDataController() -> DataController {
|
|
let schema = Schema([MoodEntryModel.self])
|
|
let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
|
|
return DataController(container: try! ModelContainer(for: schema, configurations: [config]))
|
|
}
|
|
|
|
private func makeDateWithTime(hour: Int, minute: Int) -> Date {
|
|
let calendar = Calendar.current
|
|
var components = calendar.dateComponents([.year, .month, .day], from: Date())
|
|
components.hour = hour
|
|
components.minute = minute
|
|
components.second = 0
|
|
return calendar.date(from: components)!
|
|
}
|
|
}
|