Fix Timeline not loading (#2398)

* fix cached timeline

* fix network timeline

* delete unused inc / dec extensions

* fix tests and bug in network timeline

* add db migration

* remove unused import

* commit 31.json

* improve placeholder inserting logic, add comment

* fix tests

* improve tests
This commit is contained in:
Konrad Pozniak 2022-03-28 18:39:16 +02:00 committed by GitHub
commit f2529a8e61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 938 additions and 120 deletions

View file

@ -1,10 +1,7 @@
package com.keylesspalace.tusky
import com.keylesspalace.tusky.util.dec
import com.keylesspalace.tusky.util.inc
import com.keylesspalace.tusky.util.isLessThan
import com.keylesspalace.tusky.util.isLessThanOrEqual
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
@ -38,41 +35,4 @@ class StringUtilsTest {
val notLessList = lessList.filterNot { (l, r) -> l == r }.map { (l, r) -> r to l }
notLessList.forEach { (l, r) -> assertFalse("not $l < $r", l.isLessThanOrEqual(r)) }
}
@Test
fun inc() {
listOf(
"10786565059022968z" to "107865650590229690",
"122" to "123",
"12A" to "12B",
"11z" to "120",
"0zz" to "100",
"zz" to "000",
"4zzbz" to "4zzc0",
"" to "0",
"1" to "2",
"0" to "1",
"AGdxwSQqT3pW4xrLJA" to "AGdxwSQqT3pW4xrLJB",
"AGdfqi1HnlBFVl0tkz" to "AGdfqi1HnlBFVl0tl0"
).forEach { (l, r) -> assertEquals("$l + 1 = $r", r, l.inc()) }
}
@Test
fun dec() {
listOf(
"" to "",
"107865650590229690" to "10786565059022968z",
"123" to "122",
"12B" to "12A",
"120" to "11z",
"100" to "0zz",
"000" to "zz",
"4zzc0" to "4zzbz",
"0" to "",
"2" to "1",
"1" to "0",
"AGdxwSQqT3pW4xrLJB" to "AGdxwSQqT3pW4xrLJA",
"AGdfqi1HnlBFVl0tl0" to "AGdfqi1HnlBFVl0tkz"
).forEach { (l, r) -> assertEquals("$l - 1 = $r", r, l.dec()) }
}
}

View file

@ -139,7 +139,75 @@ class CachedTimelineRemoteMediatorTest {
@Test
@ExperimentalPagingApi
fun `should refresh and insert placeholder`() {
fun `should refresh and insert placeholder when a whole page with no overlap to existing statuses is loaded`() {
val statusesAlreadyInDb = listOf(
mockStatusEntityWithAccount("3"),
mockStatusEntityWithAccount("2"),
mockStatusEntityWithAccount("1"),
)
db.insert(statusesAlreadyInDb)
val remoteMediator = CachedTimelineRemoteMediator(
accountManager = accountManager,
api = mock {
on { homeTimeline(limit = 3) } doReturn Single.just(
Response.success(
listOf(
mockStatus("8"),
mockStatus("7"),
mockStatus("5")
)
)
)
on { homeTimeline(maxId = "3", limit = 3) } doReturn Single.just(
Response.success(
listOf(
mockStatus("3"),
mockStatus("2"),
mockStatus("1")
)
)
)
},
db = db,
gson = Gson()
)
val state = state(
pages = listOf(
PagingSource.LoadResult.Page(
data = statusesAlreadyInDb,
prevKey = null,
nextKey = 0
)
),
pageSize = 3
)
val result = runBlocking { remoteMediator.load(LoadType.REFRESH, state) }
assertTrue(result is RemoteMediator.MediatorResult.Success)
assertEquals(false, (result as RemoteMediator.MediatorResult.Success).endOfPaginationReached)
db.assertStatuses(
listOf(
mockStatusEntityWithAccount("8"),
mockStatusEntityWithAccount("7"),
TimelineStatusWithAccount().apply {
status = Placeholder("5", loading = false).toEntity(1)
},
mockStatusEntityWithAccount("3"),
mockStatusEntityWithAccount("2"),
mockStatusEntityWithAccount("1"),
)
)
}
@Test
@ExperimentalPagingApi
fun `should refresh and not insert placeholder when less than a whole page is loaded`() {
val statusesAlreadyInDb = listOf(
mockStatusEntityWithAccount("3"),
@ -176,7 +244,7 @@ class CachedTimelineRemoteMediatorTest {
)
val state = state(
listOf(
pages = listOf(
PagingSource.LoadResult.Page(
data = statusesAlreadyInDb,
prevKey = null,
@ -195,9 +263,6 @@ class CachedTimelineRemoteMediatorTest {
mockStatusEntityWithAccount("8"),
mockStatusEntityWithAccount("7"),
mockStatusEntityWithAccount("5"),
TimelineStatusWithAccount().apply {
status = Placeholder("4", loading = false).toEntity(1)
},
mockStatusEntityWithAccount("3"),
mockStatusEntityWithAccount("2"),
mockStatusEntityWithAccount("1"),
@ -207,7 +272,7 @@ class CachedTimelineRemoteMediatorTest {
@Test
@ExperimentalPagingApi
fun `should refresh and not insert placeholders`() {
fun `should refresh and not insert placeholders when there is overlap with existing statuses`() {
val statusesAlreadyInDb = listOf(
mockStatusEntityWithAccount("3"),
@ -220,7 +285,7 @@ class CachedTimelineRemoteMediatorTest {
val remoteMediator = CachedTimelineRemoteMediator(
accountManager = accountManager,
api = mock {
on { homeTimeline(limit = 20) } doReturn Single.just(
on { homeTimeline(limit = 3) } doReturn Single.just(
Response.success(
listOf(
mockStatus("6"),
@ -229,7 +294,7 @@ class CachedTimelineRemoteMediatorTest {
)
)
)
on { homeTimeline(maxId = "3", limit = 20) } doReturn Single.just(
on { homeTimeline(maxId = "3", limit = 3) } doReturn Single.just(
Response.success(
listOf(
mockStatus("3"),
@ -250,7 +315,8 @@ class CachedTimelineRemoteMediatorTest {
prevKey = null,
nextKey = 0
)
)
),
pageSize = 3
)
val result = runBlocking { remoteMediator.load(LoadType.REFRESH, state) }
@ -487,11 +553,14 @@ class CachedTimelineRemoteMediatorTest {
)
}
private fun state(pages: List<PagingSource.LoadResult.Page<Int, TimelineStatusWithAccount>> = emptyList()) = PagingState(
private fun state(
pages: List<PagingSource.LoadResult.Page<Int, TimelineStatusWithAccount>> = emptyList(),
pageSize: Int = 20
) = PagingState(
pages = pages,
anchorPosition = null,
config = PagingConfig(
pageSize = 20
pageSize = pageSize
),
leadingPlaceholderCount = 0
)

View file

@ -217,8 +217,7 @@ class NetworkTimelineRemoteMediatorTest {
val newStatusData = mutableListOf(
mockStatusViewData("10"),
mockStatusViewData("9"),
mockStatusViewData("7"),
StatusViewData.Placeholder("6", false),
StatusViewData.Placeholder("7", false),
mockStatusViewData("3"),
mockStatusViewData("2"),
mockStatusViewData("1"),