-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #34 from f-lab-edu/feature/explore-test
Feature/explore viewmodel 테스트
- Loading branch information
Showing
17 changed files
with
266 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import kr.co.convention.setNamespace | ||
|
||
plugins { | ||
alias(libs.plugins.seedocs.library) | ||
} | ||
|
||
setNamespace("core.testing") | ||
|
||
dependencies { | ||
api(libs.mockk) | ||
api(libs.kotlinx.coroutines.test) | ||
api(libs.mockk.android) | ||
api(libs.koin.test) | ||
api(libs.koin.junit) | ||
api(projects.core.data) | ||
api(libs.turbine) | ||
} |
24 changes: 24 additions & 0 deletions
24
core/testing/src/main/java/kr/co/testing/repository/TestRecentRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package kr.co.testing.repository | ||
|
||
import kotlinx.coroutines.flow.Flow | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.update | ||
import kr.co.data.repository.RecentRepository | ||
import kr.co.model.FileInfo | ||
|
||
class TestRecentRepository: RecentRepository { | ||
|
||
private val recentFilesFlow: MutableStateFlow<List<FileInfo>> = | ||
MutableStateFlow(emptyList()) | ||
|
||
override suspend fun insert(recentFile: FileInfo) { | ||
recentFilesFlow.update { it + recentFile } | ||
} | ||
|
||
override fun get(): Flow<List<FileInfo>> = | ||
recentFilesFlow | ||
|
||
override suspend fun delete(recentFile: FileInfo) { | ||
recentFilesFlow.update { it - recentFile } | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
core/testing/src/main/java/kr/co/testing/rule/CoroutineTestRule.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package kr.co.testing.rule | ||
|
||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.test.UnconfinedTestDispatcher | ||
import kotlinx.coroutines.test.resetMain | ||
import kotlinx.coroutines.test.setMain | ||
import org.junit.rules.TestWatcher | ||
import org.junit.runner.Description | ||
|
||
class CoroutineTestRule : TestWatcher() { | ||
override fun starting(description: Description?) { | ||
super.starting(description) | ||
Dispatchers.setMain(UnconfinedTestDispatcher()) | ||
} | ||
|
||
override fun finished(description: Description?) { | ||
Dispatchers.resetMain() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,21 @@ | ||
package kr.co.di | ||
|
||
import kr.co.explore.ExploreViewModel | ||
import kr.co.util.FileManagerImpl | ||
import kr.co.util.FileManager | ||
import org.koin.core.module.dsl.viewModel | ||
import org.koin.dsl.module | ||
|
||
val exploreModule = | ||
module { | ||
viewModel { | ||
ExploreViewModel( | ||
get() | ||
get(), | ||
get<FileManager>(), | ||
) | ||
} | ||
|
||
single<FileManager> { | ||
FileManagerImpl() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package kr.co.util | ||
|
||
import kr.co.model.FileInfo | ||
|
||
internal fun interface FileManager { | ||
suspend fun readPDFOrDirectory(path: String): List<FileInfo> | ||
} |
44 changes: 44 additions & 0 deletions
44
feature/explore/src/main/java/kr/co/util/FileManagerImpl.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package kr.co.util | ||
|
||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.withContext | ||
import kr.co.model.FileInfo | ||
import java.io.File | ||
import java.nio.file.Files | ||
import java.nio.file.attribute.BasicFileAttributes | ||
import java.nio.file.attribute.FileTime | ||
import java.time.LocalDateTime | ||
import java.time.ZoneId | ||
|
||
internal class FileManagerImpl: FileManager { | ||
override suspend fun readPDFOrDirectory( | ||
path: String, | ||
): List<FileInfo> = withContext(Dispatchers.IO) { | ||
File(path).listFiles()?.filter { !it.isHidden && (it.isDirectory || it.extension == PDF) } | ||
?.map { | ||
val attributes = getFileAttributes(it) | ||
FileInfo( | ||
name = it.name, | ||
path = it.path, | ||
type = FileInfo.Type.from(it.extension), | ||
isDirectory = it.isDirectory, | ||
size = it.length(), | ||
isHidden = it.isHidden, | ||
createdAt = attributes.creationTime().toLocalDateTime(), | ||
lastModified = attributes.lastModifiedTime().toLocalDateTime(), | ||
) | ||
} ?: emptyList() | ||
} | ||
|
||
private fun getFileAttributes(file: File): BasicFileAttributes = | ||
Files.readAttributes(file.toPath(), BasicFileAttributes::class.java) | ||
|
||
private fun FileTime.toLocalDateTime(): LocalDateTime = | ||
LocalDateTime.ofInstant(this.toInstant(), ZoneId.systemDefault()) | ||
|
||
companion object { | ||
internal const val DEFAULT_STORAGE = "/storage/emulated/0" | ||
|
||
private const val PDF = "pdf" | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
120 changes: 120 additions & 0 deletions
120
feature/explore/src/test/kotlin/kr/co/explore/ExploreViewModelTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package kr.co.explore | ||
|
||
import app.cash.turbine.test | ||
import io.mockk.MockKAnnotations | ||
import io.mockk.coEvery | ||
import io.mockk.impl.annotations.MockK | ||
import kotlinx.coroutines.test.runTest | ||
import kr.co.model.ExploreSideEffect | ||
import kr.co.model.ExploreUiIntent | ||
import kr.co.model.FileInfo | ||
import kr.co.model.FileInfo.Type.PDF | ||
import kr.co.testing.repository.TestRecentRepository | ||
import kr.co.testing.rule.CoroutineTestRule | ||
import kr.co.util.FileManager | ||
import org.junit.Before | ||
import org.junit.Rule | ||
import org.junit.Test | ||
import java.time.LocalDateTime | ||
import kotlin.test.assertEquals | ||
|
||
|
||
class ExploreViewModelTest { | ||
|
||
@get: Rule | ||
val coroutineTestRule = CoroutineTestRule() | ||
|
||
private lateinit var viewModel: ExploreViewModel | ||
|
||
private val recentRepository = TestRecentRepository() | ||
|
||
@MockK | ||
private lateinit var fileManager: FileManager | ||
|
||
@Before | ||
fun setup() { | ||
MockKAnnotations.init(this) | ||
viewModel = ExploreViewModel(recentRepository, fileManager) | ||
} | ||
|
||
@Test | ||
fun `Given a path when Init intent is handled then state is updated`() = runTest { | ||
val path = "/path" | ||
val folders = listOf( | ||
FOLDER_DUMMY | ||
) | ||
val files = listOf( | ||
PDF_DUMMY, | ||
PDF_DUMMY | ||
) | ||
|
||
coEvery { fileManager.readPDFOrDirectory(path) } returns folders + files | ||
|
||
viewModel.handleIntent(ExploreUiIntent.Init(path)) | ||
|
||
viewModel.uiState.test { | ||
val state = awaitItem() | ||
assert(state.path == path) | ||
assertEquals(state.files.size, files.size) | ||
assertEquals(state.folders.size, folders.size) | ||
assert(state.folders == folders) | ||
assert(state.files == files) | ||
} | ||
} | ||
|
||
@Test | ||
fun `Given a file when ClickFile intent is handled then navigate to pdf`() = runTest { | ||
val file = PDF_DUMMY | ||
|
||
recentRepository.insert(file) | ||
|
||
viewModel.handleIntent(ExploreUiIntent.ClickFile(file)) | ||
|
||
recentRepository.insert(file) | ||
|
||
viewModel.sideEffect.test { | ||
awaitItem().also { | ||
assert(it is ExploreSideEffect.NavigateToPdf) | ||
assert((it as ExploreSideEffect.NavigateToPdf).path == file.path) | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun `Given a folder when ClickFolder intent is handled then navigate to folder`() = runTest { | ||
val folder = FOLDER_DUMMY | ||
|
||
viewModel.handleIntent(ExploreUiIntent.ClickFolder(folder)) | ||
|
||
viewModel.sideEffect.test { | ||
awaitItem().also { | ||
assert(it is ExploreSideEffect.NavigateToFolder) | ||
assert((it as ExploreSideEffect.NavigateToFolder).path == folder.path) | ||
} | ||
} | ||
} | ||
|
||
companion object { | ||
val PDF_DUMMY = FileInfo( | ||
name = "DUMMY.pdf", | ||
path = "", | ||
type = PDF, | ||
isDirectory = false, | ||
isHidden = false, | ||
size = 0, | ||
createdAt = LocalDateTime.now(), | ||
lastModified = LocalDateTime.now() | ||
) | ||
|
||
val FOLDER_DUMMY = FileInfo( | ||
name = "DUMMY", | ||
path = "", | ||
type = PDF, | ||
isDirectory = true, | ||
isHidden = false, | ||
size = 0, | ||
createdAt = LocalDateTime.now(), | ||
lastModified = LocalDateTime.now() | ||
) | ||
} | ||
} |
Oops, something went wrong.