move bottom sheet from fragments to activities (#628)

* move bottom sheet from fragments to activities

* move BottomSheetLogic to dedicated abstract Activity

* change tests

* improve code
This commit is contained in:
Konrad Pozniak 2018-05-06 22:05:54 +02:00 committed by GitHub
commit a2bfef3101
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 421 additions and 296 deletions

View file

@ -13,14 +13,15 @@
* You should have received a copy of the GNU General Public License along with Tusky; if not,
* see <http://www.gnu.org/licenses>. */
package com.keylesspalace.tusky.fragment
package com.keylesspalace.tusky
import android.support.design.widget.BottomSheetBehavior
import android.text.SpannedString
import android.widget.LinearLayout
import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.entity.SearchResults
import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.network.TimelineCases
import okhttp3.Request
import org.junit.Assert
import org.junit.Before
@ -35,8 +36,8 @@ import retrofit2.Callback
import retrofit2.Response
import java.util.*
class SFragmentTest {
private lateinit var fragment : FakeSFragment
class BottomSheetActivityTest {
private lateinit var activity : FakeBottomSheetActivity
private lateinit var apiMock: MastodonApi
private val accountQuery = "http://mastodon.foo.bar/@User"
private val statusQuery = "http://mastodon.foo.bar/@User/345678"
@ -85,13 +86,12 @@ class SFragmentTest {
@Before
fun setup() {
fragment = FakeSFragment()
apiMock = Mockito.mock(MastodonApi::class.java)
`when`(apiMock.search(eq(accountQuery), ArgumentMatchers.anyBoolean())).thenReturn(accountCallback)
`when`(apiMock.search(eq(statusQuery), ArgumentMatchers.anyBoolean())).thenReturn(statusCallback)
`when`(apiMock.search(eq(nonMastodonQuery), ArgumentMatchers.anyBoolean())).thenReturn(emptyCallback)
fragment.mastodonApi = apiMock
activity = FakeBottomSheetActivity(apiMock)
}
@RunWith(Parameterized::class)
@ -131,22 +131,22 @@ class SFragmentTest {
@Test
fun test() {
Assert.assertEquals(expectedResult, SFragment.looksLikeMastodonUrl(url))
Assert.assertEquals(expectedResult, looksLikeMastodonUrl(url))
}
}
@Test
fun beginEndSearch_setIsSearching_isSearchingAfterBegin() {
fragment.onBeginSearch("https://mastodon.foo.bar/@User")
Assert.assertTrue(fragment.isSearching)
activity.onBeginSearch("https://mastodon.foo.bar/@User")
Assert.assertTrue(activity.isSearching())
}
@Test
fun beginEndSearch_setIsSearching_isNotSearchingAfterEnd() {
val validUrl = "https://mastodon.foo.bar/@User"
fragment.onBeginSearch(validUrl)
fragment.onEndSearch(validUrl)
Assert.assertFalse(fragment.isSearching)
activity.onBeginSearch(validUrl)
activity.onEndSearch(validUrl)
Assert.assertFalse(activity.isSearching())
}
@Test
@ -154,18 +154,18 @@ class SFragmentTest {
val validUrl = "https://mastodon.foo.bar/@User"
val invalidUrl = ""
fragment.onBeginSearch(validUrl)
fragment.onEndSearch(invalidUrl)
Assert.assertTrue(fragment.isSearching)
activity.onBeginSearch(validUrl)
activity.onEndSearch(invalidUrl)
Assert.assertTrue(activity.isSearching())
}
@Test
fun cancelActiveSearch() {
val url = "https://mastodon.foo.bar/@User"
fragment.onBeginSearch(url)
fragment.cancelActiveSearch()
Assert.assertFalse(fragment.isSearching)
activity.onBeginSearch(url)
activity.cancelActiveSearch()
Assert.assertFalse(activity.isSearching())
}
@Test
@ -173,85 +173,84 @@ class SFragmentTest {
val firstUrl = "https://mastodon.foo.bar/@User"
val secondUrl = "https://mastodon.foo.bar/@meh"
fragment.onBeginSearch(firstUrl)
fragment.cancelActiveSearch()
activity.onBeginSearch(firstUrl)
activity.cancelActiveSearch()
fragment.onBeginSearch(secondUrl)
Assert.assertTrue(fragment.getCancelSearchRequested(firstUrl))
Assert.assertFalse(fragment.getCancelSearchRequested(secondUrl))
activity.onBeginSearch(secondUrl)
Assert.assertTrue(activity.getCancelSearchRequested(firstUrl))
Assert.assertFalse(activity.getCancelSearchRequested(secondUrl))
}
@Test
fun search_inIdealConditions_returnsRequestedResults_forAccount() {
fragment.onViewURL(accountQuery)
activity.viewUrl(accountQuery)
accountCallback.invokeCallback()
Assert.assertEquals(account.id, fragment.accountId)
Assert.assertEquals(account.id, activity.accountId)
}
@Test
fun search_inIdealConditions_returnsRequestedResults_forStatus() {
fragment.onViewURL(statusQuery)
activity.viewUrl(statusQuery)
statusCallback.invokeCallback()
Assert.assertEquals(status, fragment.status)
Assert.assertEquals(status, activity.status)
}
@Test
fun search_inIdealConditions_returnsRequestedResults_forNonMastodonURL() {
fragment.onViewURL(nonMastodonQuery)
activity.viewUrl(nonMastodonQuery)
emptyCallback.invokeCallback()
Assert.assertEquals(nonMastodonQuery, fragment.url)
Assert.assertEquals(nonMastodonQuery, activity.link)
}
@Test
fun search_withCancellation_doesNotLoadUrl_forAccount() {
fragment.onViewURL(accountQuery)
Assert.assertTrue(fragment.isSearching)
fragment.cancelActiveSearch()
Assert.assertFalse(fragment.isSearching)
activity.viewUrl(accountQuery)
Assert.assertTrue(activity.isSearching())
activity.cancelActiveSearch()
Assert.assertFalse(activity.isSearching())
accountCallback.invokeCallback()
Assert.assertEquals(null, fragment.accountId)
Assert.assertEquals(null, activity.accountId)
}
@Test
fun search_withCancellation_doesNotLoadUrl_forStatus() {
fragment.onViewURL(accountQuery)
fragment.cancelActiveSearch()
activity.viewUrl(accountQuery)
activity.cancelActiveSearch()
accountCallback.invokeCallback()
Assert.assertEquals(null, fragment.accountId)
Assert.assertEquals(null, activity.accountId)
}
@Test
fun search_withCancellation_doesNotLoadUrl_forNonMastodonURL() {
fragment.onViewURL(nonMastodonQuery)
fragment.cancelActiveSearch()
activity.viewUrl(nonMastodonQuery)
activity.cancelActiveSearch()
emptyCallback.invokeCallback()
Assert.assertEquals(null, fragment.url)
Assert.assertEquals(null, activity.searchUrl)
}
@Test
fun search_withPreviousCancellation_completes() {
// begin/cancel account search
fragment.onViewURL(accountQuery)
fragment.cancelActiveSearch()
activity.viewUrl(accountQuery)
activity.cancelActiveSearch()
// begin status search
fragment.onViewURL(statusQuery)
activity.viewUrl(statusQuery)
// return response from account search
accountCallback.invokeCallback()
// ensure that status search is still ongoing
Assert.assertTrue(fragment.isSearching)
Assert.assertTrue(activity.isSearching())
statusCallback.invokeCallback()
// ensure that the result of the status search was recorded
// and the account search wasn't
Assert.assertEquals(status, fragment.status)
Assert.assertEquals(null, fragment.accountId)
Assert.assertEquals(status, activity.status)
Assert.assertEquals(null, activity.accountId)
}
class FakeSearchResults : Call<SearchResults>
{
class FakeSearchResults : Call<SearchResults> {
private var searchResults: SearchResults
private var callback: Callback<SearchResults>? = null
@ -283,29 +282,33 @@ class SFragmentTest {
override fun request(): Request { throw NotImplementedError() }
}
class FakeSFragment : SFragment() {
class FakeBottomSheetActivity(val api: MastodonApi) : BottomSheetActivity() {
var status: Status? = null
var accountId: String? = null
var url: String? = null
var link: String? = null
init {
callList = mutableListOf()
@Suppress("UNCHECKED_CAST")
bottomSheet = Mockito.mock(BottomSheetBehavior::class.java) as BottomSheetBehavior<LinearLayout>
callList = arrayListOf()
}
override fun getMastodonApi(): MastodonApi {
return api
}
override fun openLink(url: String) {
this.url = url
this.link = url
}
override fun viewAccount(id: String?) {
accountId = id
override fun viewAccount(id: String) {
this.accountId = id
}
override fun viewThread(status: Status?) {
override fun viewThread(status: Status) {
this.status = status
}
override fun removeItem(position: Int) { throw NotImplementedError() }
override fun removeAllByAccountId(accountId: String?) { throw NotImplementedError() }
override fun timelineCases(): TimelineCases { throw NotImplementedError() }
}
}