Skip to content

Commit

Permalink
add KoinViewModelFactoryTest
Browse files Browse the repository at this point in the history
  • Loading branch information
hoc081098 committed Feb 15, 2024
1 parent 2bd4eeb commit 472546b
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 17 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,26 @@
`ViewModel`'s `addCloseable()` now immediately closes the `Closeable` if the `ViewModel` has already received a call to `onCleared()`.
Now, this behavior is the same for all targets.

### `kmp-viewmodel-koin`

- **Fix** `koinViewModelFactory`: `CreationExtras` passed to `ViewModelFactory.create` will now be
passed to the constructor of the ViewModel if it's requested.

```kotlin
class MyViewModel(val extras: CreationExtras) : ViewModel()

val myModule: Module = module {
factoryOf(::MyViewModel)
}

val factory = koinViewModelFactory<MyViewModel>(
scope = KoinPlatformTools.defaultContext().get().scopeRegistry.rootScope,
)
val extras = buildCreationExtras { /* ... */ }
val viewModel: MyViewModel = factory.create(extras)
viewModel.extras === extras // true <--- `extras` is the same as `extras` passed to `factory.create(extras)`
```

## [0.6.2] - Feb 5, 2024

### Update dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import org.koin.core.scope.Scope
* with the given [qualifier] and [parameters].
*
* [SavedStateHandle] will be created and passed to the constructor of [VM] if it's requested.
* [CreationExtras] passed to [ViewModelFactory.create] will be passed to the constructor of [VM] if it's requested.
*
* ### Example
* ```kotlin
Expand Down Expand Up @@ -67,6 +68,7 @@ public inline fun <reified VM : ViewModel> koinViewModelFactory(
* with the given [qualifier] and [parameters].
*
* [SavedStateHandle] will be created and passed to the constructor of [VM] if it's requested.
* [CreationExtras] passed to [ViewModelFactory.create] will be passed to the constructor of [VM] if it's requested.
*
* ### Example
* ```kotlin
Expand Down Expand Up @@ -124,19 +126,26 @@ internal class KmpViewModelParametersHolder(
) {

override fun <T> elementAt(i: Int, clazz: KClass<*>): T {
return createSavedStateHandleOrElse(clazz) { super.elementAt(i, clazz) }
return createSavedStateHandleOrCreationExtrasOrElse(clazz) { super.elementAt(i, clazz) }
}

override fun <T> getOrNull(clazz: KClass<*>): T? {
return createSavedStateHandleOrElse(clazz) { super.getOrNull(clazz) }
return createSavedStateHandleOrCreationExtrasOrElse(clazz) { super.getOrNull(clazz) }
}

private inline fun <T> createSavedStateHandleOrElse(clazz: KClass<*>, block: () -> T): T {
return if (clazz == SavedStateHandle::class) {
@Suppress("UNCHECKED_CAST")
extras.createSavedStateHandle() as T
} else {
block()
private inline fun <T> createSavedStateHandleOrCreationExtrasOrElse(clazz: KClass<*>, block: () -> T): T {
return when (clazz) {
SavedStateHandle::class -> {
@Suppress("UNCHECKED_CAST")
extras.createSavedStateHandle() as T
}

CreationExtras::class -> {
@Suppress("UNCHECKED_CAST")
extras as T
}

else -> block()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
package com.hoc081098.kmp.viewmodel.koin

import com.hoc081098.kmp.viewmodel.CreationExtrasKey
import com.hoc081098.kmp.viewmodel.EmptyCreationExtras
import com.hoc081098.kmp.viewmodel.SAVED_STATE_HANDLE_FACTORY_KEY
import com.hoc081098.kmp.viewmodel.SavedStateHandle
import com.hoc081098.kmp.viewmodel.SavedStateHandleFactory
import com.hoc081098.kmp.viewmodel.edit
import com.hoc081098.kmp.viewmodel.buildCreationExtras
import com.hoc081098.kmp.viewmodel.koin.test.TestSavedStateViewModel
import com.hoc081098.kmp.viewmodel.koin.test.TestViewModel
import com.hoc081098.kmp.viewmodel.koin.test.TestViewModelWithExtras
import com.hoc081098.kmp.viewmodel.koin.test.TestViewModelWithParams
import kotlin.jvm.JvmField
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertSame
import org.koin.core.Koin
import org.koin.core.annotation.KoinInternalApi
import org.koin.core.context.startKoin
Expand All @@ -22,10 +26,12 @@ import org.koin.core.module.dsl.factoryOf
import org.koin.core.parameter.parametersOf
import org.koin.dsl.module

val TestViewModelModule = module {
@JvmField
internal val TestViewModelModule = module {
factoryOf(::TestViewModel)
factoryOf(::TestViewModelWithParams)
factoryOf(::TestSavedStateViewModel)
factoryOf(::TestViewModelWithExtras)
}

@OptIn(KoinInternalApi::class)
Expand All @@ -48,7 +54,7 @@ class KoinViewModelFactoryTest {
@Test
fun createViewModelWithoutParams() {
val factory = koinViewModelFactory<TestViewModel>(
scope = koin.scopeRegistry.rootScope
scope = koin.scopeRegistry.rootScope,
)

val viewModel = factory.create(EmptyCreationExtras)
Expand All @@ -63,7 +69,7 @@ class KoinViewModelFactoryTest {

val factory = koinViewModelFactory<TestViewModelWithParams>(
scope = koin.scopeRegistry.rootScope,
parameters = { parametersOf(int, string) }
parameters = { parametersOf(int, string) },
)

val viewModel = factory.create(EmptyCreationExtras)
Expand All @@ -79,17 +85,37 @@ class KoinViewModelFactoryTest {
val value = "value"

val factory = koinViewModelFactory<TestSavedStateViewModel>(
scope = koin.scopeRegistry.rootScope
scope = koin.scopeRegistry.rootScope,
)

val viewModel = factory.create(EmptyCreationExtras.edit {
this[SAVED_STATE_HANDLE_FACTORY_KEY] = SavedStateHandleFactory { SavedStateHandle(mapOf(key to value)) }
})
val viewModel = factory.create(
buildCreationExtras {
this[SAVED_STATE_HANDLE_FACTORY_KEY] = SavedStateHandleFactory {
SavedStateHandle(mapOf(key to value))
}
},
)

assertNotNull(viewModel)
assertEquals(
expected = value,
actual = viewModel.savedStateHandle.get<String>(key),
)
}

@Test
fun createViewModelWithExtras() {
val key = object : CreationExtrasKey<String> {}
val value = "value"
val extras = buildCreationExtras { this[key] = value }

val factory = koinViewModelFactory<TestViewModelWithExtras>(
scope = koin.scopeRegistry.rootScope,
)
val viewModel = factory.create(extras)

assertNotNull(viewModel)
assertSame(expected = extras, actual = viewModel.extras)
assertEquals(expected = value, actual = viewModel.extras[key])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ package com.hoc081098.kmp.viewmodel.koin.test

import com.hoc081098.kmp.viewmodel.ViewModel

internal class TestViewModel: ViewModel()
internal class TestViewModel : ViewModel()

0 comments on commit 472546b

Please sign in to comment.