From 6be39aebde2ac64c703358f3c88eb3f4c9d29f19 Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Wed, 15 Jul 2020 23:31:59 -0700 Subject: [PATCH] Add tests for StartupReportFullyDrawn (#12560) --- .../fenix/perf/StartupReportFullyDrawn.kt | 6 +- .../fenix/perf/StartupReportFullyDrawnTest.kt | 83 +++++++++++++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 app/src/test/java/org/mozilla/fenix/perf/StartupReportFullyDrawnTest.kt diff --git a/app/src/main/java/org/mozilla/fenix/perf/StartupReportFullyDrawn.kt b/app/src/main/java/org/mozilla/fenix/perf/StartupReportFullyDrawn.kt index 695359e2c..c30720fec 100644 --- a/app/src/main/java/org/mozilla/fenix/perf/StartupReportFullyDrawn.kt +++ b/app/src/main/java/org/mozilla/fenix/perf/StartupReportFullyDrawn.kt @@ -7,8 +7,8 @@ package org.mozilla.fenix.perf import android.app.Activity import android.view.View import androidx.core.view.doOnPreDraw -import kotlinx.android.synthetic.main.activity_home.* import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.R import org.mozilla.fenix.ext.reportFullyDrawnSafe import org.mozilla.fenix.home.sessioncontrol.viewholders.topsites.TopSiteItemViewHolder import org.mozilla.fenix.perf.StartupTimelineStateMachine.StartupDestination.APP_LINK @@ -36,7 +36,7 @@ class StartupReportFullyDrawn { state is StartupState.Cold && state.destination == APP_LINK) { // Instrumenting the first frame drawn should be good enough for app link for now. isInstrumented = true - attachReportFullyDrawn(activity, activity.rootContainer) + attachReportFullyDrawn(activity, activity.findViewById(R.id.rootContainer)) } } @@ -59,7 +59,7 @@ class StartupReportFullyDrawn { } } - private fun attachReportFullyDrawn(activity: HomeActivity, view: View) { + private fun attachReportFullyDrawn(activity: Activity, view: View) { // For greater accuracy, we could add an onDrawListener instead of a preDrawListener but: // - single use onDrawListeners are not built-in and it's non-trivial to write one // - the difference in timing is minimal (< 7ms on Pixel 2) diff --git a/app/src/test/java/org/mozilla/fenix/perf/StartupReportFullyDrawnTest.kt b/app/src/test/java/org/mozilla/fenix/perf/StartupReportFullyDrawnTest.kt new file mode 100644 index 000000000..23b67713d --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/perf/StartupReportFullyDrawnTest.kt @@ -0,0 +1,83 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.perf + +import android.view.View +import android.view.ViewTreeObserver +import android.widget.LinearLayout +import io.mockk.Called +import io.mockk.MockKAnnotations +import io.mockk.Runs +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.just +import io.mockk.mockk +import io.mockk.slot +import io.mockk.verify +import kotlinx.android.synthetic.main.top_site_item.view.* +import org.junit.Before +import org.junit.Test +import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.R +import org.mozilla.fenix.home.sessioncontrol.viewholders.topsites.TopSiteItemViewHolder +import org.mozilla.fenix.perf.StartupTimelineStateMachine.StartupDestination +import org.mozilla.fenix.perf.StartupTimelineStateMachine.StartupState + +class StartupReportFullyDrawnTest { + + @MockK private lateinit var activity: HomeActivity + private lateinit var holder: TopSiteItemViewHolder + @MockK(relaxed = true) private lateinit var rootContainer: LinearLayout + @MockK(relaxed = true) private lateinit var holderItemView: View + @MockK(relaxed = true) private lateinit var viewTreeObserver: ViewTreeObserver + private lateinit var fullyDrawn: StartupReportFullyDrawn + + @Before + fun setup() { + MockKAnnotations.init(this) + every { activity.findViewById(R.id.rootContainer) } returns rootContainer + every { holderItemView.context } returns activity + every { holderItemView.top_site_item } returns mockk(relaxed = true) + holder = TopSiteItemViewHolder(holderItemView, mockk()) + every { rootContainer.viewTreeObserver } returns viewTreeObserver + every { holderItemView.viewTreeObserver } returns viewTreeObserver + + fullyDrawn = StartupReportFullyDrawn() + } + + @Test + fun testOnActivityCreateEndHome() { + // Only APP_LINK destination + fullyDrawn.onActivityCreateEndHome(StartupState.Cold(StartupDestination.UNKNOWN), activity) + fullyDrawn.onActivityCreateEndHome(StartupState.Cold(StartupDestination.HOMESCREEN), activity) + verify { activity wasNot Called } + + // Only run once + fullyDrawn.onActivityCreateEndHome(StartupState.Cold(StartupDestination.APP_LINK), activity) + verify(exactly = 1) { activity.findViewById(R.id.rootContainer) } + + fullyDrawn.onActivityCreateEndHome(StartupState.Cold(StartupDestination.APP_LINK), activity) + verify(exactly = 1) { activity.findViewById(R.id.rootContainer) } + + every { activity.reportFullyDrawn() } just Runs + triggerPreDraw() + verify { activity.reportFullyDrawn() } + } + + @Test + fun testOnTopSitesItemBound() { + fullyDrawn.onTopSitesItemBound(StartupState.Cold(StartupDestination.HOMESCREEN), holder) + + every { activity.reportFullyDrawn() } just Runs + triggerPreDraw() + verify { activity.reportFullyDrawn() } + } + + private fun triggerPreDraw() { + val listener = slot() + verify { viewTreeObserver.addOnPreDrawListener(capture(listener)) } + listener.captured.onPreDraw() + } +}