Add PlantGuide iOS app with plant identification and care management
- Implement camera capture and plant identification workflow - Add Core Data persistence for plants, care schedules, and cached API data - Create collection view with grid/list layouts and filtering - Build plant detail views with care information display - Integrate Trefle botanical API for plant care data - Add local image storage for captured plant photos - Implement dependency injection container for testability - Include accessibility support throughout the app Bug fixes in this commit: - Fix Trefle API decoding by removing duplicate CodingKeys - Fix LocalCachedImage to load from correct PlantImages directory - Set dateAdded when saving plants for proper collection sorting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
//
|
||||
// PlantCareSchedule+TestFixtures.swift
|
||||
// PlantGuideTests
|
||||
//
|
||||
// Test fixtures for PlantCareSchedule entity - provides factory methods for
|
||||
// creating test instances with sensible defaults.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@testable import PlantGuide
|
||||
|
||||
// MARK: - PlantCareSchedule Test Fixtures
|
||||
|
||||
extension PlantCareSchedule {
|
||||
|
||||
// MARK: - Factory Methods
|
||||
|
||||
/// Creates a mock care schedule with default values for testing
|
||||
/// - Parameters:
|
||||
/// - id: The schedule's unique identifier. Defaults to a new UUID.
|
||||
/// - plantID: ID of the plant this schedule belongs to. Defaults to a new UUID.
|
||||
/// - lightRequirement: Light needs. Defaults to .partialShade.
|
||||
/// - wateringSchedule: Watering description. Defaults to "Weekly".
|
||||
/// - temperatureRange: Safe temp range. Defaults to 18...26.
|
||||
/// - fertilizerSchedule: Fertilizer description. Defaults to "Monthly".
|
||||
/// - tasks: Array of care tasks. Defaults to empty.
|
||||
/// - Returns: A configured PlantCareSchedule instance for testing
|
||||
static func mock(
|
||||
id: UUID = UUID(),
|
||||
plantID: UUID = UUID(),
|
||||
lightRequirement: LightRequirement = .partialShade,
|
||||
wateringSchedule: String = "Weekly",
|
||||
temperatureRange: ClosedRange<Int> = 18...26,
|
||||
fertilizerSchedule: String = "Monthly",
|
||||
tasks: [CareTask] = []
|
||||
) -> PlantCareSchedule {
|
||||
PlantCareSchedule(
|
||||
id: id,
|
||||
plantID: plantID,
|
||||
lightRequirement: lightRequirement,
|
||||
wateringSchedule: wateringSchedule,
|
||||
temperatureRange: temperatureRange,
|
||||
fertilizerSchedule: fertilizerSchedule,
|
||||
tasks: tasks
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a mock schedule with watering tasks
|
||||
/// - Parameters:
|
||||
/// - plantID: ID of the plant this schedule belongs to
|
||||
/// - taskCount: Number of watering tasks to generate. Defaults to 4.
|
||||
/// - startDate: Starting date for first task. Defaults to tomorrow.
|
||||
/// - Returns: A schedule with generated watering tasks
|
||||
static func mockWithWateringTasks(
|
||||
plantID: UUID = UUID(),
|
||||
taskCount: Int = 4,
|
||||
startDate: Date = Calendar.current.date(byAdding: .day, value: 1, to: Date())!
|
||||
) -> PlantCareSchedule {
|
||||
let tasks = (0..<taskCount).map { index in
|
||||
CareTask.mockWatering(
|
||||
plantID: plantID,
|
||||
scheduledDate: Calendar.current.date(byAdding: .day, value: index * 7, to: startDate)!
|
||||
)
|
||||
}
|
||||
return mock(
|
||||
plantID: plantID,
|
||||
wateringSchedule: "Every 7 days",
|
||||
tasks: tasks
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a mock schedule with mixed care tasks
|
||||
/// - Parameters:
|
||||
/// - plantID: ID of the plant this schedule belongs to
|
||||
/// - Returns: A schedule with watering and fertilizing tasks
|
||||
static func mockWithMixedTasks(plantID: UUID = UUID()) -> PlantCareSchedule {
|
||||
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: Date())!
|
||||
let nextWeek = Calendar.current.date(byAdding: .day, value: 7, to: Date())!
|
||||
let nextMonth = Calendar.current.date(byAdding: .day, value: 30, to: Date())!
|
||||
|
||||
let tasks: [CareTask] = [
|
||||
.mockWatering(plantID: plantID, scheduledDate: tomorrow),
|
||||
.mockWatering(plantID: plantID, scheduledDate: nextWeek),
|
||||
.mockFertilizing(plantID: plantID, scheduledDate: nextMonth)
|
||||
]
|
||||
|
||||
return mock(
|
||||
plantID: plantID,
|
||||
wateringSchedule: "Weekly",
|
||||
fertilizerSchedule: "Monthly during growing season",
|
||||
tasks: tasks
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a mock schedule for a tropical plant (high humidity, frequent watering)
|
||||
static func mockTropical(plantID: UUID = UUID()) -> PlantCareSchedule {
|
||||
mock(
|
||||
plantID: plantID,
|
||||
lightRequirement: .partialShade,
|
||||
wateringSchedule: "Every 3 days",
|
||||
temperatureRange: 20...30,
|
||||
fertilizerSchedule: "Biweekly during growing season"
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a mock schedule for a succulent (low water, full sun)
|
||||
static func mockSucculent(plantID: UUID = UUID()) -> PlantCareSchedule {
|
||||
mock(
|
||||
plantID: plantID,
|
||||
lightRequirement: .fullSun,
|
||||
wateringSchedule: "Every 14 days",
|
||||
temperatureRange: 15...35,
|
||||
fertilizerSchedule: "Monthly during spring and summer"
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a mock schedule for a shade-loving plant
|
||||
static func mockShadePlant(plantID: UUID = UUID()) -> PlantCareSchedule {
|
||||
mock(
|
||||
plantID: plantID,
|
||||
lightRequirement: .lowLight,
|
||||
wateringSchedule: "Weekly",
|
||||
temperatureRange: 16...24,
|
||||
fertilizerSchedule: "Every 6 weeks"
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a mock schedule with overdue tasks
|
||||
static func mockWithOverdueTasks(plantID: UUID = UUID()) -> PlantCareSchedule {
|
||||
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
|
||||
let lastWeek = Calendar.current.date(byAdding: .day, value: -7, to: Date())!
|
||||
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: Date())!
|
||||
|
||||
let tasks: [CareTask] = [
|
||||
.mockWatering(plantID: plantID, scheduledDate: lastWeek), // Overdue
|
||||
.mockWatering(plantID: plantID, scheduledDate: yesterday), // Overdue
|
||||
.mockWatering(plantID: plantID, scheduledDate: tomorrow) // Upcoming
|
||||
]
|
||||
|
||||
return mock(
|
||||
plantID: plantID,
|
||||
tasks: tasks
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a mock schedule with completed tasks
|
||||
static func mockWithCompletedTasks(plantID: UUID = UUID()) -> PlantCareSchedule {
|
||||
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
|
||||
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: Date())!
|
||||
let nextWeek = Calendar.current.date(byAdding: .day, value: 7, to: Date())!
|
||||
|
||||
let tasks: [CareTask] = [
|
||||
.mockWatering(plantID: plantID, scheduledDate: yesterday, completedDate: yesterday),
|
||||
.mockWatering(plantID: plantID, scheduledDate: tomorrow),
|
||||
.mockWatering(plantID: plantID, scheduledDate: nextWeek)
|
||||
]
|
||||
|
||||
return mock(
|
||||
plantID: plantID,
|
||||
tasks: tasks
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user