Repository Unit Tests #50
@ -37,6 +37,9 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
||||
var badgeStarred = 0
|
||||
set(value) {field = if (value < 0) { 0 } else { value } }
|
||||
|
||||
private var fetchedSources = false
|
||||
private var fetchedTags = false
|
||||
|
||||
AmineB marked this conversation as resolved
Outdated
|
||||
init {
|
||||
// TODO: Dispatchers.IO not available in KMM, an alternative solution should be found
|
||||
runBlocking {
|
||||
@ -144,13 +147,17 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
||||
}
|
||||
|
||||
suspend fun getTags(): List<SelfossModel.Tag> {
|
||||
return if (isNetworkAvailable()) {
|
||||
val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
|
||||
return if (isNetworkAvailable() && !fetchedTags) {
|
||||
val apiTags = api.tags()
|
||||
if (apiTags.success && apiTags.data != null && (appSettingsService.isItemCachingEnabled() || appSettingsService.isUpdateSourcesEnabled())) {
|
||||
if (apiTags.success && apiTags.data != null && isDatabaseEnabled) {
|
||||
resetDBTagsWithData(apiTags.data)
|
||||
if (!appSettingsService.isUpdateSourcesEnabled()) {
|
||||
fetchedTags = true
|
||||
}
|
||||
}
|
||||
apiTags.data ?: emptyList()
|
||||
} else if (appSettingsService.isItemCachingEnabled() || appSettingsService.isUpdateSourcesEnabled()) {
|
||||
} else if (isDatabaseEnabled) {
|
||||
getDBTags().map { it.toView() }
|
||||
} else {
|
||||
emptyList()
|
||||
@ -172,13 +179,17 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
||||
}
|
||||
|
||||
suspend fun getSources(): ArrayList<SelfossModel.Source> {
|
||||
return if (isNetworkAvailable()) {
|
||||
val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
|
||||
return if (isNetworkAvailable() && !fetchedSources) {
|
||||
val apiSources = api.sources()
|
||||
if (apiSources.success && apiSources.data != null && (appSettingsService.isItemCachingEnabled() || appSettingsService.isUpdateSourcesEnabled())) {
|
||||
if (apiSources.success && apiSources.data != null && isDatabaseEnabled) {
|
||||
resetDBSourcesWithData(apiSources.data)
|
||||
if (!appSettingsService.isUpdateSourcesEnabled()) {
|
||||
fetchedSources = true
|
||||
}
|
||||
}
|
||||
apiSources.data ?: ArrayList()
|
||||
} else if (appSettingsService.isItemCachingEnabled() || appSettingsService.isUpdateSourcesEnabled()) {
|
||||
} else if (isDatabaseEnabled) {
|
||||
ArrayList(getDBSources().map { it.toView() })
|
||||
} else {
|
||||
ArrayList()
|
||||
|
@ -342,12 +342,35 @@ class RepositoryTest() {
|
||||
testTags = repository.getTags()
|
||||
}
|
||||
|
||||
coVerify(exactly = 1) { api.tags() }
|
||||
assertNotSame(tags, testTags)
|
||||
assertContentEquals(tagsDB.map { it.toView() }, testTags)
|
||||
coVerify(exactly = 1) { api.tags() }
|
||||
verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get tags with items caching disabled`() {
|
||||
AmineB marked this conversation as resolved
Outdated
AmineB
commented
Why is this called twice ? Why is this called twice ?
davidoskky
commented
To test that api.tags() gets called only once regardless of how many calls are made to the repository. To test that api.tags() gets called only once regardless of how many calls are made to the repository.
|
||||
val tags = listOf(SelfossModel.Tag("test", "red", 6),
|
||||
SelfossModel.Tag("second", "yellow", 0))
|
||||
val tagsDB = listOf(TAG("test_DB", "red", 6),
|
||||
TAG("second_DB", "yellow", 0))
|
||||
|
||||
coEvery { api.tags() } returns SelfossModel.StatusAndData(success = true, data = tags)
|
||||
coEvery { db.tagsQueries.tags().executeAsList() } returns tagsDB
|
||||
every { appSettingsService.isUpdateSourcesEnabled() } returns true
|
||||
every { appSettingsService.isItemCachingEnabled() } returns false
|
||||
|
||||
val repository = Repository(api, appSettingsService, connectivityStatus, db)
|
||||
var testTags: List<SelfossModel.Tag> = emptyList()
|
||||
runBlocking {
|
||||
testTags = repository.getTags()
|
||||
}
|
||||
|
||||
assertSame(tags, testTags)
|
||||
coVerify(exactly = 1) { api.tags() }
|
||||
verify(exactly = 0) { db.tagsQueries.tags().executeAsList() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get tags with sources update and items caching disabled`() {
|
||||
val tags = listOf(SelfossModel.Tag("test", "red", 6),
|
||||
@ -364,11 +387,13 @@ class RepositoryTest() {
|
||||
var testTags: List<SelfossModel.Tag> = emptyList()
|
||||
runBlocking {
|
||||
testTags = repository.getTags()
|
||||
testTags = repository.getTags()
|
||||
}
|
||||
AmineB marked this conversation as resolved
Outdated
AmineB
commented
Tags and sources caching is handled via the update_sources setting. Also, disabling that setting should clear the DB (this is not the case yet) So this line should return null, as we won't check for the update_sources setting every time we try to fetch the db data. Tags and sources caching is handled via the update_sources setting.
Also, disabling that setting should clear the DB (this is not the case yet)
So this line should return null, as we won't check for the update_sources setting every time we try to fetch the db data.
AmineB
commented
Returning Returning `null` isn't possible, so it should be an empty list.
davidoskky
commented
Why is tags caching handled by update_sources? Why is tags caching handled by update_sources?
AmineB
commented
Because it's handled separatly, so users can cache the sources/tags without caching anything else. Because it's handled separatly, so users can cache the sources/tags without caching anything else.
davidoskky
commented
I don't think sources and tags should be cached if items are not cached; what would be the use of such a function? I don't think sources and tags should be cached if items are not cached; what would be the use of such a function?
AmineB
commented
As mentionnend by you in a previous comment, it is used to limit the ammount of calls to the selfoss instance, by limiting the call to tags/sources routes. > I don't think sources and tags should be cached if items are not cached; what would be the use of such a function?
As mentionnend by you in a previous comment, it is used to limit the ammount of calls to the selfoss instance, by limiting the call to tags/sources routes.
|
||||
|
||||
assertSame(tags, testTags)
|
||||
coVerify(exactly = 1) { api.tags() }
|
||||
verify(exactly = 0) { db.tagsQueries.tags().executeAsList() }
|
||||
assertNotSame(tags, testTags)
|
||||
assertContentEquals(tagsDB.map { it.toView() }, testTags)
|
||||
verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() }
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -415,9 +440,9 @@ class RepositoryTest() {
|
||||
testTags = repository.getTags()
|
||||
}
|
||||
|
||||
assertContentEquals(tagsDB.map { it.toView() }, testTags)
|
||||
assertSame(emptyList(), testTags)
|
||||
coVerify(exactly = 0) { api.tags() }
|
||||
verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() }
|
||||
verify(exactly = 0) { db.tagsQueries.tags().executeAsList() }
|
||||
AmineB marked this conversation as resolved
Outdated
AmineB
commented
The same comments about The same comments about `Get tags without connection and items caching disabled` should be considered here.
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -464,9 +489,9 @@ class RepositoryTest() {
|
||||
testTags = repository.getTags()
|
||||
}
|
||||
|
||||
assertSame(emptyList(), testTags)
|
||||
assertContentEquals(tagsDB.map { it.toView() }, testTags)
|
||||
coVerify(exactly = 0) { api.tags() }
|
||||
verify(exactly = 0) { db.tagsQueries.tags().executeAsList() }
|
||||
verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() }
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -497,6 +522,7 @@ class RepositoryTest() {
|
||||
SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png"))
|
||||
|
||||
every { appSettingsService.isUpdateSourcesEnabled() } returns false
|
||||
every { appSettingsService.isItemCachingEnabled() } returns true
|
||||
coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources)
|
||||
every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB
|
||||
val repository = Repository(api, appSettingsService, connectivityStatus, db)
|
||||
@ -507,12 +533,34 @@ class RepositoryTest() {
|
||||
testSources = repository.getSources()
|
||||
}
|
||||
|
||||
coVerify(exactly = 1) { api.sources() }
|
||||
assertNotSame(sources, testSources)
|
||||
assertContentEquals(sourcesDB.map { it.toView() }, testSources)
|
||||
coVerify(exactly = 1) { api.sources() }
|
||||
verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `get sources with items caching disabled`() {
|
||||
val sources = arrayListOf(SelfossModel.Source(1, "First source", listOf("Test", "second"),"spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"),
|
||||
SelfossModel.Source(2, "Second source", listOf("second"),"spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png"))
|
||||
val sourcesDB = listOf<SOURCE>(SOURCE("1", "First source", "Test,second","spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"),
|
||||
SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png"))
|
||||
|
||||
every { appSettingsService.isUpdateSourcesEnabled() } returns true
|
||||
every { appSettingsService.isItemCachingEnabled() } returns false
|
||||
coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources)
|
||||
every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB
|
||||
val repository = Repository(api, appSettingsService, connectivityStatus, db)
|
||||
var testSources: List<SelfossModel.Source>? = null
|
||||
runBlocking {
|
||||
testSources = repository.getSources()
|
||||
}
|
||||
|
||||
assertSame(sources, testSources)
|
||||
coVerify(exactly = 1) { api.sources() }
|
||||
verify(exactly = 0) { db.sourcesQueries }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `get sources with sources update and items caching disabled`() {
|
||||
val sources = arrayListOf(SelfossModel.Source(1, "First source", listOf("Test", "second"),"spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"),
|
||||
@ -532,7 +580,7 @@ class RepositoryTest() {
|
||||
|
||||
assertSame(sources, testSources)
|
||||
coVerify(exactly = 1) { api.sources() }
|
||||
verify(exactly = 0) { db.sourcesQueries.sources().executeAsList() }
|
||||
verify(atLeast = 1) { db.sourcesQueries }
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -574,9 +622,9 @@ class RepositoryTest() {
|
||||
testSources = repository.getSources()
|
||||
}
|
||||
|
||||
assertContentEquals(sourcesDB.map { it.toView() }, testSources)
|
||||
assertContentEquals(ArrayList(), testSources)
|
||||
coVerify(exactly = 0) { api.sources() }
|
||||
verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() }
|
||||
verify(exactly = 0) { db.sourcesQueries.sources().executeAsList() }
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -620,9 +668,9 @@ class RepositoryTest() {
|
||||
testSources = repository.getSources()
|
||||
}
|
||||
|
||||
assertContentEquals(ArrayList(), testSources)
|
||||
assertContentEquals(sourcesDB.map { it.toView() }, testSources)
|
||||
coVerify(exactly = 0) { api.sources() }
|
||||
verify(exactly = 0) { db.sourcesQueries.sources().executeAsList() }
|
||||
verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() }
|
||||
}
|
||||
|
||||
@Test
|
||||
|
What does this change do ?
This does not change the behavior of the function at all.
runBlocking and Dispatchers.Main are basically the same thing.
However, the testing framework for the common code does not support Dispatchers.
This edit serves pretty much just to make the tests work properly.
I'm certain there is some way to make it work keeping the Dispatchers in there, but since these are equivalent I preferred saving some time and just slightly change the function.