1
0
Fork 0

Add tests for Bookmarks DiffUtil and ViewHolders.

master
Kainalu Hagiwara 2020-08-05 10:00:54 -07:00 committed by Jeff Boek
parent 6d8cfe1a50
commit b1db1cf976
5 changed files with 305 additions and 3 deletions

View File

@ -7,6 +7,7 @@ package org.mozilla.fenix.library.bookmarks
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.annotation.VisibleForTesting
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -49,7 +50,8 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto
diffUtil.dispatchUpdatesTo(this) diffUtil.dispatchUpdatesTo(this)
} }
private class BookmarkDiffUtil( @VisibleForTesting
internal class BookmarkDiffUtil(
val old: List<BookmarkNode>, val old: List<BookmarkNode>,
val new: List<BookmarkNode>, val new: List<BookmarkNode>,
val oldMode: BookmarkFragmentState.Mode, val oldMode: BookmarkFragmentState.Mode,

View File

@ -4,6 +4,7 @@
package org.mozilla.fenix.library.bookmarks.viewholders package org.mozilla.fenix.library.bookmarks.viewholders
import androidx.annotation.VisibleForTesting
import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.storage.BookmarkNode
import org.mozilla.fenix.ext.hideAndDisable import org.mozilla.fenix.ext.hideAndDisable
import org.mozilla.fenix.ext.showAndEnable import org.mozilla.fenix.ext.showAndEnable
@ -66,7 +67,8 @@ class BookmarkItemViewHolder(
setSelectionListeners(item, selectionHolder) setSelectionListeners(item, selectionHolder)
} }
private fun setColorsAndIcons(url: String?) { @VisibleForTesting
internal fun setColorsAndIcons(url: String?) {
if (url != null && url.startsWith("http")) { if (url != null && url.startsWith("http")) {
containerView.loadFavicon(url) containerView.loadFavicon(url)
} else { } else {

View File

@ -9,6 +9,8 @@ import io.mockk.spyk
import io.mockk.verifyOrder import io.mockk.verifyOrder
import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.storage.BookmarkNode
import mozilla.components.concept.storage.BookmarkNodeType import mozilla.components.concept.storage.BookmarkNodeType
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@ -19,6 +21,16 @@ internal class BookmarkAdapterTest {
private lateinit var bookmarkAdapter: BookmarkAdapter private lateinit var bookmarkAdapter: BookmarkAdapter
private val item = BookmarkNode(
BookmarkNodeType.ITEM,
"456",
"123",
0,
"Mozilla",
"http://mozilla.org",
null
)
@Before @Before
fun setup() { fun setup() {
bookmarkAdapter = spyk( bookmarkAdapter = spyk(
@ -30,7 +42,7 @@ internal class BookmarkAdapterTest {
fun `update adapter from tree of bookmark nodes, null tree returns empty list`() { fun `update adapter from tree of bookmark nodes, null tree returns empty list`() {
val tree = BookmarkNode( val tree = BookmarkNode(
BookmarkNodeType.FOLDER, "123", null, 0, "Mobile", null, listOf( BookmarkNodeType.FOLDER, "123", null, 0, "Mobile", null, listOf(
BookmarkNode(BookmarkNodeType.ITEM, "456", "123", 0, "Mozilla", "http://mozilla.org", null), item,
BookmarkNode(BookmarkNodeType.SEPARATOR, "789", "123", 1, null, null, null), BookmarkNode(BookmarkNodeType.SEPARATOR, "789", "123", 1, null, null, null),
BookmarkNode( BookmarkNode(
BookmarkNodeType.ITEM, BookmarkNodeType.ITEM,
@ -52,4 +64,52 @@ internal class BookmarkAdapterTest {
bookmarkAdapter.notifyItemRangeRemoved(0, 3) bookmarkAdapter.notifyItemRangeRemoved(0, 3)
} }
} }
@Test
fun `items are the same if they have the same guids`() {
assertTrue(createSingleItemDiffUtil(item, item).areItemsTheSame(0, 0))
assertTrue(
createSingleItemDiffUtil(
item,
item.copy(title = "Wikipedia.org", url = "https://www.wikipedia.org")
).areItemsTheSame(0, 0)
)
assertFalse(
createSingleItemDiffUtil(
item,
item.copy(guid = "111")
).areItemsTheSame(0, 0)
)
}
@Test
fun `equal items have same contents unless their selected state changes`() {
assertTrue(createSingleItemDiffUtil(item, item).areContentsTheSame(0, 0))
assertFalse(
createSingleItemDiffUtil(item, item.copy(position = 1)).areContentsTheSame(0, 0)
)
assertFalse(
createSingleItemDiffUtil(
item,
item,
oldMode = BookmarkFragmentState.Mode.Selecting(setOf(item))
).areContentsTheSame(0, 0)
)
assertFalse(
createSingleItemDiffUtil(
item,
item,
newMode = BookmarkFragmentState.Mode.Selecting(setOf(item))
).areContentsTheSame(0, 0)
)
}
private fun createSingleItemDiffUtil(
oldItem: BookmarkNode,
newItem: BookmarkNode,
oldMode: BookmarkFragmentState.Mode = BookmarkFragmentState.Mode.Normal(),
newMode: BookmarkFragmentState.Mode = BookmarkFragmentState.Mode.Normal()
): BookmarkAdapter.BookmarkDiffUtil {
return BookmarkAdapter.BookmarkDiffUtil(listOf(oldItem), listOf(newItem), oldMode, newMode)
}
} }

View File

@ -0,0 +1,91 @@
/* 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.library.bookmarks.viewholders
import androidx.appcompat.content.res.AppCompatResources
import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.verify
import mozilla.components.concept.storage.BookmarkNode
import mozilla.components.concept.storage.BookmarkNodeType
import org.junit.Before
import org.junit.Test
import org.mozilla.fenix.ext.hideAndDisable
import org.mozilla.fenix.ext.showAndEnable
import org.mozilla.fenix.library.LibrarySiteItemView
import org.mozilla.fenix.library.SelectionHolder
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentInteractor
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState
import org.mozilla.fenix.library.bookmarks.BookmarkPayload
class BookmarkFolderViewHolderTest {
@MockK
private lateinit var interactor: BookmarkFragmentInteractor
@MockK(relaxed = true)
private lateinit var siteItemView: LibrarySiteItemView
@MockK(relaxed = true)
private lateinit var selectionHolder: SelectionHolder<BookmarkNode>
private lateinit var holder: BookmarkFolderViewHolder
private val folder = BookmarkNode(
type = BookmarkNodeType.FOLDER,
guid = "456",
parentGuid = "123",
position = 0,
title = "Folder",
url = null,
children = listOf()
)
@Before
fun setup() {
MockKAnnotations.init(this)
mockkStatic(AppCompatResources::class)
every { AppCompatResources.getDrawable(any(), any()) } returns mockk(relaxed = true)
holder = BookmarkFolderViewHolder(siteItemView, interactor, selectionHolder)
}
@Test
fun `binds title and selected state`() {
holder.bind(folder, BookmarkFragmentState.Mode.Normal())
verify {
siteItemView.titleView.text = folder.title
siteItemView.overflowView.showAndEnable()
siteItemView.changeSelected(false)
}
every { selectionHolder.selectedItems } returns setOf(folder)
holder.bind(folder, BookmarkFragmentState.Mode.Selecting(setOf(folder)))
verify {
siteItemView.titleView.text = folder.title
siteItemView.overflowView.hideAndDisable()
siteItemView.changeSelected(true)
}
}
@Test
fun `bind with payload of no changes does not rebind views`() {
holder.bind(
folder,
BookmarkFragmentState.Mode.Normal(),
BookmarkPayload(false, false, false, false)
)
verify(inverse = true) {
siteItemView.titleView.text = folder.title
siteItemView.overflowView.showAndEnable()
siteItemView.overflowView.hideAndDisable()
siteItemView.changeSelected(any())
}
}
}

View File

@ -0,0 +1,147 @@
/* 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.library.bookmarks.viewholders
import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.verify
import mozilla.components.concept.storage.BookmarkNode
import mozilla.components.concept.storage.BookmarkNodeType
import org.junit.Before
import org.junit.Test
import org.mozilla.fenix.ext.hideAndDisable
import org.mozilla.fenix.ext.showAndEnable
import org.mozilla.fenix.library.LibrarySiteItemView
import org.mozilla.fenix.library.SelectionHolder
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentInteractor
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState
import org.mozilla.fenix.library.bookmarks.BookmarkPayload
class BookmarkItemViewHolderTest {
@MockK
private lateinit var interactor: BookmarkFragmentInteractor
@MockK(relaxed = true)
private lateinit var siteItemView: LibrarySiteItemView
@MockK(relaxed = true)
private lateinit var selectionHolder: SelectionHolder<BookmarkNode>
private lateinit var holder: BookmarkItemViewHolder
private val item = BookmarkNode(
type = BookmarkNodeType.ITEM,
guid = "456",
parentGuid = "123",
position = 0,
title = "Mozilla",
url = "https://www.mozilla.org",
children = listOf()
)
@Before
fun setup() {
MockKAnnotations.init(this)
holder = BookmarkItemViewHolder(siteItemView, interactor, selectionHolder)
}
@Test
fun `binds views for unselected item`() {
holder.bind(item, BookmarkFragmentState.Mode.Normal())
verify {
siteItemView.setSelectionInteractor(item, selectionHolder, interactor)
siteItemView.titleView.text = item.title
siteItemView.urlView.text = item.url
siteItemView.overflowView.showAndEnable()
siteItemView.changeSelected(false)
holder.setColorsAndIcons(item.url)
}
}
@Test
fun `binds views for selected item`() {
every { selectionHolder.selectedItems } returns setOf(item)
holder.bind(item, BookmarkFragmentState.Mode.Selecting(setOf(item)))
verify {
siteItemView.setSelectionInteractor(item, selectionHolder, interactor)
siteItemView.titleView.text = item.title
siteItemView.urlView.text = item.url
siteItemView.overflowView.hideAndDisable()
siteItemView.changeSelected(true)
holder.setColorsAndIcons(item.url)
}
}
@Test
fun `bind with payload of no changes does not rebind views`() {
holder.bind(
item,
BookmarkFragmentState.Mode.Normal(),
BookmarkPayload(false, false, false, false)
)
verify(inverse = true) {
siteItemView.titleView.text = item.title
siteItemView.urlView.text = item.url
siteItemView.overflowView.showAndEnable()
siteItemView.overflowView.hideAndDisable()
siteItemView.changeSelected(any())
holder.setColorsAndIcons(item.url)
}
}
@Test
fun `binding an item with a null title uses the url as the title`() {
val item = item.copy(title = null)
holder.bind(item, BookmarkFragmentState.Mode.Normal())
verify { siteItemView.titleView.text = item.url }
}
@Test
fun `binding an item with a blank title uses the url as the title`() {
val item = item.copy(title = " ")
holder.bind(item, BookmarkFragmentState.Mode.Normal())
verify { siteItemView.titleView.text = item.url }
}
@Test
fun `rebinds title if item title is null and the item url has changed`() {
val item = item.copy(title = null)
holder.bind(
item,
BookmarkFragmentState.Mode.Normal(),
BookmarkPayload(
titleChanged = false,
urlChanged = true,
selectedChanged = false,
modeChanged = false
)
)
verify { siteItemView.titleView.text = item.url }
}
@Test
fun `rebinds title if item title is blank and the item url has changed`() {
val item = item.copy(title = " ")
holder.bind(
item,
BookmarkFragmentState.Mode.Normal(),
BookmarkPayload(
titleChanged = false,
urlChanged = true,
selectedChanged = false,
modeChanged = false
)
)
verify { siteItemView.titleView.text = item.url }
}
}