From c060f1b3ecd215593d8d1c69b416c102b485b725 Mon Sep 17 00:00:00 2001 From: "Shane B." Date: Sun, 13 Sep 2026 20:15:30 +0200 Subject: [PATCH] Stop the empty login error box leaving a gap above the fields The box started as `invisible`, which hides a view but keeps its height, so before any sign-in had failed there was a blank band between the title and the fields. It had been there quietly; putting the Export logs button inside the box in #197 made it tall enough to notice. It now starts `gone`, which is the state the code already assumes: the only two toggles are VISIBLE on a failure and GONE on success. Height is `wrap_content` rather than `match_parent`, the same mistake #184 fixed in the device list row. The test asserts GONE specifically. `not(isDisplayed())` is equally true of an invisible view and would have passed against the gap - it is the check the Export logs test already makes, and it said nothing about this. Co-Authored-By: Claude Opus 5 (1M context) --- .../opentagviewer/AppleLoginFlowTest.java | 22 +++++++++++++++++++ .../main/res/layout/activity_apple_login.xml | 11 ++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/dev/wander/android/opentagviewer/AppleLoginFlowTest.java b/app/src/androidTest/java/dev/wander/android/opentagviewer/AppleLoginFlowTest.java index 7f4dd0df..03567a97 100644 --- a/app/src/androidTest/java/dev/wander/android/opentagviewer/AppleLoginFlowTest.java +++ b/app/src/androidTest/java/dev/wander/android/opentagviewer/AppleLoginFlowTest.java @@ -9,6 +9,7 @@ import static androidx.test.espresso.intent.Intents.intending; import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; @@ -28,6 +29,7 @@ import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; import static org.hamcrest.Matchers.allOf; import androidx.test.espresso.intent.Intents; +import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; @@ -389,6 +391,26 @@ public void thelogButtonIsNotOfferedBeforeAnythingHasFailed() { onView(withId(R.id.login_error_export_logs)).check(matches(not(isDisplayed()))); } + /** + * The empty error box takes no room. + * + *

It started as {@code invisible}, which hides a view but keeps its height, so before any + * failure there was a blank band between the title and the fields - one that grew when the + * Export logs button went inside the box, which is when somebody noticed. Asserted as + * {@code GONE} specifically, because {@code not(isDisplayed())} is equally true of an + * invisible view and would have passed against the gap. + */ + @Test + public void theemptyErrorBoxTakesNoRoomBeforeAnythingHasFailed() { + this.apple = FakeAppleAuthService.rejectsTheSignIn("Bad password"); + AppDependencies.replaceAuthService(this.apple); + + launch(); + + onView(withId(R.id.login_error_container)) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + } + /** A rejected code says so, and gives the boxes back rather than stranding them. */ @Test public void aWrongCodeIsReportedAndTheBoxesComeBack() { diff --git a/app/src/main/res/layout/activity_apple_login.xml b/app/src/main/res/layout/activity_apple_login.xml index 9964a512..7ba32070 100644 --- a/app/src/main/res/layout/activity_apple_login.xml +++ b/app/src/main/res/layout/activity_apple_login.xml @@ -120,15 +120,22 @@ android:visibility="gone" tools:visibility="gone"> +