From 6b5154c7c4021d33893c59a73b51714002d02809 Mon Sep 17 00:00:00 2001 From: pollymce Date: Thu, 1 Oct 2026 17:37:04 +0100 Subject: [PATCH] Bug 2073095 - get rid of mockk to support running ui tests on nightly. Also fix issues with settings page looking for the string "debug build", and amend the timestamp test to actually check the timestamp. --- mobile/android/fenix/app/build.gradle | 1 - .../org/mozilla/fenix/ui/NimbusEventTest.kt | 50 +++++++++++++++++-- .../ui/efficiency/core/VerbContractTest.kt | 14 ++++-- .../ui/robots/SettingsSubMenuAboutRobot.kt | 13 +++-- 4 files changed, 63 insertions(+), 15 deletions(-) diff --git a/mobile/android/fenix/app/build.gradle b/mobile/android/fenix/app/build.gradle index fd141eca9d3fa..4e34231ebc865 100644 --- a/mobile/android/fenix/app/build.gradle +++ b/mobile/android/fenix/app/build.gradle @@ -670,7 +670,6 @@ dependencies { androidTestImplementation libs.kotlin.test androidTestImplementation libs.androidx.room.testing androidTestImplementation libs.leakcanary.instrumentation - androidTestImplementation libs.mockk.android androidTestImplementation libs.mockwebserver androidTestImplementation libs.okhttp androidTestRuntimeOnly libs.okio diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/NimbusEventTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/NimbusEventTest.kt index 5a82114b62fb6..1e97e2ba77edc 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/NimbusEventTest.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/NimbusEventTest.kt @@ -5,9 +5,10 @@ package org.mozilla.fenix.ui import android.content.Intent -import io.mockk.mockk import mozilla.components.concept.sync.AuthType -import mozilla.components.service.fxa.FirefoxAccount +import mozilla.components.concept.sync.FxAEntryPoint +import mozilla.components.concept.sync.OAuthAccount +import mozilla.components.concept.sync.StatePersistenceCallback import org.junit.Assert.assertTrue import org.junit.Rule import org.junit.Test @@ -43,11 +44,52 @@ class NimbusEventTest { @Test fun telemetryAccountObserverTest() { val observer = TelemetryAccountObserver(appContext, appContext.components.settings) - // replacing interface mock with implementation mock. - observer.onAuthenticated(mockk(), AuthType.Signin) + observer.onAuthenticated(UnusedOAuthAccount(), AuthType.Signin) Experimentation.withHelper { assertTrue(evalJexl("'sync_auth.sign_in'|eventSum('Days', 28, 0) > 0")) } } } + +/** + * Stands in for the account argument of [TelemetryAccountObserver.onAuthenticated], which the observer never reads. + * Every member throws, so any future use shows up immediately rather than silently passing. + */ +private class UnusedOAuthAccount : OAuthAccount { + override fun getCurrentDeviceId() = unused() + + override suspend fun handleWebChannelLogin(jsonPayload: String) = unused() + + override fun getSignedInUserForWebChannel() = unused() + + override suspend fun getProfile(ignoreCache: Boolean) = unused() + + override suspend fun getAccessToken(singleScope: String) = unused() + + override suspend fun getAttachedClient() = unused() + + override fun authErrorDetected() = unused() + + override suspend fun checkAuthorizationStatus(singleScope: String) = unused() + + override suspend fun getTokenServerEndpointURL() = unused() + + override suspend fun getManageAccountURL(entryPoint: FxAEntryPoint) = unused() + + override fun getPairingAuthorityURL() = unused() + + override fun registerPersistenceCallback(callback: StatePersistenceCallback) = unused() + + override fun deviceConstellation() = unused() + + override fun hasScope(scope: String) = unused() + + override suspend fun disconnect() = unused() + + override fun toJSONString() = unused() + + override fun close() = unused() + + private fun unused(): Nothing = throw UnsupportedOperationException("not used by the code under test") +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/core/VerbContractTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/core/VerbContractTest.kt index 7e59fd852e0d5..c94417c9f4dad 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/core/VerbContractTest.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/core/VerbContractTest.kt @@ -7,9 +7,10 @@ package org.mozilla.fenix.ui.efficiency.core import androidx.compose.ui.test.SemanticsNodeInteractionCollection import androidx.test.espresso.Espresso.onView import androidx.test.espresso.matcher.ViewMatchers.isRoot +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiObject -import io.mockk.every -import io.mockk.mockk +import androidx.test.uiautomator.UiSelector import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertSame @@ -86,7 +87,9 @@ class VerbContractTest { // groupAbsent probes DISPLAYED on the resolved element, and Espresso's isDisplayed() needs a // running activity this unit test never launches. A UiObject reports DISPLAYED via exists(), // so a stub that exists is a present element without a UI in the loop. - val present = UiObjectUiElement(mockk { every { exists() } returns true }) + // Constructing one needs the UiDevice singleton, which nothing else in this test touches. + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + val present = UiObjectUiElement(AlwaysPresentUiObject()) val host = FakeVerbHost(TimedReporter(logger), ElementResolution.Found(present)) val absent = host.groupAbsent(verb = "verify_group_absent", label = "Page_GROUP", selectors = listOf(selector)) @@ -284,6 +287,11 @@ class VerbContractTest { override fun stepId(prefix: String, description: String) = "$prefix-$description" } + @Suppress("DEPRECATION") + private class AlwaysPresentUiObject : UiObject(UiSelector()) { + override fun exists() = true + } + private class RecordingStepLogger : StepLogger { val completed = mutableListOf() diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt index 8e511d1e42eb8..fbde05393f668 100644 --- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt @@ -28,6 +28,7 @@ import androidx.test.uiautomator.UiSelector import mozilla.components.support.utils.ext.packageManagerCompatHelper import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString +import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.R import org.mozilla.fenix.helpers.Constants.LISTS_MAXSWIPES import org.mozilla.fenix.helpers.Constants.TAG @@ -51,7 +52,7 @@ class SettingsSubMenuAboutRobot { val packageInfo = context.packageManagerCompatHelper.getPackageInfoCompat(context.packageName, 0) val versionCode = PackageInfoCompat.getLongVersionCode(packageInfo).toString() - val buildNVersion = "${packageInfo.versionName} (Build #$versionCode)\n" + val buildNVersion = "${packageInfo.versionName} (Build #$versionCode)" val geckoVersion = org.mozilla.geckoview.BuildConfig.MOZ_APP_VERSION + "-" + org.mozilla.geckoview.BuildConfig.MOZ_APP_BUILDID val asVersion = mozilla.components.Build.APPLICATION_SERVICES_VERSION @@ -89,12 +90,10 @@ class SettingsSubMenuAboutRobot { } fun verifyCurrentTimestamp() { - Log.i(TAG, "verifyCurrentTimestamp: Trying to verify that the about section contains \"debug build\"") - onView(withId(R.id.build_date)) - // Currently UI tests run against debug builds, which display a hard-coded string 'debug build' - // instead of the date. See https://github.com/mozilla-mobile/fenix/pull/10812#issuecomment-633746833 - .check(matches(withText(containsString("debug build")))) - Log.i(TAG, "verifyCurrentTimestamp: Verified that the about section contains \"debug build\"") + val buildDate = BuildConfig.BUILD_DATE + Log.i(TAG, "verifyCurrentTimestamp: Trying to verify that the about section contains \"$buildDate\"") + onView(withId(R.id.build_date)).check(matches(withText(containsString(buildDate)))) + Log.i(TAG, "verifyCurrentTimestamp: Verified that the about section contains \"$buildDate\"") } fun verifyAboutToolbar() {