Add tests for exceptions
parent
236b981881
commit
9ae1aa6f16
|
@ -14,19 +14,13 @@ import org.mozilla.fenix.exceptions.viewholders.ExceptionsDeleteButtonViewHolder
|
|||
import org.mozilla.fenix.exceptions.viewholders.ExceptionsHeaderViewHolder
|
||||
import org.mozilla.fenix.exceptions.viewholders.ExceptionsListItemViewHolder
|
||||
|
||||
sealed class AdapterItem {
|
||||
object DeleteButton : AdapterItem()
|
||||
object Header : AdapterItem()
|
||||
data class Item(val item: TrackingProtectionException) : AdapterItem()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapter for a list of sites that are exempted from Tracking Protection,
|
||||
* along with controls to remove the exception.
|
||||
*/
|
||||
class ExceptionsAdapter(
|
||||
private val interactor: ExceptionsInteractor
|
||||
) : ListAdapter<AdapterItem, RecyclerView.ViewHolder>(DiffCallback) {
|
||||
) : ListAdapter<ExceptionsAdapter.AdapterItem, RecyclerView.ViewHolder>(DiffCallback) {
|
||||
|
||||
/**
|
||||
* Change the list of items that are displayed.
|
||||
|
@ -67,6 +61,12 @@ class ExceptionsAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
sealed class AdapterItem {
|
||||
object DeleteButton : AdapterItem()
|
||||
object Header : AdapterItem()
|
||||
data class Item(val item: TrackingProtectionException) : AdapterItem()
|
||||
}
|
||||
|
||||
private object DiffCallback : DiffUtil.ItemCallback<AdapterItem>() {
|
||||
override fun areItemsTheSame(oldItem: AdapterItem, newItem: AdapterItem) =
|
||||
areContentsTheSame(oldItem, newItem)
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.mozilla.fenix.settings.SupportUtils
|
|||
* along with controls to remove the exception.
|
||||
*/
|
||||
class ExceptionsFragment : Fragment() {
|
||||
|
||||
private lateinit var exceptionsStore: ExceptionsFragmentStore
|
||||
private lateinit var exceptionsView: ExceptionsView
|
||||
private lateinit var exceptionsInteractor: ExceptionsInteractor
|
||||
|
@ -48,7 +49,7 @@ class ExceptionsFragment : Fragment() {
|
|||
exceptionsStore = StoreProvider.get(this) {
|
||||
ExceptionsFragmentStore(
|
||||
ExceptionsFragmentState(
|
||||
items = listOf()
|
||||
items = emptyList()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -61,7 +62,6 @@ class ExceptionsFragment : Fragment() {
|
|||
|
||||
@ExperimentalCoroutinesApi
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
consumeFrom(exceptionsStore) {
|
||||
exceptionsView.update(it)
|
||||
}
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
|
||||
package org.mozilla.fenix.exceptions
|
||||
|
||||
import android.text.SpannableString
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.style.UnderlineSpan
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.text.toSpannable
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.component_exceptions.view.*
|
||||
import kotlinx.android.synthetic.main.component_exceptions.*
|
||||
import mozilla.components.concept.engine.content.blocking.TrackingProtectionException
|
||||
import org.mozilla.fenix.R
|
||||
|
||||
|
@ -42,35 +42,36 @@ interface ExceptionsViewInteractor {
|
|||
* View that contains and configures the Exceptions List
|
||||
*/
|
||||
class ExceptionsView(
|
||||
override val containerView: ViewGroup,
|
||||
val interactor: ExceptionsInteractor
|
||||
container: ViewGroup,
|
||||
interactor: ExceptionsInteractor
|
||||
) : LayoutContainer {
|
||||
|
||||
val view: FrameLayout = LayoutInflater.from(containerView.context)
|
||||
.inflate(R.layout.component_exceptions, containerView, true)
|
||||
override val containerView: FrameLayout = LayoutInflater.from(container.context)
|
||||
.inflate(R.layout.component_exceptions, container, true)
|
||||
.findViewById(R.id.exceptions_wrapper)
|
||||
|
||||
private val exceptionsAdapter = ExceptionsAdapter(interactor)
|
||||
|
||||
init {
|
||||
view.exceptions_list.apply {
|
||||
exceptions_list.apply {
|
||||
adapter = exceptionsAdapter
|
||||
layoutManager = LinearLayoutManager(containerView.context)
|
||||
layoutManager = LinearLayoutManager(container.context)
|
||||
}
|
||||
val learnMoreText = view.exceptions_learn_more.text.toString()
|
||||
val textWithLink = SpannableString(learnMoreText).apply {
|
||||
setSpan(UnderlineSpan(), 0, learnMoreText.length, 0)
|
||||
}
|
||||
with(view.exceptions_learn_more) {
|
||||
|
||||
with(exceptions_learn_more) {
|
||||
val learnMoreText = text
|
||||
text = learnMoreText.toSpannable().apply {
|
||||
setSpan(UnderlineSpan(), 0, learnMoreText.length, 0)
|
||||
}
|
||||
|
||||
movementMethod = LinkMovementMethod.getInstance()
|
||||
text = textWithLink
|
||||
setOnClickListener { interactor.onLearnMore() }
|
||||
}
|
||||
}
|
||||
|
||||
fun update(state: ExceptionsFragmentState) {
|
||||
view.exceptions_empty_view.isVisible = state.items.isEmpty()
|
||||
view.exceptions_list.isVisible = state.items.isNotEmpty()
|
||||
exceptions_empty_view.isVisible = state.items.isEmpty()
|
||||
exceptions_list.isVisible = state.items.isNotEmpty()
|
||||
exceptionsAdapter.updateData(state.items)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/* 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.exceptions
|
||||
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.exceptions.viewholders.ExceptionsDeleteButtonViewHolder
|
||||
import org.mozilla.fenix.exceptions.viewholders.ExceptionsHeaderViewHolder
|
||||
import org.mozilla.fenix.exceptions.viewholders.ExceptionsListItemViewHolder
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class ExceptionsAdapterTest {
|
||||
|
||||
private lateinit var interactor: ExceptionsInteractor
|
||||
private lateinit var adapter: ExceptionsAdapter
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
interactor = mockk()
|
||||
adapter = ExceptionsAdapter(interactor)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `binds header and delete button with other adapter items`() = runBlockingTest {
|
||||
adapter.updateData(listOf(mockk(), mockk()))
|
||||
|
||||
assertEquals(4, adapter.itemCount)
|
||||
assertEquals(ExceptionsHeaderViewHolder.LAYOUT_ID, adapter.getItemViewType(0))
|
||||
assertEquals(ExceptionsListItemViewHolder.LAYOUT_ID, adapter.getItemViewType(1))
|
||||
assertEquals(ExceptionsListItemViewHolder.LAYOUT_ID, adapter.getItemViewType(2))
|
||||
assertEquals(ExceptionsDeleteButtonViewHolder.LAYOUT_ID, adapter.getItemViewType(3))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/* 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.exceptions
|
||||
|
||||
import android.text.Spannable
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.isVisible
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkConstructor
|
||||
import io.mockk.unmockkConstructor
|
||||
import io.mockk.verify
|
||||
import kotlinx.android.synthetic.main.component_exceptions.*
|
||||
import mozilla.components.concept.engine.content.blocking.TrackingProtectionException
|
||||
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.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class ExceptionsViewTest {
|
||||
|
||||
private lateinit var container: ViewGroup
|
||||
private lateinit var interactor: ExceptionsInteractor
|
||||
private lateinit var exceptionsView: ExceptionsView
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockkConstructor(ExceptionsAdapter::class)
|
||||
container = FrameLayout(testContext)
|
||||
interactor = mockk()
|
||||
|
||||
exceptionsView = ExceptionsView(container, interactor)
|
||||
every { anyConstructed<ExceptionsAdapter>().updateData(any()) } just Runs
|
||||
}
|
||||
|
||||
@After
|
||||
fun teardown() {
|
||||
unmockkConstructor(ExceptionsAdapter::class)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `binds exception text`() {
|
||||
assertTrue(exceptionsView.exceptions_learn_more.movementMethod is LinkMovementMethod)
|
||||
assertTrue(exceptionsView.exceptions_learn_more.text is Spannable)
|
||||
assertEquals("Learn more", exceptionsView.exceptions_learn_more.text.toString())
|
||||
|
||||
every { interactor.onLearnMore() } just Runs
|
||||
exceptionsView.exceptions_learn_more.performClick()
|
||||
verify { interactor.onLearnMore() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `binds empty list to adapter`() {
|
||||
exceptionsView.update(ExceptionsFragmentState(emptyList()))
|
||||
|
||||
assertTrue(exceptionsView.exceptions_empty_view.isVisible)
|
||||
assertFalse(exceptionsView.exceptions_list.isVisible)
|
||||
verify { anyConstructed<ExceptionsAdapter>().updateData(emptyList()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `binds list with items to adapter`() {
|
||||
val items = listOf<TrackingProtectionException>(mockk(), mockk())
|
||||
exceptionsView.update(ExceptionsFragmentState(items))
|
||||
|
||||
assertFalse(exceptionsView.exceptions_empty_view.isVisible)
|
||||
assertTrue(exceptionsView.exceptions_list.isVisible)
|
||||
verify { anyConstructed<ExceptionsAdapter>().updateData(items) }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/* 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.exceptions.viewholders
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import kotlinx.android.synthetic.main.delete_exceptions_button.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.R
|
||||
import org.mozilla.fenix.exceptions.ExceptionsInteractor
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class ExceptionsDeleteButtonViewHolderTest {
|
||||
|
||||
private lateinit var view: View
|
||||
private lateinit var interactor: ExceptionsInteractor
|
||||
private lateinit var viewHolder: ExceptionsDeleteButtonViewHolder
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val appCompatContext = ContextThemeWrapper(testContext, R.style.NormalTheme)
|
||||
view = LayoutInflater.from(appCompatContext)
|
||||
.inflate(ExceptionsDeleteButtonViewHolder.LAYOUT_ID, null)
|
||||
interactor = mockk(relaxed = true)
|
||||
viewHolder = ExceptionsDeleteButtonViewHolder(view, interactor)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `calls onDeleteAll on click`() {
|
||||
view.removeAllExceptions.performClick()
|
||||
|
||||
verify { interactor.onDeleteAll() }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* 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.exceptions.viewholders
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import kotlinx.android.synthetic.main.exception_item.view.*
|
||||
import mozilla.components.concept.engine.content.blocking.TrackingProtectionException
|
||||
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.exceptions.ExceptionsInteractor
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class ExceptionsListItemViewHolderTest {
|
||||
|
||||
private lateinit var view: View
|
||||
private lateinit var interactor: ExceptionsInteractor
|
||||
private lateinit var viewHolder: ExceptionsListItemViewHolder
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
view = LayoutInflater.from(testContext)
|
||||
.inflate(ExceptionsListItemViewHolder.LAYOUT_ID, null)
|
||||
interactor = mockk(relaxed = true)
|
||||
viewHolder = ExceptionsListItemViewHolder(view, interactor)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `bind url and icon`() {
|
||||
val exception = object : TrackingProtectionException {
|
||||
override val url = "https://example.com/icon.svg"
|
||||
}
|
||||
viewHolder.bind(exception)
|
||||
|
||||
assertEquals(exception.url, view.webAddressView.text)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `calls onDeleteOne on click`() {
|
||||
val exception = object : TrackingProtectionException {
|
||||
override val url = "https://example.com/icon.svg"
|
||||
}
|
||||
viewHolder.bind(exception)
|
||||
view.delete_exception.performClick()
|
||||
|
||||
verify { interactor.onDeleteOne(exception) }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue