Files
aiturk-mobil/gradle/libs.versions.toml
T
M57andM57 1c3a5386f4 fix(#472): refactor ChatViewModelTest — Fakes + Turbine, drop Mockk (#474)
* fix(#472): refactor ChatViewModelTest to use Fake* + Turbine

Replace Mockk-heavy test setup with FakeChatPersistenceRepository (+
in-memory FakeChatMessageDao) and add Turbine for Flow assertions.

Changes:
- Add Turbine v1.2.0 dependency (libs.versions.toml + build.gradle.kts)
- Create FakeChatMessageDao – in-memory DAO with MutableStateFlow
- Create FakeChatPersistenceRepository – delegates to FakeDao
- ChatViewModel: make repo injectable (@VisibleForTesting lateinit var)
- Rewrite ChatViewModelTest (751 lines vs 1,212): clearer helpers,
  Turbine test for streaming Flow sequence, same 29 tests with
  identical assertions, ~38% line reduction

Test: ktlint --format passes clean

* fix(#472): address review — constructor injection, ConcurrentHashMap, MockWebServer tests

Addresses all feedback from Sourcery review on PR #474:

Constructor injection (was lateinit var):
- Move repo to ChatViewModel primary constructor with default
- Remove @VisibleForTesting lateinit var + init block assignment
- Tests pass repo directly via constructor

Simplify FakeChatMessageDao:
- Replace manual synchronized(lock) with ConcurrentHashMap
- Same thread safety, 48% less code, no boilerplate lock object

New MockWebServer tests:
- HermesApiServiceMockWebServerTest: 6 tests covering getStatus,
  getSessions, getSessionMessages + edge cases (null fields,
  empty lists, slash-encoded session IDs)

* fix: CI compilation errors — open class, TestScope receiver, runBlocking

Three compilation errors blocking CI:

- ChatPersistenceRepository was final, but FakeChatPersistenceRepository
  extends it → make it open class
- createViewModelWithSession() called advanceUntilIdle (TestScope ext)
  and emit() (suspend) without a TestScope receiver or coroutine ctx →
  make it fun TestScope.xxx() and use tryEmit() for non-suspend emission
- HermesApiServiceMockWebServerTest called suspend API methods from
  regular @Test methods → wrap each test in runBlocking

* fix: test runtime failures — suspend helper + fix JSON escaping

- Use  so emit()
  (suspend) is valid and events are delivered synchronously instead of
  buffered via tryEmit() which was causing 17 test failures
- Fix MalformedJsonException in MockWebServer test by using plain string
  content instead of unescaped JSON-within-JSON

* fix: correct req-id values in ChatViewModelTest — SESSION_CREATE is req-id-3

* fix(test): correct ChatViewModelTest assertions for Fakes+Turbine refactor

- testMessageStreamingFlow: collect streamingState via Turbine
  (ThinkingDelta/MessageToken mutate streamingState, not uiState)
- testToolExecution_finalizesPreviousStreamingMessage:
  account for messages[0] = "Session created" system message
- testMessageStart_finalizesPreviousStreamingMessage:
  same index offset (messages[1] is the finalized stream)
- testClarifyRequestCustomResponse: options is emptyList(), not null;
  message count is 3 (session-create + user clarify reply)

Fixes CI failures introduced in PR #474.

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
2026-07-05 18:59:36 +03:00

90 lines
5.2 KiB
TOML

[versions]
androidGradlePlugin = "9.0.1"
androidxCore = "1.18.0"
androidxLifecycle = "2.10.0"
androidxActivity = "1.13.0"
androidxComposeBom = "2026.03.01"
androidxTest = "1.7.0"
androidxTestExt = "1.3.0"
androidxTestRunner = "1.7.0"
androidxTestEspresso = "3.7.0"
coroutines = "1.11.0"
junit = "4.13.2"
junit5 = "6.1.1"
junitPlatform = "6.1.1"
kotlin = "2.4.0"
# standalone per KSP 2.0+ guidance — NOT kotlinVersion-kspVersion; easy
# to miss during Kotlin upgrades since it no longer tracks the Kotlin version.
ksp = "2.3.9"
nav3Core = "1.0.1"
lifecycleViewmodelNav3 = "2.10.0"
leakcanary = "2.14"
okhttp = "5.4.0"
retrofit = "3.0.0"
gson = "2.14.0"
securityCrypto = "1.0.0"
mockk = "1.14.11"
turbine = "1.2.0"
coil = "2.7.0"
room = "2.7.1"
sqlcipher = "4.16.0"
[libraries]
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidxCore" }
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidxActivity" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3"}
androidx-compose-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended" }
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui"}
androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview"}
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4"}
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling"}
androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest"}
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidxLifecycle" }
androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidxLifecycle" }
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidxLifecycle" }
androidx-test-core = { module = "androidx.test:core", version.ref = "androidxTest" }
androidx-test-ext-junit = { module = "androidx.test.ext:junit", version.ref = "androidxTestExt" }
androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidxTestEspresso" }
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidxTestRunner" }
junit = { module = "junit:junit", version.ref = "junit" }
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit5" }
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit5" }
junit-vintage-engine = { module = "org.junit.vintage:junit-vintage-engine", version.ref = "junit5" }
junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher", version.ref = "junitPlatform" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
leakcanary-android = { module = "com.squareup.leakcanary:leakcanary-android", version.ref = "leakcanary" }
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
mockk-android = { module = "io.mockk:mockk-android", version.ref = "mockk" }
turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" }
androidx-navigation3-runtime = { module = "androidx.navigation3:navigation3-runtime", version.ref = "nav3Core" }
androidx-navigation3-ui = { module = "androidx.navigation3:navigation3-ui", version.ref = "nav3Core" }
androidx-lifecycle-viewmodel-navigation3 = { module = "androidx.lifecycle:lifecycle-viewmodel-navigation3", version.ref = "lifecycleViewmodelNav3" }
# Networking
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
okhttp-mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "okhttp" }
okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
retrofit-converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
# Security
androidx-security-crypto = { module = "androidx.security:security-crypto", version.ref = "securityCrypto" }
# Database (Room)
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
sqlcipher = { module = "net.zetetic:sqlcipher-android", version.ref = "sqlcipher" }
# Image loading
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
room = { id = "androidx.room", version.ref = "room" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }