diff --git a/core/src/testFixtures/kotlin/fake/FakeInputStream.kt b/core/src/testFixtures/kotlin/fake/FakeInputStream.kt new file mode 100644 index 0000000..ca7dd0e --- /dev/null +++ b/core/src/testFixtures/kotlin/fake/FakeInputStream.kt @@ -0,0 +1,8 @@ +package fake + +import io.mockk.mockk +import java.io.InputStream + +class FakeInputStream { + val instance = mockk() +} diff --git a/domains/android/stub/build.gradle b/domains/android/stub/build.gradle new file mode 100644 index 0000000..46ba458 --- /dev/null +++ b/domains/android/stub/build.gradle @@ -0,0 +1,20 @@ +plugins { + id 'kotlin' + id 'java-test-fixtures' +} + +def properties = new Properties() +def localProperties = rootProject.file("local.properties") +if (localProperties.exists()) { + properties.load(rootProject.file("local.properties").newDataInputStream()) +} else { + properties.setProperty("sdk.dir", System.getenv("ANDROID_HOME")) +} + +dependencies { + def androidVer = 31 + kotlinFixtures(it) + testFixturesImplementation testFixtures(project(":core")) + testFixturesImplementation files("${properties.getProperty("sdk.dir")}/platforms/android-${androidVer}/android.jar") + +} \ No newline at end of file diff --git a/domains/android/stub/src/testFixtures/kotlin/fake/FakeContentResolver.kt b/domains/android/stub/src/testFixtures/kotlin/fake/FakeContentResolver.kt new file mode 100644 index 0000000..d353c3f --- /dev/null +++ b/domains/android/stub/src/testFixtures/kotlin/fake/FakeContentResolver.kt @@ -0,0 +1,16 @@ +package fake + +import android.content.ContentResolver +import android.net.Uri +import io.mockk.every +import io.mockk.mockk +import test.delegateReturn + +class FakeContentResolver { + + val instance = mockk() + + fun givenFile(uri: Uri) = every { instance.openInputStream(uri) }.delegateReturn() + + fun givenUriResult(uri: Uri) = every { instance.query(uri, null, null, null, null) }.delegateReturn() +} diff --git a/features/settings/src/test/kotlin/app/dapk/st/settings/FakeCursor.kt b/domains/android/stub/src/testFixtures/kotlin/fake/FakeCursor.kt similarity index 95% rename from features/settings/src/test/kotlin/app/dapk/st/settings/FakeCursor.kt rename to domains/android/stub/src/testFixtures/kotlin/fake/FakeCursor.kt index 39e1d89..30f2de0 100644 --- a/features/settings/src/test/kotlin/app/dapk/st/settings/FakeCursor.kt +++ b/domains/android/stub/src/testFixtures/kotlin/fake/FakeCursor.kt @@ -1,4 +1,4 @@ -package app.dapk.st.settings +package fake import android.database.Cursor import io.mockk.every diff --git a/domains/android/stub/src/testFixtures/kotlin/fake/FakeUri.kt b/domains/android/stub/src/testFixtures/kotlin/fake/FakeUri.kt new file mode 100644 index 0000000..dbca643 --- /dev/null +++ b/domains/android/stub/src/testFixtures/kotlin/fake/FakeUri.kt @@ -0,0 +1,18 @@ +package fake + +import android.net.Uri +import io.mockk.every +import io.mockk.mockk + +class FakeUri { + val instance = mockk() + + fun givenNonHierarchical() { + givenContent(schema = "mail", path = null) + } + + fun givenContent(schema: String, path: String?) { + every { instance.scheme } returns schema + every { instance.path } returns path + } +} \ No newline at end of file diff --git a/domains/store/build.gradle b/domains/store/build.gradle index 325a858..7b6db9a 100644 --- a/domains/store/build.gradle +++ b/domains/store/build.gradle @@ -2,6 +2,7 @@ plugins { id 'kotlin' id 'com.squareup.sqldelight' id 'org.jetbrains.kotlin.plugin.serialization' + id 'java-test-fixtures' } sqldelight { @@ -22,4 +23,6 @@ dependencies { implementation Dependencies.mavenCentral.kotlinSerializationJson implementation Dependencies.mavenCentral.kotlinCoroutinesCore implementation "com.squareup.sqldelight:coroutines-extensions:1.5.3" + + kotlinFixtures(it) } \ No newline at end of file diff --git a/domains/store/src/testFixtures/kotlin/fixture/FakeStoreCleaner.kt b/domains/store/src/testFixtures/kotlin/fixture/FakeStoreCleaner.kt new file mode 100644 index 0000000..19ac519 --- /dev/null +++ b/domains/store/src/testFixtures/kotlin/fixture/FakeStoreCleaner.kt @@ -0,0 +1,6 @@ +package fixture + +import app.dapk.st.domain.StoreCleaner +import io.mockk.mockk + +class FakeStoreCleaner : StoreCleaner by mockk() diff --git a/features/settings/build.gradle b/features/settings/build.gradle index 7866c7e..4a91dc2 100644 --- a/features/settings/build.gradle +++ b/features/settings/build.gradle @@ -12,7 +12,11 @@ dependencies { kotlinTest(it) + androidImportFixturesWorkaround(project, project(":matrix:services:sync")) + androidImportFixturesWorkaround(project, project(":matrix:services:crypto")) androidImportFixturesWorkaround(project, project(":matrix:common")) androidImportFixturesWorkaround(project, project(":core")) + androidImportFixturesWorkaround(project, project(":domains:store")) androidImportFixturesWorkaround(project, project(":domains:android:viewmodel")) + androidImportFixturesWorkaround(project, project(":domains:android:stub")) } \ No newline at end of file diff --git a/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsState.kt b/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsState.kt index ea120d9..467627c 100644 --- a/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsState.kt +++ b/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsState.kt @@ -5,11 +5,11 @@ import app.dapk.st.core.Lce import app.dapk.st.design.components.Route import app.dapk.st.design.components.SpiderPage -data class SettingsScreenState( +internal data class SettingsScreenState( val page: SpiderPage, ) -sealed interface Page { +internal sealed interface Page { data class Root(val content: Lce>) : Page object Security : Page data class ImportRoomKey( @@ -29,7 +29,7 @@ data class NamedUri( val uri: Uri, ) -sealed interface SettingItem { +internal sealed interface SettingItem { val id: Id diff --git a/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsItemFactoryTest.kt b/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsItemFactoryTest.kt index 270c870..6d9be17 100644 --- a/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsItemFactoryTest.kt +++ b/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsItemFactoryTest.kt @@ -1,6 +1,8 @@ package app.dapk.st.settings import app.dapk.st.core.BuildMeta +import internalfixture.aSettingHeaderItem +import internalfixture.aSettingTextItem import org.amshove.kluent.shouldBeEqualTo import org.junit.Test diff --git a/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsViewModelTest.kt b/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsViewModelTest.kt index a56af2d..7d9c152 100644 --- a/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsViewModelTest.kt +++ b/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsViewModelTest.kt @@ -1,22 +1,16 @@ package app.dapk.st.settings import ViewModelTest -import android.content.ContentResolver -import android.database.Cursor -import android.net.Uri import app.dapk.st.core.Lce import app.dapk.st.design.components.SpiderPage -import app.dapk.st.domain.StoreCleaner -import app.dapk.st.matrix.crypto.CryptoService -import app.dapk.st.matrix.sync.SyncService -import fake.FakeCredentialsStore +import fake.* +import fixture.FakeStoreCleaner import fixture.aRoomId -import io.mockk.coEvery -import io.mockk.every -import io.mockk.mockk +import internalfake.FakeSettingsItemFactory +import internalfake.FakeUriFilenameResolver +import internalfixture.aImportRoomKeysPage +import internalfixture.aSettingTextItem import org.junit.Test -import test.delegateReturn -import java.io.InputStream private const val APP_PRIVACY_POLICY_URL = "https://ouchadam.github.io/small-talk/privacy/" private val A_LIST_OF_ROOT_ITEMS = listOf(aSettingTextItem()) @@ -203,71 +197,8 @@ internal class SettingsViewModelTest { } -class FakeInputStream { - val instance = mockk() -} - -fun aSettingTextItem( - id: SettingItem.Id = SettingItem.Id.Ignored, - content: String = "text-content", - subtitle: String? = null -) = SettingItem.Text(id, content, subtitle) - -fun aSettingHeaderItem( - label: String = "header-label", -) = SettingItem.Header(label) - -class FakeContentResolver { - val instance = mockk() - - fun givenFile(uri: Uri) = every { instance.openInputStream(uri) }.delegateReturn() - - fun givenUriResult(uri: Uri) = every { instance.query(uri, null, null, null, null) }.delegateReturn() -} - -internal class FakeSettingsItemFactory { - val instance = mockk() - - fun givenRoot() = every { instance.root() }.delegateReturn() -} - -class FakeStoreCleaner : StoreCleaner by mockk() -class FakeCryptoService : CryptoService by mockk() { - fun givenImportKeys(inputStream: InputStream, passphrase: String) = coEvery { inputStream.importRoomKeys(passphrase) }.delegateReturn() -} - -class FakeSyncService : SyncService by mockk() -class FakeUriFilenameResolver { - val instance = mockk() - - fun givenFilename(uri: Uri) = coEvery { instance.readFilenameFromUri(uri) } -} - - -class FakeUri { - val instance = mockk() - - fun givenNonHierarchical() { - givenContent(schema = "mail", path = null) - } - - fun givenContent(schema: String, path: String?) { - every { instance.scheme } returns schema - every { instance.path } returns path - } -} - @Suppress("UNCHECKED_CAST") private inline fun SpiderPage.updateState(crossinline block: S.() -> S): SpiderPage { require(this.state is S) return (this as SpiderPage).copy(state = block(this.state)) as SpiderPage } - -fun aImportRoomKeysPage( - state: Page.ImportRoomKey = Page.ImportRoomKey() -) = SpiderPage( - route = Page.Routes.importRoomKeys, - label = "Import room keys", - parent = Page.Routes.encryption, - state = state -) diff --git a/features/settings/src/test/kotlin/app/dapk/st/settings/UriFilenameResolverTest.kt b/features/settings/src/test/kotlin/app/dapk/st/settings/UriFilenameResolverTest.kt index e5ff8f4..edf72fd 100644 --- a/features/settings/src/test/kotlin/app/dapk/st/settings/UriFilenameResolverTest.kt +++ b/features/settings/src/test/kotlin/app/dapk/st/settings/UriFilenameResolverTest.kt @@ -2,6 +2,9 @@ package app.dapk.st.settings import android.provider.OpenableColumns import app.dapk.st.core.CoroutineDispatchers +import fake.FakeContentResolver +import fake.FakeCursor +import fake.FakeUri import kotlinx.coroutines.test.runTest import org.amshove.kluent.shouldBeEqualTo import org.junit.Test diff --git a/features/settings/src/test/kotlin/internalfake/FakeSettingsItemFactory.kt b/features/settings/src/test/kotlin/internalfake/FakeSettingsItemFactory.kt new file mode 100644 index 0000000..1b90817 --- /dev/null +++ b/features/settings/src/test/kotlin/internalfake/FakeSettingsItemFactory.kt @@ -0,0 +1,12 @@ +package internalfake + +import app.dapk.st.settings.SettingsItemFactory +import io.mockk.every +import io.mockk.mockk +import test.delegateReturn + +internal class FakeSettingsItemFactory { + val instance = mockk() + + fun givenRoot() = every { instance.root() }.delegateReturn() +} \ No newline at end of file diff --git a/features/settings/src/test/kotlin/internalfake/FakeUriFilenameResolver.kt b/features/settings/src/test/kotlin/internalfake/FakeUriFilenameResolver.kt new file mode 100644 index 0000000..4547c30 --- /dev/null +++ b/features/settings/src/test/kotlin/internalfake/FakeUriFilenameResolver.kt @@ -0,0 +1,12 @@ +package internalfake + +import android.net.Uri +import app.dapk.st.settings.UriFilenameResolver +import io.mockk.coEvery +import io.mockk.mockk + +class FakeUriFilenameResolver { + val instance = mockk() + + fun givenFilename(uri: Uri) = coEvery { instance.readFilenameFromUri(uri) } +} \ No newline at end of file diff --git a/features/settings/src/test/kotlin/internalfixture/PageFixture.kt b/features/settings/src/test/kotlin/internalfixture/PageFixture.kt new file mode 100644 index 0000000..165bb20 --- /dev/null +++ b/features/settings/src/test/kotlin/internalfixture/PageFixture.kt @@ -0,0 +1,13 @@ +package internalfixture + +import app.dapk.st.design.components.SpiderPage +import app.dapk.st.settings.Page + +internal fun aImportRoomKeysPage( + state: Page.ImportRoomKey = Page.ImportRoomKey() +) = SpiderPage( + route = Page.Routes.importRoomKeys, + label = "Import room keys", + parent = Page.Routes.encryption, + state = state +) diff --git a/features/settings/src/test/kotlin/internalfixture/SettingItemFixture.kt b/features/settings/src/test/kotlin/internalfixture/SettingItemFixture.kt new file mode 100644 index 0000000..5625fe7 --- /dev/null +++ b/features/settings/src/test/kotlin/internalfixture/SettingItemFixture.kt @@ -0,0 +1,13 @@ +package internalfixture + +import app.dapk.st.settings.SettingItem + +internal fun aSettingTextItem( + id: SettingItem.Id = SettingItem.Id.Ignored, + content: String = "text-content", + subtitle: String? = null +) = SettingItem.Text(id, content, subtitle) + +internal fun aSettingHeaderItem( + label: String = "header-label", +) = SettingItem.Header(label) \ No newline at end of file diff --git a/matrix/services/crypto/src/testFixtures/kotlin/fake/FakeCryptoService.kt b/matrix/services/crypto/src/testFixtures/kotlin/fake/FakeCryptoService.kt new file mode 100644 index 0000000..40261a3 --- /dev/null +++ b/matrix/services/crypto/src/testFixtures/kotlin/fake/FakeCryptoService.kt @@ -0,0 +1,11 @@ +package fake + +import app.dapk.st.matrix.crypto.CryptoService +import io.mockk.coEvery +import io.mockk.mockk +import test.delegateReturn +import java.io.InputStream + +class FakeCryptoService : CryptoService by mockk() { + fun givenImportKeys(inputStream: InputStream, passphrase: String) = coEvery { inputStream.importRoomKeys(passphrase) }.delegateReturn() +} diff --git a/matrix/services/sync/src/testFixtures/kotlin/fake/FakeSyncService.kt b/matrix/services/sync/src/testFixtures/kotlin/fake/FakeSyncService.kt new file mode 100644 index 0000000..8d40e52 --- /dev/null +++ b/matrix/services/sync/src/testFixtures/kotlin/fake/FakeSyncService.kt @@ -0,0 +1,6 @@ +package fake + +import app.dapk.st.matrix.sync.SyncService +import io.mockk.mockk + +class FakeSyncService : SyncService by mockk() diff --git a/settings.gradle b/settings.gradle index 0bd07ea..ba9cc6b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -20,6 +20,7 @@ include ':features:messenger' include ':features:navigator' include ':features:verification' +include ':domains:android:stub' include ':domains:android:core' include ':domains:android:imageloader' include ':domains:android:work'