Первые тесты

This commit is contained in:
2026-05-19 00:48:07 +03:00
parent fd6f2e5879
commit eecaf44b72
58 changed files with 1634 additions and 501 deletions

View File

@@ -1,3 +1,5 @@
import java.util.Properties
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.compose.compiler)
@@ -5,6 +7,13 @@ plugins {
alias(libs.plugins.ksp)
}
val localProps = Properties().apply {
val file = rootProject.file("local.properties")
if (file.exists()) {
file.inputStream().use { load(it) }
}
}
android {
namespace = "com.github.nullptroma.wallenc.app"
compileSdk = 37
@@ -17,6 +26,12 @@ android {
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments["yandex.oauth.token"] =
localProps.getProperty("yandex.test.oauth.token").orEmpty()
testInstrumentationRunnerArguments["yandex.user.id"] =
localProps.getProperty("yandex.test.user.id").orEmpty()
testInstrumentationRunnerArguments["yandex.vault.uuid"] =
localProps.getProperty("yandex.test.vault.uuid").orEmpty()
vectorDrawables {
useSupportLibrary = true
}
@@ -78,6 +93,14 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(libs.kotlinx.coroutines.test)
androidTestImplementation(libs.room.testing)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.okhttp3)
androidTestImplementation(libs.retrofit)
androidTestImplementation(libs.retrofit.converter.jackson)
androidTestImplementation(libs.jackson.module.kotlin)
androidTestImplementation(libs.jackson.datatype.jsr310)
implementation(project(":domain"))
implementation(project(":usecases"))

View File

@@ -1,24 +0,0 @@
package com.github.nullptroma.wallenc.app
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.github.nullptroma.wallenc.app", appContext.packageName)
}
}

View File

@@ -0,0 +1,53 @@
package com.github.nullptroma.wallenc.app.integration.yandex
import android.util.Log
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.github.nullptroma.wallenc.infrastructure.android.db.app.AppDb
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
/**
* Ручной helper: после входа в Yandex через приложение печатает в Logcat маскированный
* токен и подсказку для local.properties. Запускать вручную из Android Studio.
*/
@RunWith(AndroidJUnit4::class)
@Ignore("Manual: export Yandex credentials to local.properties")
class ExportYandexTestCredentialsTest {
@Test
fun printFirstAccountCredentialsToLogcat() {
val context = ApplicationProvider.getApplicationContext<android.content.Context>()
val db = Room.databaseBuilder(context, AppDb::class.java, "wallenc.db")
.build()
try {
val row = runBlocking {
db.yandexAccountDao.observeAll().first().firstOrNull()
}
if (row == null) {
Log.i(TAG, "No Yandex accounts in DB. Link a vault in the app first.")
return
}
Log.i(TAG, "Add to local.properties:")
Log.i(TAG, "yandex.test.oauth.token=<copy full token from app debug storage if needed>")
Log.i(TAG, "yandex.test.oauth.token.prefix=${maskToken(row.oauthToken)}")
Log.i(TAG, "yandex.test.user.id=${row.yandexUserId}")
Log.i(TAG, "yandex.test.vault.uuid=${row.vaultUuid}")
} finally {
db.close()
}
}
private fun maskToken(token: String): String {
if (token.length <= 8) return "***"
return token.take(4) + "" + token.takeLast(4)
}
companion object {
private const val TAG = "WallencYandexExport"
}
}

View File

@@ -0,0 +1,66 @@
package com.github.nullptroma.wallenc.app.integration.yandex
import com.github.nullptroma.wallenc.domain.vault.network.yandexdisk.YandexDiskApiFactory
import com.github.nullptroma.wallenc.domain.vault.network.yandexdisk.repository.YandexDiskRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@RunWith(JUnit4::class)
class YandexDiskLiveIntegrationTest {
private lateinit var repository: YandexDiskRepository
private val testFolder = "disk:/wallenc-integration-test"
private val probeFileName = "wallenc-probe.txt"
private val probePath = "$testFolder/$probeFileName"
private val probePayload = "wallenc-integration-probe".encodeToByteArray()
@Before
fun setUp() {
YandexTestCredentials.assumePresent()
val token = YandexTestCredentials.oauthToken()!!
repository = YandexDiskApiFactory.createRepositoryWithToken(token, Dispatchers.IO)
runBlocking {
runCatching { repository.createFolder(testFolder) }
runCatching {
repository.uploadBytes(probePath, probePayload, overwrite = true)
}
}
}
@After
fun tearDown() = runBlocking {
runCatching { repository.delete(probePath, permanently = true) }
}
@Test
fun diskInfoReturnsQuota() = runBlocking {
val info = repository.diskInfo()
assertNotNull(info.totalSpace)
assertTrue(info.totalSpace!! > 0)
}
@Test
fun listTestFolderDoesNotThrow() = runBlocking {
val result = repository.list(testFolder, limit = 10, offset = 0)
assertNotNull(result)
}
@Test
fun uploadAndDownloadRoundTrip() = runBlocking {
val path = "$testFolder/roundtrip-${System.currentTimeMillis()}.bin"
try {
repository.uploadBytes(path, probePayload, overwrite = true)
val downloaded = repository.openDownloadStream(path).use { it.readBytes() }
assertTrue(downloaded.contentEquals(probePayload))
} finally {
runCatching { repository.delete(path, permanently = true) }
}
}
}

View File

@@ -0,0 +1,19 @@
package com.github.nullptroma.wallenc.app.integration.yandex
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assume.assumeFalse
object YandexTestCredentials {
fun oauthToken(): String? =
InstrumentationRegistry.getArguments().getString("yandex.oauth.token")?.takeIf { it.isNotBlank() }
fun userId(): String? =
InstrumentationRegistry.getArguments().getString("yandex.user.id")?.takeIf { it.isNotBlank() }
fun vaultUuid(): String? =
InstrumentationRegistry.getArguments().getString("yandex.vault.uuid")?.takeIf { it.isNotBlank() }
fun assumePresent(message: String = "Добавьте yandex.test.oauth.token в local.properties") {
assumeFalse(message, oauthToken().isNullOrBlank())
}
}

View File

@@ -2,12 +2,12 @@ package com.github.nullptroma.wallenc.app.di.modules.data
import com.github.nullptroma.wallenc.app.di.modules.app.IoDispatcher
import com.github.nullptroma.wallenc.domain.interfaces.IStorageSyncGroupStore
import com.github.nullptroma.wallenc.domain.vault.db.app.dao.StorageKeyMapDao
import com.github.nullptroma.wallenc.domain.vault.db.app.dao.StorageSyncGroupDao
import com.github.nullptroma.wallenc.domain.vault.db.app.dao.YandexAccountDao
import com.github.nullptroma.wallenc.domain.vault.db.app.repository.StorageKeyMapRepository
import com.github.nullptroma.wallenc.domain.vault.db.app.repository.StorageSyncGroupRepository
import com.github.nullptroma.wallenc.domain.vault.db.app.repository.YandexAccountRepository
import com.github.nullptroma.wallenc.infrastructure.android.db.app.dao.StorageKeyMapDao
import com.github.nullptroma.wallenc.infrastructure.android.db.app.dao.StorageSyncGroupDao
import com.github.nullptroma.wallenc.infrastructure.android.db.app.dao.YandexAccountDao
import com.github.nullptroma.wallenc.infrastructure.android.db.app.repository.StorageKeyMapRepository
import com.github.nullptroma.wallenc.infrastructure.android.db.app.repository.StorageSyncGroupRepository
import com.github.nullptroma.wallenc.infrastructure.android.db.app.repository.YandexAccountRepository
import com.github.nullptroma.wallenc.domain.vault.ports.StorageKeyMapStore
import com.github.nullptroma.wallenc.domain.vault.ports.YandexAccountStore
import dagger.Module

View File

@@ -1,12 +1,12 @@
package com.github.nullptroma.wallenc.app.di.modules.data
import android.content.Context
import com.github.nullptroma.wallenc.domain.vault.db.RoomFactory
import com.github.nullptroma.wallenc.domain.vault.db.app.IAppDb
import com.github.nullptroma.wallenc.domain.vault.db.app.dao.StorageKeyMapDao
import com.github.nullptroma.wallenc.domain.vault.db.app.dao.StorageMetaInfoDao
import com.github.nullptroma.wallenc.domain.vault.db.app.dao.StorageSyncGroupDao
import com.github.nullptroma.wallenc.domain.vault.db.app.dao.YandexAccountDao
import com.github.nullptroma.wallenc.infrastructure.android.db.RoomFactory
import com.github.nullptroma.wallenc.infrastructure.android.db.app.IAppDb
import com.github.nullptroma.wallenc.infrastructure.android.db.app.dao.StorageKeyMapDao
import com.github.nullptroma.wallenc.infrastructure.android.db.app.dao.StorageMetaInfoDao
import com.github.nullptroma.wallenc.infrastructure.android.db.app.dao.StorageSyncGroupDao
import com.github.nullptroma.wallenc.infrastructure.android.db.app.dao.YandexAccountDao
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals name="task_notification_group_subtext">
<item quantity="one">Выполняется %d задача</item>
<item quantity="few">Выполняется %d задачи</item>
<item quantity="many">Выполняется %d задач</item>
<item quantity="other">Выполняется %d задач</item>
</plurals>
<plurals name="task_notification_more_tasks">
<item quantity="one">ещё %d</item>
<item quantity="few">ещё %d</item>
<item quantity="many">ещё %d</item>
<item quantity="other">ещё %d</item>
</plurals>
</resources>

View File

@@ -1,17 +0,0 @@
package com.github.nullptroma.wallenc.app
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}