feat: working on tests for pressure estimation feature to resolve filter drop bugs

This commit is contained in:
2024-06-18 11:02:59 -04:00
parent 3503f3bbe2
commit 710811878d
3 changed files with 216 additions and 6 deletions

View File

@@ -5,6 +5,7 @@ import SharedModels
import Styleguide
import SwiftUI
#warning("Revert rated static pressures section.")
@Reducer
public struct EquipmentSettingsForm {

View File

@@ -17,7 +17,7 @@ public struct FlaggedMeasurementsList: Sendable {
@ObservableState
@dynamicMemberLookup
public struct State: Equatable {
public struct State: Equatable, Sendable {
@Presents public var destination: Destination.State?
@Shared var sharedSettings: SharedPressureEstimationState
@@ -130,16 +130,38 @@ public struct FlaggedMeasurementsList: Sendable {
)
}
state.destination = nil
return handleEstimationForm(form: form, state: state)
return .run { [state] send in
do {
guard let flaggedEstimation = try await self._handleEstimationForm(form: form, state: state)
else { return }
await send(.receive(.success(.estimatedFlaggedMeasurement(flaggedEstimation))))
} catch {
await send(.receive(.failure(error)))
}
}
}
case .editButtonTapped(id: _):
return .none
case .onAppear:
guard let equipmentMeasurement = state.sharedSettings.equipmentMeasurement else {
return .none
guard state.sharedSettings.flaggedEquipmentMeasurement == nil
else { return .none }
guard let equipmentMeasurement = state.sharedSettings.equipmentMeasurement
else {
return .fail(
"""
Equipment measurement is not set, skipping generating flagged measurement for existing
equipment.
This is considered an application logic error.
""",
logger: logger
)
}
if state.sharedSettings.budgets == nil {
state.sharedSettings.budgets = .init(
equipmentType: state.sharedSettings.equipmentMeasurement!.equipmentType,
@@ -159,6 +181,42 @@ public struct FlaggedMeasurementsList: Sendable {
.ifLet(\.$destination, action: \.destination)
}
enum EstimationFormFailure: Error {
case invalidState
}
func _handleEstimationForm(form: EstimationForm.State, state: State) async throws -> SharedPressureEstimationState.FlaggedEstimationContainer? {
guard let equipmentMeasurement = state.sharedSettings.equipmentMeasurement,
let budgets = state.sharedSettings.budgets
else {
throw EstimationFormFailure.invalidState
}
guard let estimationState = ensureHasChanges(
formState: form,
flaggedEstimations: state.sharedSettings.flaggedEstimations
) else {
logger.debug("No changes found, not generating a new flagged estimation measurement.")
return nil
}
let flaggedMeasurement = try await flaggedMeasurement(
airflow: estimationState.cfm.airflow,
budgets: budgets,
equipmentMeasurement: equipmentMeasurement,
filterPressureDrop: parseFilterPressureDrop(formState: form, sharedSettings: state.sharedSettings),
ratedStaticPresures: state.sharedSettings.ratedStaticPressures,
tons: form.coolingCapacity
)
return SharedPressureEstimationState.FlaggedEstimationContainer(
id: form.id ?? uuid(),
estimationState: estimationState,
flaggedMeasurement: flaggedMeasurement
)
}
#warning("This is making it hard to test, perhaps don't return an effect here.")
private func handleEstimationForm(form: EstimationForm.State, state: State) -> Effect<Action> {
guard let equipmentMeasurement = state.sharedSettings.equipmentMeasurement,
let budgets = state.sharedSettings.budgets
@@ -179,7 +237,6 @@ public struct FlaggedMeasurementsList: Sendable {
flaggedEstimations: state.sharedSettings.flaggedEstimations
) else {
logger.debug("No changes found, not generating a new flagged estimation measurement.")
print("No changes found, not generating a new flagged estimation measurement.")
return .none
}

View File

@@ -1,8 +1,10 @@
import ComposableArchitecture
import SharedModels
import Testing
import XCTest
@testable import PressureEstimationsFeature
struct FlaggedMeasurementListTests {
struct FlaggedMeasurementListStateTests {
@Test(
"Ensure Estimation Has Changes",
@@ -21,6 +23,156 @@ struct FlaggedMeasurementListTests {
#expect(result != nil)
}
@Test(
"Handle Estimation Form",
.tags(.flaggedMeasurementList)
)
func handleEstimationForm() async throws {
try await withDependencies {
$0.estimatedPressuresClient = .liveValue
$0.uuid = .incrementing
} operation: {
@Dependency(\.estimatedPressuresClient) var client
let reducer = FlaggedMeasurementsList()
let result = try await reducer._handleEstimationForm(
form: .init(
existingMeasurement: SharedReader(Shared(.mock(type: .airHandler))),
cfmTextField: 350,
name: "Test"
),
state: .init(sharedSettings: Shared(.init(
budgets: .init(equipmentType: .airHandler, fanType: .constantSpeed),
equipmentMeasurement: .mock(type: .airHandler),
flaggedEquipmentMeasurement: .init(
budgets: .init(equipmentType: .airHandler, fanType: .constantSpeed),
measurement: .mock(type: .airHandler),
ratedPressures: .init(),
tons: .three
)
)))
)
let measurement = try await client.estimatedPressure(
equipmentMeasurement: .mock(type: .airHandler),
airflow: 1050,
filterPressureDrop: 0.1
)
#expect(result != nil)
#expect(result?.estimationState == .init(
cfm: .cfmPerTon(350, .three),
filterPressureDrop: 0.1,
name: "Test"
))
#expect(result?.flaggedMeasurement == .init(
budgets: .init(equipmentType: .airHandler, fanType: .constantSpeed),
measurement: measurement,
ratedPressures: .init(),
tons: .three)
)
}
}
}
final class FlaggedMeasurementListReducerTests: XCTestCase {
override func invokeTest() {
withDependencies {
$0.uuid = .incrementing
$0.estimatedPressuresClient = .liveValue
} operation: {
super.invokeTest()
}
}
@MainActor
func testFlaggedMeasurementListReducer() async throws {
@Dependency(\.estimatedPressuresClient) var estimatedPressuresClient
let store = TestStore(
initialState: FlaggedMeasurementsList.State(
sharedSettings: Shared(SharedPressureEstimationState(
budgets: nil,
equipmentMeasurement: .mock(type: .airHandler),
equipmentMetadata: .init(
coolingCapacity: .three,
fanType: .constantSpeed,
ratedStaticPressures: .init()
)
))
)
) {
FlaggedMeasurementsList()
}
let budgets = BudgetedPercentEnvelope(
equipmentType: .airHandler,
fanType: .constantSpeed
)
let flaggedMeasurement = EquipmentMeasurement.FlaggedMeasurement.init(
budgets: budgets,
measurement: .mock(type: .airHandler),
ratedPressures: .init(),
tons: .three
)
await store.send(.view(.onAppear)) {
$0.sharedSettings.budgets = budgets
$0.sharedSettings.flaggedEquipmentMeasurement = flaggedMeasurement
}
await store.send(.view(.addButtonTapped)) {
$0.destination = .estimationForm(.init(
existingMeasurement: $0.$sharedSettings.equipmentMeasurement,
coolingCapacity: $0.sharedSettings.equipmentMetadata.coolingCapacity
))
}
store.exhaustivity = .off
await store.send(.destination(.presented(.estimationForm(.binding(.set(\.cfmTextField, 350))))))
await store.send(.destination(.presented(.estimationForm(.binding(.set(\.name, "Test"))))))
await store.send(.destination(.presented(.estimationForm(.binding(.set(\.filterPressureDrop, 0.1))))))
// store.exhaustivity = .on
let pressureResult = try await estimatedPressuresClient.estimatedPressure(
equipmentMeasurement: .mock(type: .airHandler),
airflow: 1050,
filterPressureDrop: 0.1
)
let flaggedResult = EquipmentMeasurement.FlaggedMeasurement(
budgets: budgets,
measurement: pressureResult,
ratedPressures: .init(),
tons: .three
)
store.exhaustivity = .off(showSkippedAssertions: true)
// store.exhaustivity = .on
await store.send(.view(.destination(.doneButtonTapped))) {
$0.destination = nil
}
// await store.receive(\.receive.failure, timeout: 10)
// await store.receive(\.receive.success.estimatedFlaggedMeasurement, timeout: 10) {
// $0.sharedSettings.flaggedEstimations[id: UUID(0)] = .init(
// id: UUID(0),
// estimationState: .init(
// cfm: .cfmPerTon(350, .three),
// filterPressureDrop: 0.1,
// name: "Test"
// ),
// flaggedMeasurement: flaggedResult
// )
// }
//
await store.finish()
}
}
extension Tag {