test: cover the offline queue, account wipe, importers, and wear codecs#36
Merged
Conversation
…s. Adds 70 phone tests and ~40 wear tests, and fixes two live bugs the tests surfaced. Fixes: runCatching, so a throw from the cache clear skipped the queue deletes and left the previous account's queued switches to replay under the new session. Each step now runs independently. This is a cross-account isolation guard, so - The importers hand-build their JSON submit bodies and escaped only quotes and backslashes. A pasted token with a newline (routine when copying from a chat client) produced a literal newline inside a JSON string and the import 422'd. Added a shared jsonEscape/jsonQuote covering the control range and routed the eight importers through it. Small refactors to make logic testable without an Android framework: - Extracted SyncWorker's op ordering and failure classification to top-level mergeQueuedOps / isPermanentHttpFailure. - Made wear's isPermanentSwitchError a top-level function and widened WearSwitchQueue.parseLine to internal. Coverage added: - Phone: FrontUpdate tri-state adapter, SystemTimezoneBody serialize-nulls, MemberRead display/initials, SyncWorker ordering + classification, TrustedDeviceCookieJar scoping, RevisionSafety re-auth gating, history pagination math, MemberDetailViewModel create-then-patch dedupe, RelationshipsEditorViewModel load-retry latch. - Wear: FrontHistory codec, WearSwitchQueue codec, isPermanentSwitchError parity with the phone, WearMember display/initials, markdown stripping.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A general test-coverage pass over the pure logic that fails silently when it breaks: serialisers whose
wrong output the server accepts as a no-op, queue codecs whose parse errors just drop a row, and
classification that quietly deletes an offline action. Went from 70 to 140 phone tests and from a handful to
45 wear tests, and it turned up two live bugs on the way.
Live bugs found (and fixed here)
AccountDataWiper skipped the queue wipe on a cache error. All three clears sat inside one
runCatching, so a throw fromcache.clearAll()skipped bothdeleteAllSwitches()/deleteAllRemovals().That is the precise failure the class exists to prevent: the previous account
s queued front switches surviving to replay against the new accounts credentials. Each step now runs independently.Importing with a token that had a control char produced invalid JSON. The importers hand-build their
submit bodies (the options blob is already-encoded JSON, so a typed class would encode it twice) and escaped
only
"and\. A PluralKit token pasted from a chat client routinely carries a trailing newline, whichwent into the body as a literal newline inside a JSON string and the whole import 422
d. Added a sharedjsonEscape/jsonQuote` that covers the JSON control range and routed all eight importers through it.Small refactors to make logic testable without an Android framework
SyncWorker: extracted the op ordering and the failure classification to top-levelmergeQueuedOps/isPermanentHttpFailure(they wereprivateinside a@HiltWorkerthat needs aContext).isPermanentSwitchErroris now a top-level function;WearSwitchQueue.parseLinewidened tointernal. No behaviour change.What is now covered
Phone (new): the
FrontUpdatetri-state adapter (omit / explicit-null / value, i.e. the "mark stillongoing" clear),
SystemTimezoneBodyserialize-nulls (the "Automatic = explicit null" contract),MemberReaddisplay-name/initials, the offline-queue ordering + drop-vs-retry classification,
AccountDataWiperstepindependence, import body escaping + terminal-result decoding,
TrustedDeviceCookieJarscoping (only the onecookie, only under
/v1/auth/),RevisionSafetyre-auth gating, history pagination math, theMemberDetailViewModelcreate-then-patch duplicate guard, and theRelationshipsEditorViewModelload-retrylatch.
Wear (new): the
FrontHistoryandWearSwitchQueuehand-rolled codecs,isPermanentSwitchErrorheld to thesame verdicts as the phone,
WearMemberdisplay/initials, and markdown stripping.Not done here (tracked)
The higher-cost targets need infrastructure this PR deliberately skips:
TokenAuthenticatorandWearApiClientrefresh-mutex tests want MockWebServer; the SharedPreferences-backed wear helpers and theWearAuthManagersign-out latch want Robolectric; and there is still noandroidTest baseline at all. Thoseare worth a follow-up if we want to add the deps.
Verification
:app:assemblePlayRelease :wear:assembleRelease :app:testPlayReleaseUnitTest :wear:testPlayReleaseUnitTestgreen.