Files
Reflect/ReflectTests/IntegrationTests.swift
Trey t 0442eab1f8 Rebrand entire project from Feels to Reflect
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>
2026-02-26 11:47:16 -06:00

142 lines
4.9 KiB
Swift

//
// IntegrationTests.swift
// ReflectTests
//
// Integration tests verifying full lifecycle pipelines.
//
import XCTest
import SwiftData
@testable import Reflect
@MainActor
final class IntegrationTests: XCTestCase {
var sut: DataController!
override func setUp() {
super.setUp()
let schema = Schema([MoodEntryModel.self])
let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
sut = DataController(container: try! ModelContainer(for: schema, configurations: [config]))
}
override func tearDown() {
sut = nil
super.tearDown()
}
// MARK: - Phase 8: Integration Pipelines
func test_fullCRUD_lifecycle() {
let date = makeDate(2024, 6, 15)
// Create
sut.add(mood: .good, forDate: date, entryType: .listView)
XCTAssertNotNil(sut.getEntry(byDate: date))
// Read
let entry = sut.getEntry(byDate: date)
XCTAssertEqual(entry?.mood, .good)
// Update
let updated = sut.update(entryDate: date, withMood: .great)
XCTAssertTrue(updated)
XCTAssertEqual(sut.getEntry(byDate: date)?.mood, .great)
// Update notes
sut.updateNotes(forDate: date, notes: "Lifecycle test")
XCTAssertEqual(sut.getEntry(byDate: date)?.notes, "Lifecycle test")
// Delete
sut.deleteAllEntries(forDate: date)
XCTAssertNil(sut.getEntry(byDate: date))
}
func test_streak_throughLifecycle() {
let today = Calendar.current.startOfDay(for: Date())
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: today)!
// Add today streak=1
sut.add(mood: .good, forDate: today, entryType: .listView)
XCTAssertEqual(sut.calculateStreak(from: today).streak, 1)
// Add yesterday streak=2
sut.add(mood: .great, forDate: yesterday, entryType: .listView)
XCTAssertEqual(sut.calculateStreak(from: today).streak, 2)
// Update today's mood streak still 2
sut.update(entryDate: today, withMood: .average)
XCTAssertEqual(sut.calculateStreak(from: today).streak, 2)
// Delete today streak=1 (counting from yesterday)
sut.deleteAllEntries(forDate: today)
XCTAssertEqual(sut.calculateStreak(from: today).streak, 1)
}
func test_voteStatus_throughLifecycle() {
let onboarding = OnboardingData()
onboarding.inputDay = .Today
// Set unlock time to 00:01 so we're always "after" unlock
var components = Calendar.current.dateComponents([.year, .month, .day], from: Date())
components.hour = 0
components.minute = 1
onboarding.date = Calendar.current.date(from: components)!
let votingDate = ShowBasedOnVoteLogics.getCurrentVotingDate(onboardingData: onboarding)
// Helper: check vote status using testable DataController
func isVoteNeeded() -> Bool {
let entry = sut.getEntry(byDate: votingDate.startOfDay)
return entry == nil || entry?.mood == .missing
}
// No entry vote needed
XCTAssertTrue(isVoteNeeded())
// Add entry no vote needed
sut.add(mood: .great, forDate: votingDate, entryType: .listView)
XCTAssertFalse(isVoteNeeded())
// Delete entry vote needed again
sut.deleteAllEntries(forDate: votingDate)
XCTAssertTrue(isVoteNeeded())
}
func test_duplicateRemoval() {
let date = makeDate(2024, 6, 15)
// Manually insert 3 entries for same date (simulating CloudKit conflict)
let entry1 = MoodEntryModel(forDate: date, mood: .great, entryType: .listView)
entry1.timestamp = makeDate(2024, 6, 15, hour: 10)
sut.modelContext.insert(entry1)
let entry2 = MoodEntryModel(forDate: date, mood: .good, entryType: .listView)
entry2.timestamp = makeDate(2024, 6, 15, hour: 8)
sut.modelContext.insert(entry2)
let entry3 = MoodEntryModel(forDate: date, mood: .missing, entryType: .filledInMissing)
entry3.timestamp = makeDate(2024, 6, 15, hour: 12)
sut.modelContext.insert(entry3)
sut.save()
let removed = sut.removeDuplicates()
XCTAssertEqual(removed, 2)
XCTAssertEqual(sut.getAllEntries(byDate: date).count, 1)
}
func test_dataListeners_fireOnMutation() {
var listenerCallCount = 0
sut.addNewDataListener {
listenerCallCount += 1
}
// add() calls saveAndRunDataListeners internally
sut.add(mood: .good, forDate: makeDate(2024, 6, 15), entryType: .listView)
// add() does: delete-save (if existing) + insert + saveAndRunDataListeners
// For a fresh add with no existing entry, listener fires once from saveAndRunDataListeners
XCTAssertGreaterThanOrEqual(listenerCallCount, 1, "Listener should fire at least once on mutation")
}
}