Unverified Commit 67ce5ad5 authored by Tiger Oakes's avatar Tiger Oakes Committed by GitHub
Browse files

Add tests for onboarding viewholders (#11522)

parent cf94906e
Loading
Loading
Loading
Loading
+37 −31
Original line number Diff line number Diff line
@@ -5,12 +5,14 @@
package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding

import android.view.View
import android.widget.Button
import androidx.annotation.VisibleForTesting
import androidx.appcompat.content.res.AppCompatResources.getDrawable
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.onboarding_automatic_signin.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import mozilla.components.service.fxa.manager.SignInWithShareableAccountResult
import mozilla.components.service.fxa.sharing.ShareableAccount
@@ -20,36 +22,51 @@ import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components

class OnboardingAutomaticSignInViewHolder(view: View) : RecyclerView.ViewHolder(view) {
class OnboardingAutomaticSignInViewHolder(
    view: View,
    private val scope: CoroutineScope = MainScope()
) : RecyclerView.ViewHolder(view) {

    private lateinit var shareableAccount: ShareableAccount
    private val headerText = view.header_text

    init {
        view.turn_on_sync_button.setOnClickListener {
            it.context.components.analytics.metrics.track(Event.OnboardingAutoSignIn)
            scope.launch {
                onClick(it.turn_on_sync_button)
            }
        }
    }

            it.turn_on_sync_button.text = it.context.getString(
                R.string.onboarding_firefox_account_signing_in
    fun bind(account: ShareableAccount) {
        shareableAccount = account
        headerText.text = itemView.context.getString(
            R.string.onboarding_firefox_account_auto_signin_header_2, account.email
        )
            it.turn_on_sync_button.isEnabled = false
        val icon = getDrawable(itemView.context, R.drawable.ic_onboarding_avatar_anonymous)
        headerText.putCompoundDrawablesRelativeWithIntrinsicBounds(start = icon)
    }

    @VisibleForTesting
    internal suspend fun onClick(button: Button) {
        val context = button.context
        context.components.analytics.metrics.track(Event.OnboardingAutoSignIn)

        button.text = context.getString(R.string.onboarding_firefox_account_signing_in)
        button.isEnabled = false

            CoroutineScope(Dispatchers.Main).launch {
                val result = view.context.components.backgroundServices.accountManager
                    .signInWithShareableAccountAsync(shareableAccount).await()
                when (result) {
        val accountManager = context.components.backgroundServices.accountManager
        when (accountManager.signInWithShareableAccountAsync(shareableAccount).await()) {
            SignInWithShareableAccountResult.Failure -> {
                // Failed to sign-in (e.g. bad credentials). Allow to try again.
                        it.turn_on_sync_button.text = it.context.getString(
                            R.string.onboarding_firefox_account_auto_signin_confirm
                        )
                        it.turn_on_sync_button.isEnabled = true
                button.text = context.getString(R.string.onboarding_firefox_account_auto_signin_confirm)
                button.isEnabled = true
                FenixSnackbar.make(
                            view = it,
                    view = button,
                    duration = Snackbar.LENGTH_SHORT,
                    isDisplayedWithBrowserToolbar = false
                ).setText(
                            it.context.getString(R.string.onboarding_firefox_account_automatic_signin_failed)
                    context.getString(R.string.onboarding_firefox_account_automatic_signin_failed)
                ).show()
            }
            SignInWithShareableAccountResult.WillRetry, SignInWithShareableAccountResult.Success -> {
@@ -57,17 +74,6 @@ class OnboardingAutomaticSignInViewHolder(view: View) : RecyclerView.ViewHolder(
            }
        }
    }
        }
    }

    fun bind(account: ShareableAccount) {
        shareableAccount = account
        headerText.text = itemView.context.getString(
            R.string.onboarding_firefox_account_auto_signin_header_2, account.email
        )
        val icon = getDrawable(itemView.context, R.drawable.ic_onboarding_avatar_anonymous)
        headerText.putCompoundDrawablesRelativeWithIntrinsicBounds(start = icon)
    }

    companion object {
        const val LAYOUT_ID = R.layout.onboarding_automatic_signin
+1 −1
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ import mozilla.components.feature.pwa.WebAppShortcutManager
class TestCore(context: Context) : Core(context) {

    override val engine = mockk<Engine>(relaxed = true) {
        every { this@mockk getProperty "settings" } returns mockk<Settings>()
        every { this@mockk getProperty "settings" } returns mockk<Settings>(relaxed = true)
    }
    override val sessionManager = SessionManager(engine)
    override val store = mockk<BrowserStore>()
+105 −0
Original line number Diff line number Diff line
/* 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.home.sessioncontrol.viewholders.onboarding

import android.view.LayoutInflater
import android.view.View
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.unmockkObject
import io.mockk.verify
import kotlinx.android.synthetic.main.onboarding_automatic_signin.view.*
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runBlockingTest
import mozilla.components.service.fxa.manager.SignInWithShareableAccountResult
import mozilla.components.service.fxa.sharing.ShareableAccount
import mozilla.components.support.test.robolectric.testContext
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.components.BackgroundServices
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner

@ExperimentalCoroutinesApi
@RunWith(FenixRobolectricTestRunner::class)
class OnboardingAutomaticSignInViewHolderTest {

    private lateinit var view: View
    private lateinit var backgroundServices: BackgroundServices
    private lateinit var snackbar: FenixSnackbar

    @Before
    fun setup() {
        view = LayoutInflater.from(testContext)
            .inflate(OnboardingAutomaticSignInViewHolder.LAYOUT_ID, null)
        snackbar = mockk(relaxed = true)
        mockkObject(FenixSnackbar.Companion)

        backgroundServices = testContext.components.backgroundServices
        every { FenixSnackbar.make(any(), any(), any(), any()) } returns snackbar
    }

    @After
    fun teardown() {
        unmockkObject(FenixSnackbar.Companion)
    }

    @Test
    fun `bind updates header text`() {
        val holder = OnboardingAutomaticSignInViewHolder(view)
        holder.bind(mockk {
            every { email } returns "email@example.com"
        })
        assertEquals(
            "You are signed in as email@example.com on another Firefox browser on this phone. Would you like to sign in with this account?",
            view.header_text.text
        )
        assertTrue(view.turn_on_sync_button.isEnabled)
    }

    @Test
    fun `sign in on click`() = runBlocking {
        val account = mockk<ShareableAccount> {
            every { email } returns "email@example.com"
        }
        every {
            backgroundServices.accountManager.signInWithShareableAccountAsync(account)
        } returns CompletableDeferred(SignInWithShareableAccountResult.Success)

        val holder = OnboardingAutomaticSignInViewHolder(view, scope = this)
        holder.bind(account)
        holder.onClick(view.turn_on_sync_button)

        assertEquals("Signing in…", view.turn_on_sync_button.text)
        assertFalse(view.turn_on_sync_button.isEnabled)
    }

    @Test
    fun `show error if sign in fails`() = runBlockingTest {
        val account = mockk<ShareableAccount> {
            every { email } returns "email@example.com"
        }
        every {
            backgroundServices.accountManager.signInWithShareableAccountAsync(account)
        } returns CompletableDeferred(SignInWithShareableAccountResult.Failure)

        val holder = OnboardingAutomaticSignInViewHolder(view, scope = this)
        holder.bind(account)
        holder.onClick(view.turn_on_sync_button)

        assertEquals("Yes, sign me in", view.turn_on_sync_button.text)
        assertTrue(view.turn_on_sync_button.isEnabled)
        verify { snackbar.setText("Failed to sign-in") }
    }
}
+39 −0
Original line number Diff line number Diff line
/* 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.home.sessioncontrol.viewholders.onboarding

import android.view.LayoutInflater
import android.view.View
import io.mockk.mockk
import io.mockk.verify
import kotlinx.android.synthetic.main.onboarding_finish.view.*
import mozilla.components.support.test.robolectric.testContext
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.home.sessioncontrol.OnboardingInteractor

@RunWith(FenixRobolectricTestRunner::class)
class OnboardingFinishViewHolderTest {

    private lateinit var view: View
    private lateinit var interactor: OnboardingInteractor

    @Before
    fun setup() {
        view = LayoutInflater.from(testContext)
            .inflate(OnboardingFinishViewHolder.LAYOUT_ID, null)
        interactor = mockk(relaxed = true)
    }

    @Test
    fun `call interactor on click`() {
        OnboardingFinishViewHolder(view, interactor)

        view.finish_button.performClick()
        verify { interactor.onStartBrowsingClicked() }
    }
}
+34 −0
Original line number Diff line number Diff line
/* 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.home.sessioncontrol.viewholders.onboarding

import android.view.LayoutInflater
import android.view.View
import kotlinx.android.synthetic.main.onboarding_header.view.*
import mozilla.components.support.test.robolectric.testContext
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner

@RunWith(FenixRobolectricTestRunner::class)
class OnboardingHeaderViewHolderTest {

    private lateinit var view: View

    @Before
    fun setup() {
        view = LayoutInflater.from(testContext)
            .inflate(OnboardingHeaderViewHolder.LAYOUT_ID, null)
    }

    @Test
    fun `bind header text`() {
        OnboardingHeaderViewHolder(view)

        assertEquals("Welcome to Firefox Preview!", view.header_text.text)
    }
}
Loading