Files
mantra-kmp/composeApp
Kgothatso Ngako 93f8ab313c test(projects): cover the three view models and the query nothing asked about
The feature's logic was tested from the events down to the chronicle and not at
all above the repository. Four gaps, each one something no other layer would
catch.

**AddProjectViewModel.** A project and its contents go out as one batch whose
memberships carry the project's id -- which is a hash over the group's key at
the room's path and does not exist until the proposal is made, so the screen
hands over a function of the signed lead. Nothing downstream notices if that
function returns the wrong thing: a membership naming another project is a
valid event, signs cleanly, and lands as a row pointing elsewhere. Eight cases
assert the batch's shape against a recording repository that signs the lead the
way a finished session does, including that the creator is the member filling
the form in -- there is no field for it and nothing else to check it against.

**AddToProjectViewModel.** The candidate filtering is the only thing stopping a
duplicate membership, because a duplicate is a valid event with its own id: the
keys are satisfied, the signature is good, the row gets written. A wrong filter
would spend a quorum saying what the group has already said and look like the
feature working. Ten cases, including that the two halves filter independently.

**FrostSigningViewModel's resolver.** Unresolved, the signing screen asks a
member to agree to "a4f1be55d0c3". Seven cases through the same `summarize`
call the screen makes: a membership reads as the artifact and label, a stranger
falls back to a hash rather than an invented name, the room owning its own work
says nothing, and a project being signed in the same batch resolves to nothing
-- which is why a membership says the version first.

**getProjectsByTranslationArtifactVersionId** had no test at any layer while its
artifact-side twin had one from the start. That asymmetry is what a copied join
hides.

Two notes for whoever writes the next view-model test. These view models hold
state in `mutableStateOf` and initiate on `Dispatchers.IO`, so there is nothing
to collect and the call returns before the work is done -- hence `awaitValue`,
polling in real time for the same reason `NavigationIdentityRoutingJvmTest`
does. And `NostrRepository.NO_OP_NOSTR_REPOSITORY.getProfileWithPublicKey` is a
`TODO()`, so a resolver that asks it about anybody throws on a background
dispatcher and surfaces as a timeout rather than a failure anybody can read;
these read profiles from the seeded database instead, which also gives the
honest answer for a stranger.

983 jvmTest, 447 testDebugUnitTest, no failures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-02 20:26:05 +02:00
..