field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

commit 85539f4be30deb45c8cd03cbd7216f29370510b5
parent 92b7b5528150afc41e4d0b91f09b98a217a4c0f5
Author: triesap <tyson@radroots.org>
Date:   Fri, 28 Aug 2026 18:37:57 +0000

test: observe both terminal UI signals

- Retain the ordinary status label as the primary submission lifecycle signal.
- Accept a guarded changed submit value when the status row is virtualized.
- Never read a submit value until XCUITest confirms that element exists.
- Preserve a single visible tap and the zero-duplicate publication invariant.

Diffstat:
MRadrootsUITests/RadrootsRemoteQualificationUITests.swift | 28+++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/RadrootsUITests/RadrootsRemoteQualificationUITests.swift b/RadrootsUITests/RadrootsRemoteQualificationUITests.swift @@ -1069,12 +1069,14 @@ final class RadrootsRemoteQualificationUITests: XCTestCase { private func submitAndWait(_ app: XCUIApplication, submit: XCUIElement) -> String? { let status = app.staticTexts.matching(identifier: "radroots.add.status").firstMatch let priorStatusLabel = status.exists ? status.label : nil + let priorSubmitValue = submit.value as? String guard tapSubmitUntilWorkStarts( app, submit: submit, status: status, - priorStatusLabel: priorStatusLabel + priorStatusLabel: priorStatusLabel, + priorSubmitValue: priorSubmitValue ) else { XCTFail( @@ -1086,8 +1088,10 @@ final class RadrootsRemoteQualificationUITests: XCTestCase { guard waitForWorkToFinish( app, + submit: submit, status: status, - priorStatusLabel: priorStatusLabel + priorStatusLabel: priorStatusLabel, + priorSubmitValue: priorSubmitValue ) else { XCTFail( @@ -1130,13 +1134,20 @@ final class RadrootsRemoteQualificationUITests: XCTestCase { @MainActor private func waitForWorkToFinish( _ app: XCUIApplication, + submit: XCUIElement, status: XCUIElement, - priorStatusLabel: String? + priorStatusLabel: String?, + priorSubmitValue: String? ) -> Bool { let progress = app.descendants(matching: .any)["radroots.add.progress"] let finished = NSPredicate { _, _ in - guard !progress.exists, status.exists else { return false } - return !status.label.isEmpty && status.label != priorStatusLabel + guard !progress.exists else { return false } + if status.exists, !status.label.isEmpty, status.label != priorStatusLabel { + return true + } + guard submit.exists else { return false } + let submitValue = submit.value as? String + return submitValue != priorSubmitValue && submitValue != "Working" } let expectation = XCTNSPredicateExpectation(predicate: finished, object: app) return XCTWaiter.wait(for: [expectation], timeout: 180) == .completed @@ -1147,13 +1158,16 @@ final class RadrootsRemoteQualificationUITests: XCTestCase { _ app: XCUIApplication, submit: XCUIElement, status: XCUIElement, - priorStatusLabel: String? + priorStatusLabel: String?, + priorSubmitValue: String? ) -> Bool { let progress = app.descendants(matching: .any)["radroots.add.progress"] let started = NSPredicate { _, _ in if progress.exists { return true } if status.exists { return status.label != priorStatusLabel } - return priorStatusLabel != nil + if priorStatusLabel != nil { return true } + guard submit.exists else { return false } + return (submit.value as? String) != priorSubmitValue } submit.tap()