recommendedCrossSection now satisfies two criteria and takes whichever demands more copper: the voltage-drop budget, and an ampacity at least as high as the fuse protecting the circuit (ABYC E-11: the OCP rating must not exceed the conductor's ampacity). Ampacity comes from ABYC E-11 Table 6A for AWG and ISO 13297 Table A1 for mm², both 105 °C. Before this, a 40 A load over 0.5 m was sized 1.5 mm² / AWG 16 next to a 50 A fuse: a cable the fuse can never protect. Long runs stay voltage-drop driven and unchanged. The drop budget is now stored per system (3 / 5 / 10 %) and editable in the system editor, with a global default in Settings that the standalone calculator uses and new systems inherit. Cross-sections are derived, never entered by the user, so LoadCableSync re-derives them when a system opens and when its budget changes. Library loads are computed instead of being stored as a 1.0 mm² placeholder. LoadConfigurationStatus therefore reports only what the user can actually fix: missing length or current. Also removes the dead cable.pro.* strings and folds three copies of the mm²-to-AWG conversion into ElectricalCalculations.nearestAWG.
65 lines
2.2 KiB
Swift
65 lines
2.2 KiB
Swift
import XCTest
|
|
|
|
/// Verifies that a system exposes its voltage-drop budget and that picking a tighter
|
|
/// target sticks, which is what drives cable sizing for that system.
|
|
final class SystemVoltageDropTargetUITests: XCTestCase {
|
|
|
|
override func setUpWithError() throws {
|
|
try super.setUpWithError()
|
|
continueAfterFailure = false
|
|
XCUIDevice.shared.orientation = .portrait
|
|
}
|
|
|
|
@MainActor
|
|
func testVoltageDropBudgetIsSelectableInSystemEditor() throws {
|
|
let app = launch(arguments: ["--uitest-reset-data", "--uitest-sample-data"])
|
|
|
|
openFirstSystem(in: app)
|
|
|
|
let systemTitle = app.buttons["system-title-button"]
|
|
XCTAssertTrue(systemTitle.waitForExistence(timeout: 15))
|
|
systemTitle.tap()
|
|
|
|
let picker = app.segmentedControls["system-voltage-drop-picker"]
|
|
XCTAssertTrue(picker.waitForExistence(timeout: 15), "System editor must offer a voltage drop budget")
|
|
|
|
let standard = picker.buttons["5 %"]
|
|
XCTAssertTrue(standard.waitForExistence(timeout: 5))
|
|
XCTAssertTrue(standard.isSelected, "New systems start at the 5 % default")
|
|
|
|
let critical = picker.buttons["3 %"]
|
|
XCTAssertTrue(critical.exists)
|
|
critical.tap()
|
|
XCTAssertTrue(critical.isSelected, "Picking 3 % must stick")
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
private func launch(arguments: [String]) -> XCUIApplication {
|
|
let app = XCUIApplication()
|
|
app.launchArguments = arguments
|
|
app.launch()
|
|
return app
|
|
}
|
|
|
|
private func openFirstSystem(in app: XCUIApplication) {
|
|
let list: XCUIElement
|
|
if app.collectionViews["systems-list"].waitForExistence(timeout: 15) {
|
|
list = app.collectionViews["systems-list"]
|
|
} else {
|
|
list = app.collectionViews.firstMatch
|
|
}
|
|
XCTAssertTrue(list.waitForExistence(timeout: 15))
|
|
|
|
let firstCell = list.cells.element(boundBy: 0)
|
|
XCTAssertTrue(firstCell.waitForExistence(timeout: 10))
|
|
|
|
let cellButton = firstCell.buttons.firstMatch
|
|
if cellButton.exists {
|
|
cellButton.tap()
|
|
} else {
|
|
firstCell.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
|
|
}
|
|
}
|
|
}
|