Two apps, three defects that only driving them could find
The relay is asked what it is, and the answer went nowhere. SiteConfig is a
data class whose only constructor property was `baseUrl`; `discovered` was a
`var` in the body, so the generated equals() ignored it. MutableStateFlow
conflates on equality, which made
_site.value = config.also { it.discovered = found }
a no-op against the value already there. The descriptor was fetched correctly
and discarded. The sign-in screen sat on "Checking what this server uses…"
forever — the one line whose whole job is to say, BEFORE the passphrase is
typed, whether that passphrase leaves the device — and accountProvider stayed
LOCAL for a relay that had just answered SHARED. Now a constructor property,
written with copy(), with the first JVM unit tests the :app module has ever
had. Confirmed live: the screen reads "One Flamenet account, shared with
Flamenet Files."
Two XCUITest queries matched more than one element and so could tap neither:
- "👍" is in the emoji picker's Gestures row, in its Recent row once picked,
and in ChatView's quick-reaction bar. Picker buttons now carry a
section-scoped identifier.
- "Sign out" is both the row in ProfileView and the destructive button in the
confirmation it opens; SwiftUI keeps both in the tree, so the query was
ambiguous before the dialog was even reached. Both now identified.
Neither was load — both fail the same way on an idle machine.
Also adds completeSignIn to UITestSupport, the counterpart to completeSignUp.
Sign-ups are rate limited at three an hour per address, so a test that only
needs AN identity should reuse one rather than mint another and fail with a
429 that reads like a broken sign-up screen. CrossPlatformUITests takes
FN_TEST_PASSWORD and signs in when given one.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b051814a6c
commit
053cefbce4
@@ -172,7 +172,10 @@ class MessengerViewModel(app: Application) : AndroidViewModel(app) {
|
||||
io.flamenet.client.RelayDiscovery.describe(config.baseUrl)
|
||||
}
|
||||
if (_relayInput.value != value) return@launch
|
||||
_site.value = config.also { it.discovered = found }
|
||||
// copy(), not a mutation: SiteConfig is a data class and the flow
|
||||
// conflates on equality, so an in-place write is indistinguishable
|
||||
// from the value already there and never reaches the UI.
|
||||
_site.value = config.copy(discovered = found)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,22 @@ import java.net.URI
|
||||
* - **Self-hosted, local** — their relay, its own account table. Not a lesser
|
||||
* mode: everything works, it simply is not the same login as Files.
|
||||
*/
|
||||
data class SiteConfig(val baseUrl: String) {
|
||||
data class SiteConfig(
|
||||
val baseUrl: String,
|
||||
/**
|
||||
* What the relay said about itself, or null until it has answered.
|
||||
*
|
||||
* ⚠️ **A constructor property on purpose.** It used to be a `var` in the
|
||||
* class body, which left it out of the generated `equals()` — and
|
||||
* `MutableStateFlow` conflates on equality, so writing back a config that
|
||||
* differed ONLY by its descriptor was silently dropped. The relay was
|
||||
* asked, it answered, and the answer went nowhere: the sign-in screen sat
|
||||
* on "Checking what this server uses…" forever and `accountProvider` stayed
|
||||
* LOCAL for a shared-accounts relay. Keep it in the constructor and write
|
||||
* it with `copy(...)`.
|
||||
*/
|
||||
val discovered: io.flamenet.client.RelayDiscovery.Descriptor? = null,
|
||||
) {
|
||||
|
||||
enum class AccountProvider {
|
||||
/** The shared FlameNet account service. One credential across products. */
|
||||
@@ -65,8 +80,6 @@ data class SiteConfig(val baseUrl: String) {
|
||||
* Defaults to LOCAL until the descriptor has been fetched, which is the
|
||||
* safe direction: the passphrase goes only to the server the user typed.
|
||||
*/
|
||||
var discovered: io.flamenet.client.RelayDiscovery.Descriptor? = null
|
||||
|
||||
val accountProvider: AccountProvider
|
||||
get() = if (discovered?.usesSharedAccounts == true) {
|
||||
AccountProvider.SHARED
|
||||
|
||||
Reference in New Issue
Block a user