diff --git a/.drone.yml b/.drone.yml index 93d6729..6060363 100644 --- a/.drone.yml +++ b/.drone.yml @@ -11,7 +11,7 @@ steps: - ./gradlew sonarqube -Dsonar.projectKey=RFS2 -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" - echo "---------------------------------------------------------" - echo "Building..." - - ./gradlew :androidApp:build -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false + - ./gradlew build -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false - echo "---------------------------------------------------------" - echo "Testing..." - echo "---------------------------------------------------------" diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index a13deb4..e76add7 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -116,13 +116,6 @@ dependencies { implementation("androidx.preference:preference-ktx:1.1.1") - // Testing - androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0-alpha02") - androidTestImplementation("androidx.test:runner:1.3.1-alpha02") - // Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource - androidTestImplementation("androidx.test.espresso:espresso-contrib:3.4.0-alpha02") - // Espresso-intents for validation and stubbing of Intents - androidTestImplementation("androidx.test.espresso:espresso-intents:3.4.0-alpha02") implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs"))) // Android Support @@ -190,9 +183,6 @@ dependencies { implementation("androidx.core:core-ktx:1.8.0") - // implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.5.1") - // implementation("androidx.lifecycle:lifecycle-common-java8:2.5.1") - // implementation("androidx.lifecycle:lifecycle-runtime:2.5.1") implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") // Network information @@ -200,4 +190,23 @@ dependencies { // SQLDELIGHT implementation("com.squareup.sqldelight:android-driver:1.5.3") + + //test + testImplementation("junit:junit:4.13.2") + testImplementation("io.mockk:mockk:1.12.0") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") +} + +tasks.withType { + outputs.upToDateWhen { false } + useJUnit() + testLogging { + exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL + events = setOf( + org.gradle.api.tasks.testing.logging.TestLogEvent.PASSED, + org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED, + org.gradle.api.tasks.testing.logging.TestLogEvent.STANDARD_ERROR + ) + showStandardStreams = true + } } \ No newline at end of file diff --git a/androidApp/proguard-rules.pro b/androidApp/proguard-rules.pro index f7c7eff..3f9c98f 100644 --- a/androidApp/proguard-rules.pro +++ b/androidApp/proguard-rules.pro @@ -90,3 +90,5 @@ # @Serializable and @Polymorphic are used at runtime for polymorphic serialization. -keepattributes RuntimeVisibleAnnotations,AnnotationDefault +-dontwarn io.mockk.** +-keep class io.mockk.** { *; } diff --git a/androidApp/src/test/kotlin/RepositoryTest.kt b/androidApp/src/test/kotlin/RepositoryTest.kt new file mode 100644 index 0000000..6033d25 --- /dev/null +++ b/androidApp/src/test/kotlin/RepositoryTest.kt @@ -0,0 +1,1421 @@ +package bou.amine.apps.readerforselfossv2.repository + +import bou.amine.apps.readerforselfossv2.dao.ITEM +import bou.amine.apps.readerforselfossv2.dao.ReaderForSelfossDB +import bou.amine.apps.readerforselfossv2.dao.SOURCE +import bou.amine.apps.readerforselfossv2.dao.TAG +import bou.amine.apps.readerforselfossv2.model.SelfossModel +import bou.amine.apps.readerforselfossv2.rest.SelfossApi +import bou.amine.apps.readerforselfossv2.service.AppSettingsService +import bou.amine.apps.readerforselfossv2.utils.ItemType +import bou.amine.apps.readerforselfossv2.utils.toView +import io.mockk.* +import junit.framework.TestCase.* +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.runBlocking +import org.junit.Assert.assertNotEquals +import org.junit.Before +import org.junit.Test + +class RepositoryTest { + private val db = mockk(relaxed = true) + private val appSettingsService = mockk() + private val api = mockk() + + private val NUMBER_ARTICLES = 100 + private val NUMBER_UNREAD = 50 + private val NUMBER_STARRED = 20 + private lateinit var repository: Repository + + + private fun initializeRepository( + isConnectionAvailable: MutableStateFlow = MutableStateFlow( + true + ) + ) { + repository = Repository(api, appSettingsService, isConnectionAvailable, db) + + runBlocking { + repository.updateApiVersion() + } + } + + @Before + fun setup() { + clearAllMocks() + every { appSettingsService.getApiVersion() } returns 4 + every { appSettingsService.getBaseUrl() } returns "https://test.com/selfoss/" + every { appSettingsService.isItemCachingEnabled() } returns false + every { appSettingsService.isUpdateSourcesEnabled() } returns false + + coEvery { api.version() } returns SelfossModel.StatusAndData( + success = true, + data = SelfossModel.ApiVersion("2.19-ba1e8e3", "4.0.0") + ) + coEvery { api.stats() } returns SelfossModel.StatusAndData( + success = true, + data = SelfossModel.Stats(NUMBER_ARTICLES, NUMBER_UNREAD, NUMBER_STARRED) + ) + + every { db.itemsQueries.items().executeAsList() } returns generateTestDBItems() + every { db.tagsQueries.deleteAllTags() } returns Unit + every { db.tagsQueries.transaction(any(), any()) } returns Unit + every { db.tagsQueries.insertTag(any()) } returns Unit + } + + @Test + fun Instantiate_repository() { + initializeRepository() + + coVerify(exactly = 1) { api.version() } + } + + @Test + fun Instantiate_repository_without_api_version() { + every { appSettingsService.getApiVersion() } returns -1 + + initializeRepository(MutableStateFlow(false)) + + coVerify(exactly = 0) { api.version() } + coVerify(exactly = 0) { api.stats() } + } + + @Test + fun Get_api_4_date_with_api_1_version_stored() { + every { appSettingsService.getApiVersion() } returns 1 + coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns + SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) + every { appSettingsService.updateApiVersion(any()) } returns Unit + + initializeRepository() + runBlocking { + repository.getNewerItems() + } + + assertSame(repository.items.size, 1) + verify(exactly = 1) { appSettingsService.updateApiVersion(4) } + } + + @Test + fun Get_api_1_date_with_api_4_version_stored() { + every { appSettingsService.getApiVersion() } returns 4 + coEvery { api.version() } returns SelfossModel.StatusAndData(success = false, null) + val itemParameters = FakeItemParameters() + itemParameters.datetime = "2021-04-23 11:45:32" + coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns + SelfossModel.StatusAndData( + success = true, + data = generateTestApiItem(itemParameters) + ) + + initializeRepository() + runBlocking { + repository.getNewerItems() + } + + assertSame(1, repository.items.size) + } + + @Test + fun Get_newer_items() { + coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns + SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) + + initializeRepository() + runBlocking { + repository.getNewerItems() + } + + assertSame(repository.items.size, 1) + coVerify(exactly = 1) { api.getItems("unread", 0, null, null, null, null, any()) } + verify(exactly = 0) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Get_all_newer_items() { + coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns + SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) + + initializeRepository() + repository.displayedItems = ItemType.ALL + runBlocking { + repository.getNewerItems() + } + + assertSame(repository.items.size, 1) + coVerify(exactly = 1) { api.getItems("all", 0, null, null, null, null, any()) } + verify(exactly = 0) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Get_newer_starred_items() { + coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns + SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) + + initializeRepository() + repository.displayedItems = ItemType.STARRED + runBlocking { + repository.getNewerItems() + } + + assertSame(repository.items.size, 1) + coVerify(exactly = 1) { api.getItems("starred", 0, null, null, null, null, any()) } + verify(exactly = 0) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Get_newer_items_without_connectivity() { + every { appSettingsService.isItemCachingEnabled() } returns true + + initializeRepository(MutableStateFlow(false)) + runBlocking { + repository.getNewerItems() + } + + assertSame(repository.items.size, 1) + coVerify(exactly = 0) { api.getItems("unread", 0, null, null, null, null, any()) } + verify(atLeast = 1) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Get_newer_items_without_connectivity_and_tag_filter() { + val itemParameter1 = FakeItemParameters() + val itemParameter2 = FakeItemParameters() + val itemParameter3 = FakeItemParameters() + itemParameter2.tags = "Test, Stuff" + itemParameter2.id = "2" + itemParameter3.tags = "Other, Tag" + itemParameter3.id = "3" + coEvery { db.itemsQueries.items().executeAsList() } returns generateTestDBItems( + itemParameter1 + ) + + generateTestDBItems(itemParameter2) + + generateTestDBItems(itemParameter3) + + every { appSettingsService.isItemCachingEnabled() } returns true + + initializeRepository(MutableStateFlow(false)) + repository.tagFilter = SelfossModel.Tag("Test", "red", 3) + runBlocking { + repository.getNewerItems() + } + + assertSame(repository.items.size, 1) + coVerify(exactly = 0) { api.getItems("unread", 0, null, null, null, null, any()) } + verify(atLeast = 1) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Get_newer_items_without_connectivity_and_source_filter() { + val itemParameter1 = FakeItemParameters() + val itemParameter2 = FakeItemParameters() + val itemParameter3 = FakeItemParameters() + itemParameter2.sourcetitle = "Test" + itemParameter2.id = "2" + itemParameter3.sourcetitle = "Other" + itemParameter3.id = "3" + coEvery { db.itemsQueries.items().executeAsList() } returns generateTestDBItems( + itemParameter1 + ) + + generateTestDBItems(itemParameter2) + + generateTestDBItems(itemParameter3) + + every { appSettingsService.isItemCachingEnabled() } returns true + + initializeRepository(MutableStateFlow(false)) + repository.sourceFilter = SelfossModel.Source( + 1, + "Test", + listOf("tags"), + "spouts\\rss\\fulltextrss", + "", + "b3aa8a664d08eb15d6ff1db2fa83e0d9.png" + ) + runBlocking { + repository.getNewerItems() + } + + assertSame(repository.items.size, 1) + coVerify(exactly = 0) { api.getItems("unread", 0, null, null, null, null, any()) } + verify(atLeast = 1) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Get_older_items() { + coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns + SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) + + initializeRepository() + repository.items = ArrayList(generateTestApiItem()) + runBlocking { + repository.getOlderItems() + } + + assertSame(repository.items.size, 2) + coVerify(exactly = 1) { api.getItems("unread", 1, null, null, null, null, any()) } + verify(exactly = 0) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Get_all_older_items() { + coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns + SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) + + initializeRepository() + repository.items = ArrayList(generateTestApiItem()) + repository.displayedItems = ItemType.ALL + runBlocking { + repository.getOlderItems() + } + + assertSame(repository.items.size, 2) + coVerify(exactly = 1) { api.getItems("all", 1, null, null, null, null, any()) } + verify(exactly = 0) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Get_older_starred_items() { + coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns + SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) + + initializeRepository() + repository.displayedItems = ItemType.STARRED + repository.items = ArrayList(generateTestApiItem()) + runBlocking { + repository.getOlderItems() + } + + assertSame(repository.items.size, 2) + coVerify(exactly = 1) { api.getItems("starred", 1, null, null, null, null, any()) } + verify(exactly = 0) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Reload_badges() { + var success = false + + initializeRepository() + runBlocking { + success = repository.reloadBadges() + } + + assertSame(true, success) + assertSame(NUMBER_ARTICLES, repository.badgeAll) + assertSame(NUMBER_UNREAD, repository.badgeUnread) + assertSame(NUMBER_STARRED, repository.badgeStarred) + coVerify(atLeast = 1) { api.stats() } + verify(exactly = 0) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Reload_badges_without_response() { + coEvery { api.stats() } returns SelfossModel.StatusAndData(success = false, data = null) + + var success = false + + initializeRepository() + runBlocking { + success = repository.reloadBadges() + } + + assertSame(false, success) + assertSame(0, repository.badgeAll) + assertSame(0, repository.badgeUnread) + assertSame(0, repository.badgeStarred) + coVerify(atLeast = 1) { api.stats() } + verify(exactly = 0) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Reload_badges_without_connection() { + every { appSettingsService.isItemCachingEnabled() } returns true + every { db.itemsQueries.items().executeAsList() } returns generateTestDBItems() + + var success = false + + initializeRepository(MutableStateFlow(false)) + runBlocking { + success = repository.reloadBadges() + } + + assertTrue(success) + assertSame(1, repository.badgeAll) + assertSame(1, repository.badgeUnread) + assertSame(1, repository.badgeStarred) + coVerify(exactly = 0) { api.stats() } + verify(atLeast = 1) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Reload_badges_without_connection_and_items_caching_disabled() { + every { appSettingsService.isItemCachingEnabled() } returns false + every { appSettingsService.isUpdateSourcesEnabled() } returns true + + var success = false + + initializeRepository(MutableStateFlow(false)) + runBlocking { + success = repository.reloadBadges() + } + + assertFalse(success) + assertSame(0, repository.badgeAll) + assertSame(0, repository.badgeUnread) + assertSame(0, repository.badgeStarred) + coVerify(exactly = 0) { api.stats() } + verify(exactly = 0) { db.itemsQueries.items().executeAsList() } + } + + @Test + fun Get_tags() { + 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 true + + initializeRepository() + var testTags: List? = null + runBlocking { + testTags = repository.getTags() + } + + assertSame(tags, testTags) + assertNotSame(tagsDB.map { it.toView() }, testTags) + coVerify(exactly = 1) { api.tags() } + } + + @Test + fun Get_tags_with_sources_update_disabled() { + 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 false + every { appSettingsService.isItemCachingEnabled() } returns true + + initializeRepository() + var testTags: List = emptyList() + runBlocking { + testTags = repository.getTags() + // Tags will be fetched from the database on the second call, thus testTags != tags + testTags = repository.getTags() + } + + coVerify(exactly = 1) { api.tags() } + assertNotSame(tags, testTags) + assertEquals(tagsDB.map { it.toView() }, testTags) + verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() } + } + + @Test + fun Get_tags_with_items_caching_disabled() { + 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 + + initializeRepository() + var testTags: List = 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), + 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 false + every { appSettingsService.isItemCachingEnabled() } returns false + + initializeRepository() + var testTags: List = emptyList() + runBlocking { + testTags = repository.getTags() + testTags = repository.getTags() + } + + coVerify(exactly = 1) { api.tags() } + assertNotSame(tags, testTags) + assertEquals(tagsDB.map { it.toView() }, testTags) + verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() } + } + + @Test + fun Get_tags_without_connection() { + 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 true + + initializeRepository(MutableStateFlow(false)) + var testTags: List = emptyList() + runBlocking { + testTags = repository.getTags() + } + + assertNotSame(tags, testTags) + assertEquals(tagsDB.map { it.toView() }, testTags) + coVerify(exactly = 0) { api.tags() } + verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() } + } + + @Test + fun Get_tags_without_connection_and_items_caching_disabled() { + 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.isItemCachingEnabled() } returns false + every { appSettingsService.isUpdateSourcesEnabled() } returns true + + initializeRepository(MutableStateFlow(false)) + var testTags: List = emptyList() + runBlocking { + testTags = repository.getTags() + } + + assertSame(emptyList(), testTags) + coVerify(exactly = 0) { api.tags() } + verify(exactly = 0) { db.tagsQueries.tags().executeAsList() } + } + + @Test + fun Get_tags_without_connection_and_sources_update_disabled() { + 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 false + every { appSettingsService.isItemCachingEnabled() } returns true + + initializeRepository(MutableStateFlow(false)) + var testTags: List = emptyList() + runBlocking { + testTags = repository.getTags() + } + + assertNotSame(tags, testTags) + assertEquals(tagsDB.map { it.toView() }, testTags) + coVerify(exactly = 0) { api.tags() } + verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() } + } + + @Test + fun Get_tags_without_connection_and_sources_update_and_items_caching_disabled() { + 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 false + every { appSettingsService.isItemCachingEnabled() } returns false + + initializeRepository(MutableStateFlow(false)) + var testTags: List = emptyList() + runBlocking { + testTags = repository.getTags() + } + + assertEquals(tagsDB.map { it.toView() }, testTags) + coVerify(exactly = 0) { api.tags() } + verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() } + } + + @Test + fun get_sources() { + 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( + "1", + "First DB source", + "Test,second", + "spouts\\rss\\fulltextrss", + "", + "d8c92cdb1ef119ea85c4b9205c879ca7.png" + ), + SOURCE( + "2", + "Second source", + "second", + "spouts\\rss\\fulltextrss", + "", + "b3aa8a664d08eb15d6ff1db2fa83e0d9.png" + ) + ) + + coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) + every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB + initializeRepository() + var testSources: List? = null + runBlocking { + testSources = repository.getSources() + } + + assertSame(sources, testSources) + assertNotEquals(sourcesDB.map { it.toView() }, testSources) + coVerify(exactly = 1) { api.sources() } + } + + @Test + fun get_sources_with_sources_update_disabled() { + val sources = arrayListOf( + SelfossModel.Source( + 1, + "First source", + listOf("Test", "second"), + "spouts\\rss\\fulltextrss", + "", + "d8c92cdb1ef119ea85c4b9205c879ca7.png" + ), + SelfossModel.Source( + 2, + "Second DB source", + listOf("second"), + "spouts\\rss\\fulltextrss", + "", + "b3aa8a664d08eb15d6ff1db2fa83e0d9.png" + ) + ) + val sourcesDB = listOf( + 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 false + every { appSettingsService.isItemCachingEnabled() } returns true + coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) + every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB + initializeRepository() + var testSources: List? = null + runBlocking { + testSources = repository.getSources() + // Sources will be fetched from the database on the second call, thus testSources != sources + testSources = repository.getSources() + } + + coVerify(exactly = 1) { api.sources() } + assertNotSame(sources, testSources) + assertEquals(sourcesDB.map { it.toView() }, testSources) + 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( + "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 + initializeRepository() + var testSources: List? = 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" + ), + SelfossModel.Source( + 2, + "Second source", + listOf("second"), + "spouts\\rss\\fulltextrss", + "", + "b3aa8a664d08eb15d6ff1db2fa83e0d9.png" + ) + ) + val sourcesDB = listOf( + 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 false + every { appSettingsService.isItemCachingEnabled() } returns false + coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) + every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB + initializeRepository() + var testSources: List? = null + runBlocking { + testSources = repository.getSources() + } + + assertSame(sources, testSources) + coVerify(exactly = 1) { api.sources() } + verify(atLeast = 1) { db.sourcesQueries } + } + + @Test + fun get_sources_without_connection() { + 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( + "1", + "First DB source", + "Test,second", + "spouts\\rss\\fulltextrss", + "", + "d8c92cdb1ef119ea85c4b9205c879ca7.png" + ), + SOURCE( + "2", + "Second source", + "second", + "spouts\\rss\\fulltextrss", + "", + "b3aa8a664d08eb15d6ff1db2fa83e0d9.png" + ) + ) + + coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) + every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB + initializeRepository(MutableStateFlow(false)) + var testSources: List? = null + runBlocking { + testSources = repository.getSources() + } + + assertEquals(sourcesDB.map { it.toView() }, testSources) + coVerify(exactly = 0) { api.sources() } + verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() } + } + + @Test + fun get_sources_without_connection_and_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( + "1", + "First DB source", + "Test,second", + "spouts\\rss\\fulltextrss", + "", + "d8c92cdb1ef119ea85c4b9205c879ca7.png" + ), + SOURCE( + "2", + "Second source", + "second", + "spouts\\rss\\fulltextrss", + "", + "b3aa8a664d08eb15d6ff1db2fa83e0d9.png" + ) + ) + + every { appSettingsService.isItemCachingEnabled() } returns false + every { appSettingsService.isUpdateSourcesEnabled() } returns true + coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) + every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB + initializeRepository(MutableStateFlow(false)) + var testSources: List? = null + runBlocking { + testSources = repository.getSources() + } + + assertEquals(emptyList(), testSources) + coVerify(exactly = 0) { api.sources() } + verify(exactly = 0) { db.sourcesQueries.sources().executeAsList() } + } + + @Test + fun get_sources_without_connection_and_sources_update_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( + "1", + "First DB source", + "Test,second", + "spouts\\rss\\fulltextrss", + "", + "d8c92cdb1ef119ea85c4b9205c879ca7.png" + ), + SOURCE( + "2", + "Second source", + "second", + "spouts\\rss\\fulltextrss", + "", + "b3aa8a664d08eb15d6ff1db2fa83e0d9.png" + ) + ) + + every { appSettingsService.isItemCachingEnabled() } returns true + every { appSettingsService.isUpdateSourcesEnabled() } returns false + coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) + every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB + initializeRepository(MutableStateFlow(false)) + var testSources: List? = null + runBlocking { + testSources = repository.getSources() + } + + assertEquals(sourcesDB.map { it.toView() }, testSources) + coVerify(exactly = 0) { api.sources() } + verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() } + } + + @Test + fun get_sources_without_connection_and_items_caching_and_sources_update_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( + "1", + "First DB source", + "Test,second", + "spouts\\rss\\fulltextrss", + "", + "d8c92cdb1ef119ea85c4b9205c879ca7.png" + ), + SOURCE( + "2", + "Second source", + "second", + "spouts\\rss\\fulltextrss", + "", + "b3aa8a664d08eb15d6ff1db2fa83e0d9.png" + ) + ) + + every { appSettingsService.isItemCachingEnabled() } returns false + every { appSettingsService.isUpdateSourcesEnabled() } returns false + coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) + every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB + initializeRepository(MutableStateFlow(false)) + var testSources: List? = null + runBlocking { + testSources = repository.getSources() + } + + assertEquals(sourcesDB.map { it.toView() }, testSources) + coVerify(exactly = 0) { api.sources() } + verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() } + } + + @Test + fun create_source() { + coEvery { api.createSourceForVersion(any(), any(), any(), any(), any(), any()) } returns + SelfossModel.SuccessResponse(true) + + initializeRepository() + var response = false + runBlocking { + response = repository.createSource( + "test", + "https://test.com/feed", + "spouts\\rss\\fulltextrss", + "Test, New", + "" + ) + } + + coVerify(exactly = 1) { + api.createSourceForVersion( + any(), + any(), + any(), + any(), + any(), + any() + ) + } + assertSame(true, response) + } + + @Test + fun create_source_but_response_fails() { + coEvery { api.createSourceForVersion(any(), any(), any(), any(), any(), any()) } returns + SelfossModel.SuccessResponse(false) + + initializeRepository() + var response = false + runBlocking { + response = repository.createSource( + "test", + "https://test.com/feed", + "spouts\\rss\\fulltextrss", + "Test, New", + "" + ) + } + + coVerify(exactly = 1) { + api.createSourceForVersion( + any(), + any(), + any(), + any(), + any(), + any() + ) + } + assertSame(false, response) + } + + @Test + fun create_source_without_connection() { + coEvery { api.createSourceForVersion(any(), any(), any(), any(), any(), any()) } returns + SelfossModel.SuccessResponse(true) + + initializeRepository(MutableStateFlow(false)) + var response = false + runBlocking { + response = repository.createSource( + "test", + "https://test.com/feed", + "spouts\\rss\\fulltextrss", + "Test, New", + "" + ) + } + + coVerify(exactly = 0) { + api.createSourceForVersion( + any(), + any(), + any(), + any(), + any(), + any() + ) + } + assertSame(false, response) + } + + @Test + fun delete_source() { + coEvery { api.deleteSource(any()) } returns SelfossModel.SuccessResponse(true) + + initializeRepository() + var response = false + runBlocking { + response = repository.deleteSource(5) + } + + coVerify(exactly = 1) { api.deleteSource(5) } + assertSame(true, response) + } + + @Test + fun delete_source_but_response_fails() { + coEvery { api.deleteSource(any()) } returns SelfossModel.SuccessResponse(false) + + initializeRepository() + var response = false + runBlocking { + response = repository.deleteSource(5) + } + + coVerify(exactly = 1) { api.deleteSource(5) } + assertSame(false, response) + } + + @Test + fun delete_source_without_connection() { + coEvery { api.deleteSource(any()) } returns SelfossModel.SuccessResponse(false) + + initializeRepository(MutableStateFlow(false)) + var response = false + runBlocking { + response = repository.deleteSource(5) + } + + coVerify(exactly = 0) { api.deleteSource(5) } + assertSame(false, response) + } + + @Test + fun update_remote() { + coEvery { api.update() } returns SelfossModel.StatusAndData( + success = true, + data = "finished" + ) + + initializeRepository() + var response = false + runBlocking { + response = repository.updateRemote() + } + + coVerify(exactly = 1) { api.update() } + assertTrue(response) + } + + @Test + fun update_remote_but_response_fails() { + coEvery { api.update() } returns SelfossModel.StatusAndData( + success = false, + data = "unallowed access" + ) + + initializeRepository() + var response = false + runBlocking { + response = repository.updateRemote() + } + + coVerify(exactly = 1) { api.update() } + assertSame(false, response) + } + + @Test + fun update_remote_with_unallowed_access() { + coEvery { api.update() } returns SelfossModel.StatusAndData( + success = true, + data = "unallowed access" + ) + + initializeRepository() + var response = false + runBlocking { + response = repository.updateRemote() + } + + coVerify(exactly = 1) { api.update() } + assertSame(false, response) + } + + @Test + fun update_remote_without_connection() { + coEvery { api.update() } returns SelfossModel.StatusAndData( + success = true, + data = "undocumented..." + ) + + initializeRepository(MutableStateFlow(false)) + var response = false + runBlocking { + response = repository.updateRemote() + } + + coVerify(exactly = 0) { api.update() } + assertSame(false, response) + } + + @Test + fun login() { + coEvery { api.login() } returns SelfossModel.SuccessResponse(success = true) + + initializeRepository() + var response = false + runBlocking { + response = repository.login() + } + + coVerify(exactly = 1) { api.login() } + assertSame(true, response) + } + + @Test + fun login_but_response_fails() { + coEvery { api.login() } returns SelfossModel.SuccessResponse(success = false) + + initializeRepository() + var response = false + runBlocking { + response = repository.login() + } + + coVerify(exactly = 1) { api.login() } + assertSame(false, response) + } + + @Test + fun login_but_without_connection() { + coEvery { api.login() } returns SelfossModel.SuccessResponse(success = true) + + initializeRepository(MutableStateFlow(false)) + var response = false + runBlocking { + response = repository.login() + } + + coVerify(exactly = 0) { api.login() } + assertSame(false, response) + } + + @Test + fun refresh_login_information() { + coEvery { api.refreshLoginInformation() } returns Unit + coEvery { appSettingsService.refreshLoginInformation(any(), any(), any()) } returns Unit + + initializeRepository() + repository.refreshLoginInformation("https://test.com/selfoss/", "login", "password") + + coVerify(exactly = 1) { api.refreshLoginInformation() } + coVerify(exactly = 1) { + appSettingsService.refreshLoginInformation( + "https://test.com/selfoss/", + "login", + "password" + ) + } + } + + @Test + fun cache_items() { + val itemParameter1 = FakeItemParameters() + val itemParameter2 = FakeItemParameters() + val itemParameter3 = FakeItemParameters() + itemParameter2.id = "2" + itemParameter3.id = "3" + coEvery { + api.getItems( + any(), + any(), + any(), + any(), + any(), + any(), + any() + ) + } returnsMany listOf( + SelfossModel.StatusAndData(success = true, data = generateTestApiItem(itemParameter1)), + SelfossModel.StatusAndData(success = true, data = generateTestApiItem(itemParameter2)), + SelfossModel.StatusAndData(success = true, data = generateTestApiItem(itemParameter1)), + ) + + initializeRepository() + repository.tagFilter = SelfossModel.Tag("Tag", "read", 0) + repository.sourceFilter = SelfossModel.Source( + 1, + "First source", + listOf("Test", "second"), + "spouts\\rss\\fulltextrss", + "", + "d8c92cdb1ef119ea85c4b9205c879ca7.png" + ) + repository.searchFilter = "search" + runBlocking { + repository.tryToCacheItemsAndGetNewOnes() + } + + coVerify(exactly = 3) { api.getItems(any(), 0, null, null, null, null, 200) } + } + + @Test + fun cache_items_but_response_fails() { + coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns + SelfossModel.StatusAndData(success = false, data = generateTestApiItem()) + + initializeRepository() + repository.tagFilter = SelfossModel.Tag("Tag", "read", 0) + repository.sourceFilter = SelfossModel.Source( + 1, + "First source", + listOf("Test", "second"), + "spouts\\rss\\fulltextrss", + "", + "d8c92cdb1ef119ea85c4b9205c879ca7.png" + ) + repository.searchFilter = "search" + runBlocking { + repository.tryToCacheItemsAndGetNewOnes() + } + + coVerify(exactly = 3) { api.getItems(any(), 0, null, null, null, null, 200) } + } + + @Test + fun cache_items_without_connection() { + coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns + SelfossModel.StatusAndData(success = false, data = generateTestApiItem()) + + initializeRepository(MutableStateFlow(false)) + repository.tagFilter = SelfossModel.Tag("Tag", "read", 0) + repository.sourceFilter = SelfossModel.Source( + 1, + "First source", + listOf("Test", "second"), + "spouts\\rss\\fulltextrss", + "", + "d8c92cdb1ef119ea85c4b9205c879ca7.png" + ) + repository.searchFilter = "search" + runBlocking { + repository.tryToCacheItemsAndGetNewOnes() + } + + coVerify(exactly = 0) { api.getItems(any(), 0, null, null, null, null, 200) } + } +} + +fun generateTestDBItems(item: FakeItemParameters = FakeItemParameters()): List { + return listOf( + ITEM( + id = item.id, + datetime = item.datetime, + title = item.title, + content = item.content, + unread = item.unread, + starred = item.starred, + thumbnail = item.thumbnail, + icon = item.icon, + link = item.link, + sourcetitle = item.sourcetitle, + tags = item.tags + ) + ) +} + +fun generateTestApiItem(item: FakeItemParameters = FakeItemParameters()): List { + return listOf( + SelfossModel.Item( + id = item.id.toInt(), + datetime = item.datetime, + title = item.title, + content = item.content, + unread = item.unread, + starred = item.starred, + thumbnail = item.thumbnail, + icon = item.icon, + link = item.link, + sourcetitle = item.sourcetitle, + tags = item.tags.split(',') + ) + ) +} + +class FakeItemParameters { + var id = "20" + var datetime = "2022-09-09T03:32:01-04:00" + val title = "Etica della ricerca sotto i riflettori." + val content = + "

Luigi Campanella, già Presidente SCI

\n

L’etica della scienza è di certo ambito di cui continuiamo a scoprire nuovi aspetti e risvolti.

\n

L’ultimo è quello delle intelligenze artificiali capaci di creare opere complesse basate su immagini e parole memorizzate con il rischio di fake news e di contenuti disturbanti.

\n

Per evitare che ciò accada si sta procedendo filtrando secondo criteri di autocensura i dati da cui l’intelligenza artificiale parte.

\n

Comincia ad intravedersi un futuro prossimo di competizione fra autori umani ed artificiali nel quale sarà importante, quando i loro prodotti saranno indistinguibili, dichiararne l’origine.

\n

Come si comprende, si conferma che gli aspetti etici dell’innovazione e della ricerca si diversificato sempre di più.

\n

La biologia molecolare e la genetica già in passato hanno posto all’attenzione comune aspetti di etica della scienza che hanno indotto a nuove riflessioni circa i limiti delle ricerche.

\n

L’argomento, sempre attuale, torna sulle prime pagine a seguito della pubblicazione di una ricerca della Università di Cambridge che ha sviluppato una struttura cellulare di un topo con un cuore che batte regolarmente.

\n\"\"\"\"

Magdalena Zernicka-Goetz

\n\"\"

Gianluca Amadei

\n

Del gruppo fa parte anche uno scienziato italiano Gianluca Amadei,che dinnanzi alle obiezioni di natura etica sulla realizzazione della vita artificiale si è affrettato a sostenere che non è creare nuove vite il fine primario della ricerca, ma quello di salvare quelle esistenti, di dare contributi essenziali alla medicina citando il caso del fallimento tuttora non interpretato di alcune gravidanze e di superare la sperimentazione animale, così contribuendo positivamente alla soluzione di un altro dilemma etico.

\n

L’embrione sintetico ha ovviamente come primo traguardo il contributo ai trapianti oggi drammaticamente carenti nell’offerta rispetto alla domanda, con attese fino a 4 anni per i trapianti di cuore ed a 2 anni per quelli di fegato. Il lavoro dovrebbe adesso continuare presso l’Ateneo di Padova per creare nuovi organi e nuovi farmaci.

" + var unread = true + var starred = true + val thumbnail = null + val icon = "ba79e238383ce83c23a169929c8906ef.png" + val link = + "https://ilblogdellasci.wordpress.com/2022/09/09/etica-della-ricerca-sotto-i-riflettori/" + var sourcetitle = "La Chimica e la Società" + var tags = "Chimica, Testing" +} diff --git a/build.gradle.kts b/build.gradle.kts index f4d60ef..49edef4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,8 +9,8 @@ plugins { //trick: for the same plugin versions in all sub-modules id("com.android.application").version("7.3.1").apply(false) id("com.android.library").version("7.3.1").apply(false) - kotlin("android").version("1.7.10").apply(false) - kotlin("multiplatform").version("1.7.10").apply(false) + kotlin("android").version("1.7.20").apply(false) + kotlin("multiplatform").version("1.7.20").apply(false) id("org.sonarqube").version("3.4.0.2513").apply(false) } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index c4020d8..c650e50 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -18,7 +18,7 @@ kotlin { listOf( iosX64(), iosArm64(), - iosSimulatorArm64() + // iosSimulatorArm64() ).forEach { it.binaries.framework { baseName = "shared" @@ -40,7 +40,7 @@ kotlin { implementation("org.kodein.di:kodein-di:7.12.0") //Settings - implementation("com.russhwolf:multiplatform-settings-no-arg:0.9") + implementation("com.russhwolf:multiplatform-settings-no-arg:1.0.0-RC") //Logging implementation("io.github.aakira:napier:2.6.1") @@ -53,9 +53,6 @@ kotlin { dependencies { implementation(kotlin("test-common")) implementation(kotlin("test-annotations-common")) - // implementation("io.mockk:mockk:1.12.0") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") - } } val androidMain by getting { @@ -74,12 +71,12 @@ kotlin { } val iosX64Main by getting val iosArm64Main by getting - val iosSimulatorArm64Main by getting + // val iosSimulatorArm64Main by getting val iosMain by creating { dependsOn(commonMain) iosX64Main.dependsOn(this) iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) + // iosSimulatorArm64Main.dependsOn(this) dependencies { implementation(SqlDelight.native) @@ -88,12 +85,12 @@ kotlin { } val iosX64Test by getting val iosArm64Test by getting - val iosSimulatorArm64Test by getting + // val iosSimulatorArm64Test by getting val iosTest by creating { dependsOn(commonTest) iosX64Test.dependsOn(this) iosArm64Test.dependsOn(this) - iosSimulatorArm64Test.dependsOn(this) + // iosSimulatorArm64Test.dependsOn(this) } } } diff --git a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt index 62668c6..8ff8dda 100644 --- a/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt +++ b/shared/src/androidMain/kotlin/bou/amine/apps/readerforselfossv2/utils/DateUtils.kt @@ -1,5 +1,6 @@ package bou.amine.apps.readerforselfossv2.utils +import android.os.Build import android.text.format.DateUtils import bou.amine.apps.readerforselfossv2.service.AppSettingsService import java.time.Instant @@ -15,10 +16,18 @@ actual class DateUtils actual constructor(actual val appSettingsService: AppSett val FORMATTERV1 = "yyyy-MM-dd HH:mm:ss" return if (appSettingsService.getApiVersion() >= 4) { - OffsetDateTime.parse(dateString).toInstant().toEpochMilli() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + OffsetDateTime.parse(dateString).toInstant().toEpochMilli() + } else { + TODO("VERSION.SDK_INT < O") + } } else { - LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(FORMATTERV1)).toInstant( - ZoneOffset.UTC).toEpochMilli() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(FORMATTERV1)).toInstant( + ZoneOffset.UTC).toEpochMilli() + } else { + TODO("VERSION.SDK_INT < O") + } } } @@ -26,11 +35,15 @@ actual class DateUtils actual constructor(actual val appSettingsService: AppSett val date = parseDate(dateString) - return " " + DateUtils.getRelativeTimeSpanString( - date, - Instant.now().toEpochMilli(), - DateUtils.MINUTE_IN_MILLIS, - DateUtils.FORMAT_ABBREV_RELATIVE - ) + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + " " + DateUtils.getRelativeTimeSpanString( + date, + Instant.now().toEpochMilli(), + DateUtils.MINUTE_IN_MILLIS, + DateUtils.FORMAT_ABBREV_RELATIVE + ) + } else { + TODO("VERSION.SDK_INT < O") + } } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/AppSettingsService.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/AppSettingsService.kt index 8a28a23..3b96e2f 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/AppSettingsService.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/service/AppSettingsService.kt @@ -54,8 +54,8 @@ class AppSettingsService { return _apiVersion } - fun refreshApiVersion() { - _apiVersion = settings.getInt("apiVersionMajor", -1) + private fun refreshApiVersion() { + _apiVersion = settings.getInt(API_VERSION_MAJOR, -1) } fun getBaseUrl(): String { @@ -86,8 +86,8 @@ class AppSettingsService { return _itemsNumber!! } - fun refreshItemsNumber() { - _itemsNumber = settings.getString("prefer_api_items_number", "20").toInt() + private fun refreshItemsNumber() { + _itemsNumber = settings.getString(API_ITEMS_NUMBER, "20").toInt() } fun getApiTimeout(): Long { @@ -98,24 +98,24 @@ class AppSettingsService { } private fun refreshApiTimeout() { - val settingsTimeout = settings.getLong("api_timeout", HttpTimeout.INFINITE_TIMEOUT_MS) + val settingsTimeout = settings.getLong(API_TIMEOUT, HttpTimeout.INFINITE_TIMEOUT_MS) _apiTimeout = if (settingsTimeout > 0) settingsTimeout else HttpTimeout.INFINITE_TIMEOUT_MS } private fun refreshBaseUrl() { - _baseUrl = settings.getString("url", "") + _baseUrl = settings.getString(BASE_URL, "") } private fun refreshUsername() { - _userName = settings.getString("login", "") + _userName = settings.getString(LOGIN, "") } private fun refreshPassword() { - _password = settings.getString("password", "") + _password = settings.getString(PASSWORD, "") } private fun refreshArticleViewerEnabled() { - _articleViewer = settings.getBoolean("prefer_article_viewer", true) + _articleViewer = settings.getBoolean(PREFER_ARTICLE_VIEWER, true) } fun isArticleViewerEnabled(): Boolean { @@ -125,7 +125,7 @@ class AppSettingsService { return _articleViewer == true } private fun refreshShouldBeCardViewEnabled() { - _shouldBeCardView = settings.getBoolean("card_view_active", false) + _shouldBeCardView = settings.getBoolean(CARD_VIEW_ACTIVE, false) } fun isCardViewEnabled(): Boolean { @@ -135,7 +135,7 @@ class AppSettingsService { return _shouldBeCardView == true } private fun refreshDisplayUnreadCountEnabled() { - _displayUnreadCount = settings.getBoolean("display_unread_count", true) + _displayUnreadCount = settings.getBoolean(DISPLAY_UNREAD_COUNT, true) } fun isDisplayUnreadCountEnabled(): Boolean { @@ -145,7 +145,7 @@ class AppSettingsService { return _displayUnreadCount == true } private fun refreshDisplayAllCountEnabled() { - _displayAllCount = settings.getBoolean("display_other_count", false) + _displayAllCount = settings.getBoolean(DISPLAY_OTHER_COUNT, false) } fun isDisplayAllCountEnabled(): Boolean { @@ -155,7 +155,7 @@ class AppSettingsService { return _displayAllCount == true } private fun refreshFullHeightCardsEnabled() { - _fullHeightCards = settings.getBoolean("full_height_cards", false) + _fullHeightCards = settings.getBoolean(FULL_HEIGHT_CARDS, false) } fun isFullHeightCardsEnabled(): Boolean { @@ -165,7 +165,7 @@ class AppSettingsService { return _fullHeightCards == true } private fun refreshUpdateSourcesEnabled() { - _updateSources = settings.getBoolean("update_sources", true) + _updateSources = settings.getBoolean(UPDATE_SOURCES, true) } fun isUpdateSourcesEnabled(): Boolean { @@ -175,7 +175,7 @@ class AppSettingsService { return _updateSources == true } private fun refreshPeriodicRefreshEnabled() { - _periodicRefresh = settings.getBoolean("periodic_refresh", false) + _periodicRefresh = settings.getBoolean(PERIODIC_REFRESH, false) } fun isPeriodicRefreshEnabled(): Boolean { @@ -186,7 +186,7 @@ class AppSettingsService { } private fun refreshRefreshWhenChargingOnlyEnabled() { - _refreshWhenChargingOnly = settings.getBoolean("refresh_when_charging", false) + _refreshWhenChargingOnly = settings.getBoolean(REFRESH_WHEN_CHARGING, false) } fun isRefreshWhenChargingOnlyEnabled(): Boolean { @@ -197,22 +197,22 @@ class AppSettingsService { } private fun refreshRefreshMinutes() { - _refreshMinutes = settings.getString("periodic_refresh_minutes", "360").toLong() + _refreshMinutes = settings.getString(PERIODIC_REFRESH_MINUTES, "360").toLong() if (_refreshMinutes <= 15) { _refreshMinutes = 15 } } fun getRefreshMinutes(): Long { - if (_refreshMinutes != null) { + if (_refreshMinutes != 360L) { refreshRefreshMinutes() } return _refreshMinutes } private fun refreshHiddenTags() { - if (settings.getString("hidden_tags", "").isNotEmpty()) { - _hiddenTags = settings.getString("hidden_tags", "").replace("\\s".toRegex(), "").split(",") + if (settings.getString(HIDDEN_TAGS, "").isNotEmpty()) { + _hiddenTags = settings.getString(HIDDEN_TAGS, "").replace("\\s".toRegex(), "").split(",") } } @@ -224,7 +224,7 @@ class AppSettingsService { } private fun refreshInfiniteLoadingEnabled() { - _infiniteLoading = settings.getBoolean("infinite_loading", false) + _infiniteLoading = settings.getBoolean(INFINITE_LOADING, false) } fun isInfiniteLoadingEnabled(): Boolean { @@ -235,7 +235,7 @@ class AppSettingsService { } private fun refreshItemCachingEnabled() { - _itemsCaching = settings.getBoolean("items_caching", false) + _itemsCaching = settings.getBoolean(ITEMS_CACHING, false) } fun isItemCachingEnabled(): Boolean { @@ -246,7 +246,7 @@ class AppSettingsService { } private fun refreshNotifyNewItemsEnabled() { - _notifyNewItems = settings.getBoolean("notify_new_items", false) + _notifyNewItems = settings.getBoolean(NOTIFY_NEW_ITEMS, false) } fun isNotifyNewItemsEnabled(): Boolean { @@ -258,7 +258,7 @@ class AppSettingsService { private fun refreshMarkOnScrollEnabled() { - _markOnScroll = settings.getBoolean("mark_on_scroll", false) + _markOnScroll = settings.getBoolean(MARK_ON_SCROLL, false) } fun isMarkOnScrollEnabled(): Boolean { @@ -270,7 +270,7 @@ class AppSettingsService { private fun refreshActiveAllignment() { - _activeAlignment = settings.getInt("text_align", JUSTIFY) + _activeAlignment = settings.getInt(TEXT_ALIGN, JUSTIFY) } fun getActiveAllignment(): Int { @@ -281,12 +281,12 @@ class AppSettingsService { } fun changeAllignment(allignment: Int) { - settings.putInt("text_align", allignment) + settings.putInt(TEXT_ALIGN, allignment) _activeAlignment = allignment } private fun refreshFontSize() { - _fontSize = settings.getString("reader_font_size", "16").toInt() + _fontSize = settings.getString(READER_FONT_SIZE, "16").toInt() } fun getFontSize(): Int { @@ -297,7 +297,7 @@ class AppSettingsService { } private fun refreshStaticBarEnabled() { - _staticBar = settings.getBoolean("reader_static_bar", false) + _staticBar = settings.getBoolean(READER_STATIC_BAR, false) } fun isStaticBarEnabled(): Boolean { @@ -308,11 +308,11 @@ class AppSettingsService { } private fun refreshFont() { - _font = settings.getString("reader_font", "") + _font = settings.getString(READER_FONT, "") } fun getFont(): String { - if (_font != null) { + if (_font.isEmpty()) { refreshFont() } return _font @@ -353,21 +353,21 @@ class AppSettingsService { login: String, password: String ) { - settings.putString("url", url) - settings.putString("login", login) - settings.putString("password", password) + settings.putString(BASE_URL, url) + settings.putString(LOGIN, login) + settings.putString(PASSWORD, password) refreshApiSettings() } fun resetLoginInformation() { - settings.remove("url") - settings.remove("login") - settings.remove("password") + settings.remove(BASE_URL) + settings.remove(LOGIN) + settings.remove(PASSWORD) refreshApiSettings() } fun updateApiVersion(apiMajorVersion: Int) { - settings.putInt("apiVersionMajor", apiMajorVersion) + settings.putInt(API_VERSION_MAJOR, apiMajorVersion) refreshApiVersion() } @@ -378,7 +378,7 @@ class AppSettingsService { } fun disableArticleViewer() { - settings.putBoolean("prefer_article_viewer", false) + settings.putBoolean(PREFER_ARTICLE_VIEWER, false) refreshArticleViewerEnabled() } @@ -396,5 +396,53 @@ class AppSettingsService { const val JUSTIFY = 1 const val ALIGN_LEFT = 2 + + const val API_VERSION_MAJOR = "apiVersionMajor" + + const val API_ITEMS_NUMBER = "prefer_api_items_number" + + const val API_TIMEOUT = "api_timeout" + + const val BASE_URL = "url" + + const val LOGIN = "login" + + const val PASSWORD = "password" + + const val PREFER_ARTICLE_VIEWER = "prefer_article_viewer" + + const val CARD_VIEW_ACTIVE = "card_view_active" + + const val DISPLAY_UNREAD_COUNT = "display_unread_count" + + const val DISPLAY_OTHER_COUNT = "display_other_count" + + const val FULL_HEIGHT_CARDS = "full_height_cards" + + const val UPDATE_SOURCES = "update_sources" + + const val PERIODIC_REFRESH = "periodic_refresh" + + const val REFRESH_WHEN_CHARGING = "refresh_when_charging" + + const val READER_FONT = "reader_font" + + const val READER_STATIC_BAR = "reader_static_bar" + + const val READER_FONT_SIZE = "reader_font_size" + + const val TEXT_ALIGN = "text_align" + + const val MARK_ON_SCROLL = "mark_on_scroll" + + const val NOTIFY_NEW_ITEMS = "notify_new_items" + + const val PERIODIC_REFRESH_MINUTES = "periodic_refresh_minutes" + + const val HIDDEN_TAGS = "hidden_tags" + + const val INFINITE_LOADING = "infinite_loading" + + const val ITEMS_CACHING = "items_caching" } } \ No newline at end of file diff --git a/shared/src/commonTest/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryTest.kt b/shared/src/commonTest/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryTest.kt deleted file mode 100644 index cc5e284..0000000 --- a/shared/src/commonTest/kotlin/bou/amine/apps/readerforselfossv2/repository/RepositoryTest.kt +++ /dev/null @@ -1,1052 +0,0 @@ -//package bou.amine.apps.readerforselfossv2.repository -// -//import bou.amine.apps.readerforselfossv2.dao.ITEM -//import bou.amine.apps.readerforselfossv2.dao.ReaderForSelfossDB -//import bou.amine.apps.readerforselfossv2.dao.SOURCE -//import bou.amine.apps.readerforselfossv2.dao.TAG -//import bou.amine.apps.readerforselfossv2.model.SelfossModel -//import bou.amine.apps.readerforselfossv2.rest.SelfossApi -//import bou.amine.apps.readerforselfossv2.service.AppSettingsService -//import bou.amine.apps.readerforselfossv2.utils.ItemType -//import bou.amine.apps.readerforselfossv2.utils.toView -//import com.github.ln_12.library.ConnectivityStatus -//import io.mockk.* -//import kotlinx.coroutines.flow.MutableStateFlow -//import kotlinx.coroutines.runBlocking -//import kotlin.test.* -// -//class RepositoryTest() { -// private val connectivityStatus = mockk() -// private val db = mockk(relaxed = true) -// private val appSettingsService = mockk() -// private val api = mockk() -// -// private val NUMBER_ARTICLES = 100 -// private val NUMBER_UNREAD = 50 -// private val NUMBER_STARRED = 20 -// private lateinit var repository: Repository -// -// @BeforeTest -// fun setup() { -// clearAllMocks() -// every { appSettingsService.getApiVersion() } returns 4 -// every { appSettingsService.getBaseUrl() } returns "https://test.com/selfoss/" -// every { appSettingsService.isItemCachingEnabled() } returns false -// every { appSettingsService.isUpdateSourcesEnabled() } returns false -// -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(true) -// -// coEvery { api.version() } returns SelfossModel.StatusAndData(success = true, data = SelfossModel.ApiVersion("2.19-ba1e8e3", "4.0.0")) -// coEvery { api.stats() } returns SelfossModel.StatusAndData(success = true, data = SelfossModel.Stats(NUMBER_ARTICLES, NUMBER_UNREAD, NUMBER_STARRED)) -// -// every { db.itemsQueries.items().executeAsList() } returns generateTestDBItems() -// every { db.tagsQueries.deleteAllTags() } returns Unit -// every { db.tagsQueries.transaction(any(), any()) } returns Unit -// every { db.tagsQueries.insertTag(any()) } returns Unit -// -// every { connectivityStatus.start() } returns Unit -// } -// -// @Test -// fun `Instantiate repository`() { -// initializeRepository() -// -// coVerify(exactly = 1) { api.version() } -// } -// -// @Test -// fun `Instantiate repository without api version`() { -// every { appSettingsService.getApiVersion() } returns -1 -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// -// initializeRepository() -// -// coVerify(exactly = 0) { api.version() } -// coVerify(exactly = 0) { api.stats() } -// } -// -// @Test -// fun `Get api 4 date with api 1 version stored`() { -// every { appSettingsService.getApiVersion() } returns 1 -// coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) -// every { appSettingsService.updateApiVersion(any()) } returns Unit -// -// initializeRepository() -// runBlocking { -// repository.getNewerItems() -// } -// -// assertSame(repository.items.size, 1) -// verify(exactly = 1) { appSettingsService.updateApiVersion(4) } -// } -// -// @Test -// fun `Get api 1 date with api 4 version stored`() { -// every { appSettingsService.getApiVersion() } returns 4 -// coEvery { api.version() } returns SelfossModel.StatusAndData(success = false, null) -// val itemParameters = FakeItemParameters() -// itemParameters.datetime = "2021-04-23 11:45:32" -// coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.StatusAndData(success = true, data = generateTestApiItem(itemParameters)) -// -// initializeRepository() -// runBlocking { -// repository.getNewerItems() -// } -// -// assertSame(1, repository.items.size) -// } -// -// @Test -// fun `Get newer items`() { -// coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) -// -// initializeRepository() -// runBlocking { -// repository.getNewerItems() -// } -// -// assertSame(repository.items.size, 1) -// coVerify(exactly = 1) { api.getItems("unread", 0, null, null, null, null, any()) } -// verify(exactly = 0) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Get all newer items`() { -// coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) -// -// initializeRepository() -// repository.displayedItems = ItemType.ALL -// runBlocking { -// repository.getNewerItems() -// } -// -// assertSame(repository.items.size, 1) -// coVerify(exactly = 1) { api.getItems("all", 0, null, null, null, null, any()) } -// verify(exactly = 0) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Get newer starred items`() { -// coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) -// -// initializeRepository() -// repository.displayedItems = ItemType.STARRED -// runBlocking { -// repository.getNewerItems() -// } -// -// assertSame(repository.items.size, 1) -// coVerify(exactly = 1) { api.getItems("starred", 0, null, null, null, null, any()) } -// verify(exactly = 0) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Get newer items without connectivity`() { -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isItemCachingEnabled() } returns true -// -// initializeRepository() -// runBlocking { -// repository.getNewerItems() -// } -// -// assertSame(repository.items.size, 1) -// coVerify(exactly = 0) { api.getItems("unread", 0, null, null, null, null, any()) } -// verify(atLeast = 1) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Get newer items without connectivity and tag filter`() { -// val itemParameter1 = FakeItemParameters() -// val itemParameter2 = FakeItemParameters() -// val itemParameter3 = FakeItemParameters() -// itemParameter2.tags = "Test, Stuff" -// itemParameter2.id = "2" -// itemParameter3.tags = "Other, Tag" -// itemParameter3.id = "3" -// coEvery { db.itemsQueries.items().executeAsList() } returns generateTestDBItems(itemParameter1) + -// generateTestDBItems(itemParameter2) + -// generateTestDBItems(itemParameter3) -// -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isItemCachingEnabled() } returns true -// -// initializeRepository() -// repository.tagFilter = SelfossModel.Tag("Test", "red", 3) -// runBlocking { -// repository.getNewerItems() -// } -// -// assertSame(repository.items.size, 1) -// coVerify(exactly = 0) { api.getItems("unread", 0, null, null, null, null, any()) } -// verify(atLeast = 1) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Get newer items without connectivity and source filter`() { -// val itemParameter1 = FakeItemParameters() -// val itemParameter2 = FakeItemParameters() -// val itemParameter3 = FakeItemParameters() -// itemParameter2.sourcetitle = "Test" -// itemParameter2.id = "2" -// itemParameter3.sourcetitle = "Other" -// itemParameter3.id = "3" -// coEvery { db.itemsQueries.items().executeAsList() } returns generateTestDBItems(itemParameter1) + -// generateTestDBItems(itemParameter2) + -// generateTestDBItems(itemParameter3) -// -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isItemCachingEnabled() } returns true -// -// initializeRepository() -// repository.sourceFilter = SelfossModel.Source(1, "Test", listOf("tags"),"spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png") -// runBlocking { -// repository.getNewerItems() -// } -// -// assertSame(repository.items.size, 1) -// coVerify(exactly = 0) { api.getItems("unread", 0, null, null, null, null, any()) } -// verify(atLeast = 1) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Get older items`() { -// coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) -// -// initializeRepository() -// repository.items = ArrayList(generateTestApiItem()) -// runBlocking { -// repository.getOlderItems() -// } -// -// assertSame(repository.items.size, 2) -// coVerify(exactly = 1) { api.getItems("unread", 1, null, null, null, null, any()) } -// verify(exactly = 0) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Get all older items`() { -// coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) -// -// initializeRepository() -// repository.items = ArrayList(generateTestApiItem()) -// repository.displayedItems = ItemType.ALL -// runBlocking { -// repository.getOlderItems() -// } -// -// assertSame(repository.items.size, 2) -// coVerify(exactly = 1) { api.getItems("all", 1, null, null, null, null, any()) } -// verify(exactly = 0) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Get older starred items`() { -// coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.StatusAndData(success = true, data = generateTestApiItem()) -// -// initializeRepository() -// repository.displayedItems = ItemType.STARRED -// repository.items = ArrayList(generateTestApiItem()) -// runBlocking { -// repository.getOlderItems() -// } -// -// assertSame(repository.items.size, 2) -// coVerify(exactly = 1) { api.getItems("starred", 1, null, null, null, null, any()) } -// verify(exactly = 0) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Reload badges`() { -// var success = false -// -// initializeRepository() -// runBlocking { -// success = repository.reloadBadges() -// } -// -// assertSame(true, success) -// assertSame(NUMBER_ARTICLES, repository.badgeAll) -// assertSame(NUMBER_UNREAD, repository.badgeUnread) -// assertSame(NUMBER_STARRED, repository.badgeStarred) -// coVerify(atLeast = 1) { api.stats() } -// verify(exactly = 0) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Reload badges without response`() { -// coEvery { api.stats() } returns SelfossModel.StatusAndData(success = false, data = null) -// -// var success = false -// -// initializeRepository() -// runBlocking { -// success = repository.reloadBadges() -// } -// -// assertSame(false, success) -// assertSame(0, repository.badgeAll) -// assertSame(0, repository.badgeUnread) -// assertSame(0, repository.badgeStarred) -// coVerify(atLeast = 1) { api.stats() } -// verify(exactly = 0) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Reload badges without connection`() { -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isItemCachingEnabled() } returns true -// every { db.itemsQueries.items().executeAsList() } returns generateTestDBItems() -// -// var success = false -// -// initializeRepository() -// runBlocking { -// success = repository.reloadBadges() -// } -// -// assertTrue(success) -// assertSame(1, repository.badgeAll) -// assertSame(1, repository.badgeUnread) -// assertSame(1, repository.badgeStarred) -// coVerify(exactly = 0) { api.stats() } -// verify(atLeast = 1) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Reload badges without connection and items caching disabled`() { -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isItemCachingEnabled() } returns false -// every { appSettingsService.isUpdateSourcesEnabled() } returns true -// -// var success = false -// -// initializeRepository() -// runBlocking { -// success = repository.reloadBadges() -// } -// -// assertFalse(success) -// assertSame(0, repository.badgeAll) -// assertSame(0, repository.badgeUnread) -// assertSame(0, repository.badgeStarred) -// coVerify(exactly = 0) { api.stats() } -// verify(exactly = 0) { db.itemsQueries.items().executeAsList()} -// } -// -// @Test -// fun `Get tags`() { -// 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 true -// -// initializeRepository() -// var testTags: List? = null -// runBlocking { -// testTags = repository.getTags() -// } -// -// assertSame(tags, testTags) -// assertNotSame(tagsDB.map { it.toView() }, testTags) -// coVerify(exactly = 1) { api.tags() } -// } -// -// @Test -// fun `Get tags with sources update disabled`() { -// 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 false -// every { appSettingsService.isItemCachingEnabled() } returns true -// -// initializeRepository() -// var testTags: List = emptyList() -// runBlocking { -// testTags = repository.getTags() -// // Tags will be fetched from the database on the second call, thus testTags != tags -// testTags = repository.getTags() -// } -// -// coVerify(exactly = 1) { api.tags() } -// assertNotSame(tags, testTags) -// assertContentEquals(tagsDB.map { it.toView() }, testTags) -// verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() } -// } -// -// @Test -// fun `Get tags with items caching disabled`() { -// 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 -// -// initializeRepository() -// var testTags: List = 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), -// 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 false -// every { appSettingsService.isItemCachingEnabled() } returns false -// -// initializeRepository() -// var testTags: List = emptyList() -// runBlocking { -// testTags = repository.getTags() -// testTags = repository.getTags() -// } -// -// coVerify(exactly = 1) { api.tags() } -// assertNotSame(tags, testTags) -// assertContentEquals(tagsDB.map { it.toView() }, testTags) -// verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() } -// } -// -// @Test -// fun `Get tags without connection`() { -// 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 { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isUpdateSourcesEnabled() } returns true -// every { appSettingsService.isItemCachingEnabled() } returns true -// -// initializeRepository() -// var testTags: List = emptyList() -// runBlocking { -// testTags = repository.getTags() -// } -// -// assertNotSame(tags, testTags) -// assertContentEquals(tagsDB.map { it.toView() }, testTags) -// coVerify(exactly = 0) { api.tags() } -// verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() } -// } -// -// @Test -// fun `Get tags without connection and items caching disabled`() { -// 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 { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isItemCachingEnabled() } returns false -// every { appSettingsService.isUpdateSourcesEnabled() } returns true -// -// initializeRepository() -// var testTags: List = emptyList() -// runBlocking { -// testTags = repository.getTags() -// } -// -// assertSame(emptyList(), testTags) -// coVerify(exactly = 0) { api.tags() } -// verify(exactly = 0) { db.tagsQueries.tags().executeAsList() } -// } -// -// @Test -// fun `Get tags without connection and sources update disabled`() { -// 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 { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isUpdateSourcesEnabled() } returns false -// every { appSettingsService.isItemCachingEnabled() } returns true -// -// initializeRepository() -// var testTags: List = emptyList() -// runBlocking { -// testTags = repository.getTags() -// } -// -// assertNotSame(tags, testTags) -// assertContentEquals(tagsDB.map { it.toView() }, testTags) -// coVerify(exactly = 0) { api.tags() } -// verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() } -// } -// -// @Test -// fun `Get tags without connection and sources update and items caching disabled`() { -// 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 { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isUpdateSourcesEnabled() } returns false -// every { appSettingsService.isItemCachingEnabled() } returns false -// -// initializeRepository() -// var testTags: List = emptyList() -// runBlocking { -// testTags = repository.getTags() -// } -// -// assertContentEquals(tagsDB.map { it.toView() }, testTags) -// coVerify(exactly = 0) { api.tags() } -// verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() } -// } -// -// @Test -// fun `get sources`() { -// 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("1", "First DB source", "Test,second","spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"), -// SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png")) -// -// coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) -// every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB -// initializeRepository() -// var testSources: List? = null -// runBlocking { -// testSources = repository.getSources() -// } -// -// assertSame(sources, testSources) -// assertNotEquals(sourcesDB.map { it.toView() }, testSources) -// coVerify(exactly = 1) { api.sources() } -// } -// -// @Test -// fun `get sources with sources update disabled`() { -// val sources = arrayListOf(SelfossModel.Source(1, "First source", listOf("Test", "second"),"spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"), -// SelfossModel.Source(2, "Second DB source", listOf("second"),"spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png")) -// val sourcesDB = listOf(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 false -// every { appSettingsService.isItemCachingEnabled() } returns true -// coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) -// every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB -// initializeRepository() -// var testSources: List? = null -// runBlocking { -// testSources = repository.getSources() -// // Sources will be fetched from the database on the second call, thus testSources != sources -// testSources = repository.getSources() -// } -// -// coVerify(exactly = 1) { api.sources() } -// assertNotSame(sources, testSources) -// assertContentEquals(sourcesDB.map { it.toView() }, testSources) -// 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("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 -// initializeRepository() -// var testSources: List? = 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"), -// SelfossModel.Source(2, "Second source", listOf("second"),"spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png")) -// val sourcesDB = listOf(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 false -// every { appSettingsService.isItemCachingEnabled() } returns false -// coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) -// every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB -// initializeRepository() -// var testSources: List? = null -// runBlocking { -// testSources = repository.getSources() -// } -// -// assertSame(sources, testSources) -// coVerify(exactly = 1) { api.sources() } -// verify(atLeast = 1) { db.sourcesQueries } -// } -// -// @Test -// fun `get sources without connection`() { -// 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("1", "First DB source", "Test,second","spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"), -// SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png")) -// -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) -// every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB -// initializeRepository() -// var testSources: List? = null -// runBlocking { -// testSources = repository.getSources() -// } -// -// assertContentEquals(sourcesDB.map { it.toView() }, testSources) -// coVerify(exactly = 0) { api.sources() } -// verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() } -// } -// -// @Test -// fun `get sources without connection and 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("1", "First DB source", "Test,second","spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"), -// SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png")) -// -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isItemCachingEnabled() } returns false -// every { appSettingsService.isUpdateSourcesEnabled() } returns true -// coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) -// every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB -// initializeRepository() -// var testSources: List? = null -// runBlocking { -// testSources = repository.getSources() -// } -// -// assertContentEquals(ArrayList(), testSources) -// coVerify(exactly = 0) { api.sources() } -// verify(exactly = 0) { db.sourcesQueries.sources().executeAsList() } -// } -// -// @Test -// fun `get sources without connection and sources update 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("1", "First DB source", "Test,second","spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"), -// SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png")) -// -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isItemCachingEnabled() } returns true -// every { appSettingsService.isUpdateSourcesEnabled() } returns false -// coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) -// every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB -// initializeRepository() -// var testSources: List? = null -// runBlocking { -// testSources = repository.getSources() -// } -// -// assertContentEquals(sourcesDB.map { it.toView() }, testSources) -// coVerify(exactly = 0) { api.sources() } -// verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() } -// } -// -// @Test -// fun `get sources without connection and items caching and sources update 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("1", "First DB source", "Test,second","spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"), -// SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png")) -// -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// every { appSettingsService.isItemCachingEnabled() } returns false -// every { appSettingsService.isUpdateSourcesEnabled() } returns false -// coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources) -// every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB -// initializeRepository() -// var testSources: List? = null -// runBlocking { -// testSources = repository.getSources() -// } -// -// assertContentEquals(sourcesDB.map { it.toView() }, testSources) -// coVerify(exactly = 0) { api.sources() } -// verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() } -// } -// -// @Test -// fun `create source`() { -// coEvery { api.createSourceForVersion(any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.SuccessResponse(true) -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.createSource("test", "https://test.com/feed", "spouts\\rss\\fulltextrss", "Test, New", "") -// } -// -// coVerify(exactly = 1) { api.createSourceForVersion(any(), any(), any(), any(), any(), any()) } -// assertSame(true, response) -// } -// -// @Test -// fun `create source but response fails`() { -// coEvery { api.createSourceForVersion(any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.SuccessResponse(false) -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.createSource("test", "https://test.com/feed", "spouts\\rss\\fulltextrss", "Test, New", "") -// } -// -// coVerify(exactly = 1) { api.createSourceForVersion(any(), any(), any(), any(), any(), any()) } -// assertSame(false, response) -// } -// -// @Test -// fun `create source without connection`() { -// coEvery { api.createSourceForVersion(any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.SuccessResponse(true) -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.createSource("test", "https://test.com/feed", "spouts\\rss\\fulltextrss", "Test, New", "") -// } -// -// coVerify(exactly = 0) { api.createSourceForVersion(any(), any(), any(), any(), any(), any()) } -// assertSame(false, response) -// } -// -// @Test -// fun `delete source`() { -// coEvery { api.deleteSource(any())} returns SelfossModel.SuccessResponse(true) -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.deleteSource(5) -// } -// -// coVerify(exactly = 1) { api.deleteSource(5) } -// assertSame(true, response) -// } -// -// @Test -// fun `delete source but response fails`() { -// coEvery { api.deleteSource(any())} returns SelfossModel.SuccessResponse(false) -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.deleteSource(5) -// } -// -// coVerify(exactly = 1) { api.deleteSource(5) } -// assertSame(false, response) -// } -// -// @Test -// fun `delete source without connection`() { -// coEvery { api.deleteSource(any())} returns SelfossModel.SuccessResponse(false) -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.deleteSource(5) -// } -// -// coVerify(exactly = 0) { api.deleteSource(5) } -// assertSame(false, response) -// } -// -// @Test -// fun `update remote`() { -// coEvery { api.update()} returns SelfossModel.StatusAndData(success = true, data = "finished") -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.updateRemote() -// } -// -// coVerify(exactly = 1) { api.update() } -// assertTrue(response) -// } -// -// @Test -// fun `update remote but response fails`() { -// coEvery { api.update()} returns SelfossModel.StatusAndData(success = false, data = "unallowed access") -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.updateRemote() -// } -// -// coVerify(exactly = 1) { api.update() } -// assertSame(false, response) -// } -// -// @Test -// fun `update remote with unallowed access`() { -// coEvery { api.update()} returns SelfossModel.StatusAndData(success = true, data = "unallowed access") -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.updateRemote() -// } -// -// coVerify(exactly = 1) { api.update() } -// assertSame(false, response) -// } -// -// @Test -// fun `update remote without connection`() { -// coEvery { api.update()} returns SelfossModel.StatusAndData(success = true, data = "undocumented...") -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.updateRemote() -// } -// -// coVerify(exactly = 0) { api.update() } -// assertSame(false, response) -// } -// -// @Test -// fun login() { -// coEvery { api.login() } returns SelfossModel.SuccessResponse(success = true) -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.login() -// } -// -// coVerify(exactly = 1) { api.login() } -// assertSame(true, response) -// } -// -// @Test -// fun `login but response fails`() { -// coEvery { api.login() } returns SelfossModel.SuccessResponse(success = false) -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.login() -// } -// -// coVerify(exactly = 1) { api.login() } -// assertSame(false, response) -// } -// -// @Test -// fun `login but without connection`() { -// coEvery { api.login() } returns SelfossModel.SuccessResponse(success = true) -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// -// initializeRepository() -// var response = false -// runBlocking { -// response = repository.login() -// } -// -// coVerify(exactly = 0) { api.login() } -// assertSame(false, response) -// } -// -// @Test -// fun `refresh login information`() { -// coEvery { api.refreshLoginInformation() } returns Unit -// coEvery { appSettingsService.refreshLoginInformation(any(), any(), any()) } returns Unit -// -// initializeRepository() -// repository.refreshLoginInformation("https://test.com/selfoss/", "login", "password") -// -// coVerify(exactly = 1) { api.refreshLoginInformation() } -// coVerify(exactly = 1) {appSettingsService.refreshLoginInformation("https://test.com/selfoss/", "login", "password")} -// } -// -// @Test -// fun `cache items`() { -// val itemParameter1 = FakeItemParameters() -// val itemParameter2 = FakeItemParameters() -// val itemParameter3 = FakeItemParameters() -// itemParameter2.id = "2" -// itemParameter3.id = "3" -// coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returnsMany listOf( -// SelfossModel.StatusAndData(success = true, data = generateTestApiItem(itemParameter1)), -// SelfossModel.StatusAndData(success = true, data = generateTestApiItem(itemParameter2)), -// SelfossModel.StatusAndData(success = true, data = generateTestApiItem(itemParameter1)), -// ) -// -// initializeRepository() -// repository.tagFilter = SelfossModel.Tag("Tag", "read", 0) -// repository.sourceFilter = SelfossModel.Source( -// 1, -// "First source", -// listOf("Test", "second"), -// "spouts\\rss\\fulltextrss", -// "", -// "d8c92cdb1ef119ea85c4b9205c879ca7.png" -// ) -// repository.searchFilter = "search" -// runBlocking { -// repository.tryToCacheItemsAndGetNewOnes() -// } -// -// coVerify(exactly = 3) { api.getItems(any(), 0, null, null, null, null, 200) } -// } -// -// @Test -// fun `cache items but response fails`() { -// coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.StatusAndData(success = false, data = generateTestApiItem()) -// -// initializeRepository() -// repository.tagFilter = SelfossModel.Tag("Tag", "read", 0) -// repository.sourceFilter = SelfossModel.Source( -// 1, -// "First source", -// listOf("Test", "second"), -// "spouts\\rss\\fulltextrss", -// "", -// "d8c92cdb1ef119ea85c4b9205c879ca7.png" -// ) -// repository.searchFilter = "search" -// runBlocking { -// repository.tryToCacheItemsAndGetNewOnes() -// } -// -// coVerify(exactly = 3) { api.getItems(any(), 0, null, null, null, null, 200) } -// } -// -// @Test -// fun `cache items without connection`() { -// coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns -// SelfossModel.StatusAndData(success = false, data = generateTestApiItem()) -// every { connectivityStatus.isNetworkConnected } returns MutableStateFlow(false) -// -// initializeRepository() -// repository.tagFilter = SelfossModel.Tag("Tag", "read", 0) -// repository.sourceFilter = SelfossModel.Source( -// 1, -// "First source", -// listOf("Test", "second"), -// "spouts\\rss\\fulltextrss", -// "", -// "d8c92cdb1ef119ea85c4b9205c879ca7.png" -// ) -// repository.searchFilter = "search" -// runBlocking { -// repository.tryToCacheItemsAndGetNewOnes() -// } -// -// coVerify(exactly = 0) { api.getItems(any(), 0, null, null, null, null, 200) } -// } -// -// fun initializeRepository() { -// repository = Repository(api, appSettingsService, connectivityStatus, db) -// -// runBlocking { -// repository.updateApiVersion() -// } -// } -//} -// -//fun generateTestDBItems(item : FakeItemParameters = FakeItemParameters()) : List { -// return listOf(ITEM( -// id = item.id, -// datetime = item.datetime, -// title = item.title, -// content = item.content, -// unread = item.unread, -// starred = item.starred, -// thumbnail = item.thumbnail, -// icon = item.icon, -// link = item.link, -// sourcetitle = item.sourcetitle, -// tags = item.tags -//))} -// -//fun generateTestApiItem(item : FakeItemParameters = FakeItemParameters()) : List { -// return listOf( -// SelfossModel.Item( -// id = item.id.toInt(), -// datetime = item.datetime, -// title = item.title, -// content = item.content, -// unread = item.unread, -// starred = item.starred, -// thumbnail = item.thumbnail, -// icon = item.icon, -// link = item.link, -// sourcetitle = item.sourcetitle, -// tags = item.tags.split(',') -// ) -// ) -//} -// -//class FakeItemParameters() { -// var id = "20" -// var datetime = "2022-09-09T03:32:01-04:00" -// val title = "Etica della ricerca sotto i riflettori." -// val content = "

Luigi Campanella, già Presidente SCI

\n

L’etica della scienza è di certo ambito di cui continuiamo a scoprire nuovi aspetti e risvolti.

\n

L’ultimo è quello delle intelligenze artificiali capaci di creare opere complesse basate su immagini e parole memorizzate con il rischio di fake news e di contenuti disturbanti.

\n

Per evitare che ciò accada si sta procedendo filtrando secondo criteri di autocensura i dati da cui l’intelligenza artificiale parte.

\n

Comincia ad intravedersi un futuro prossimo di competizione fra autori umani ed artificiali nel quale sarà importante, quando i loro prodotti saranno indistinguibili, dichiararne l’origine.

\n

Come si comprende, si conferma che gli aspetti etici dell’innovazione e della ricerca si diversificato sempre di più.

\n

La biologia molecolare e la genetica già in passato hanno posto all’attenzione comune aspetti di etica della scienza che hanno indotto a nuove riflessioni circa i limiti delle ricerche.

\n

L’argomento, sempre attuale, torna sulle prime pagine a seguito della pubblicazione di una ricerca della Università di Cambridge che ha sviluppato una struttura cellulare di un topo con un cuore che batte regolarmente.

\n\"\"\"\"

Magdalena Zernicka-Goetz

\n\"\"

Gianluca Amadei

\n

Del gruppo fa parte anche uno scienziato italiano Gianluca Amadei,che dinnanzi alle obiezioni di natura etica sulla realizzazione della vita artificiale si è affrettato a sostenere che non è creare nuove vite il fine primario della ricerca, ma quello di salvare quelle esistenti, di dare contributi essenziali alla medicina citando il caso del fallimento tuttora non interpretato di alcune gravidanze e di superare la sperimentazione animale, così contribuendo positivamente alla soluzione di un altro dilemma etico.

\n

L’embrione sintetico ha ovviamente come primo traguardo il contributo ai trapianti oggi drammaticamente carenti nell’offerta rispetto alla domanda, con attese fino a 4 anni per i trapianti di cuore ed a 2 anni per quelli di fegato. Il lavoro dovrebbe adesso continuare presso l’Ateneo di Padova per creare nuovi organi e nuovi farmaci.

" -// var unread = true -// var starred = true -// val thumbnail = null -// val icon = "ba79e238383ce83c23a169929c8906ef.png" -// val link = "https://ilblogdellasci.wordpress.com/2022/09/09/etica-della-ricerca-sotto-i-riflettori/" -// var sourcetitle = "La Chimica e la Società" -// var tags = "Chimica, Testing" -//} diff --git a/shared/src/iosTest/kotlin/bou/amine/apps/readerforselfossv2/iosTest.kt b/shared/src/iosTest/kotlin/bou/amine/apps/readerforselfossv2/iosTest.kt deleted file mode 100644 index 6df9dfc..0000000 --- a/shared/src/iosTest/kotlin/bou/amine/apps/readerforselfossv2/iosTest.kt +++ /dev/null @@ -1,12 +0,0 @@ -package bou.amine.apps.readerforselfossv2 - -import kotlin.test.Test -import kotlin.test.assertTrue - -class IosGreetingTest { - - @Test - fun testExample() { - assertTrue(Greeting().greeting().contains("iOS"), "Check iOS is mentioned") - } -} \ No newline at end of file