Skip to content

Commit

Permalink
Merge pull request #114 from kosenda/test/add-test-6
Browse files Browse the repository at this point in the history
:feature:makecolorのViewModelのテスト作成
  • Loading branch information
kosenda authored May 13, 2023
2 parents 50464a2 + f882656 commit 0624b9a
Show file tree
Hide file tree
Showing 8 changed files with 517 additions and 0 deletions.
1 change: 1 addition & 0 deletions core/mock/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ dependencies {
implementation(project(":core:data"))
implementation(project(":core:model"))
implementation(project(":core:util"))
implementation(libs.compose.color.picker)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package kosenda.makecolor.core.mock

import com.godaddy.android.colorpicker.HsvColor

class MockHsvColor {
val item = HsvColor(hue = 180f, saturation = 0.9f, value = 0.9f, alpha = 1f)
}
1 change: 1 addition & 0 deletions feature/makecolor/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ android {
dependencies {
implementation(project(":core:data"))
implementation(project(":core:domain"))
implementation(project(":core:mock"))
implementation(project(":core:model"))
implementation(project(":core:resource"))
implementation(project(":core:ui"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package kosenda.makecolor.feature.viewmodel

import com.google.common.truth.Truth.assertThat
import kosenda.makecolor.core.domain.InputColorTextUseCase
import kosenda.makecolor.core.domain.UpdateColorDataUseCase
import kosenda.makecolor.core.domain.UpdateOtherColorUseCase
import kosenda.makecolor.core.model.data.CMYKColor
import kosenda.makecolor.core.model.data.ColorTypeWithHex
import kosenda.makecolor.core.model.data.HSVColor
import kosenda.makecolor.core.model.data.RGBColor
import kosenda.makecolor.core.util.hexToRGB
import org.junit.Test

class InputTextViewModelImplTest {

private val viewModel = InputTextViewModelImpl(
inputColorTextUseCase = InputColorTextUseCase(),
updateColorDataUseCase = UpdateColorDataUseCase(
updateOtherColorUseCase = UpdateOtherColorUseCase()
),
updateOtherColorUseCase = UpdateOtherColorUseCase(),
)

@Test
fun updateSelectColorType_everyIndex_settingColorType() {
// Indexを設定したときにUiStateのSelectColorTypeが設定されることを確認
assertThat(viewModel.uiState.value.selectColorType).isEqualTo(ColorTypeWithHex.RGB)
viewModel.updateSelectColorType(ColorTypeWithHex.CMYK.index)
assertThat(viewModel.uiState.value.selectColorType).isEqualTo(ColorTypeWithHex.CMYK)
viewModel.updateSelectColorType(ColorTypeWithHex.RGB.index)
assertThat(viewModel.uiState.value.selectColorType).isEqualTo(ColorTypeWithHex.RGB)
viewModel.updateSelectColorType(ColorTypeWithHex.HSV.index)
assertThat(viewModel.uiState.value.selectColorType).isEqualTo(ColorTypeWithHex.HSV)
viewModel.updateSelectColorType(ColorTypeWithHex.HEX.index)
assertThat(viewModel.uiState.value.selectColorType).isEqualTo(ColorTypeWithHex.HEX)
}

@Test
fun updateInputText_rgbColorAndNotNumValue_errorTextIsNotNull() {
// RGBColorと数値以外の文字列を設定したときにUiStateのErrorTextが設定されることを確認
assertThat(viewModel.updateInputText(RGBColor.RED, "text")).isNotNull()
}

@Test
fun updateInputText_rgbColorAndNumValue_errorTextIsNullAndSettingTextRGB() {
// RGBColorと数値の文字列を設定したときにErrorTextがnullかつUiStateのColorDataが設定されることを確認
assertThat(viewModel.uiState.value.textRGB.red).isEqualTo("")
val newRedValue = "50"
assertThat(viewModel.updateInputText(RGBColor.RED, newRedValue)).isNull()
assertThat(viewModel.uiState.value.textRGB.red).isEqualTo(newRedValue)
}

@Test
fun updateInputText_rgbColorAndNumValue_settingColorData() {
// RGBColorと数値の文字列を設定したときにUiStateのColorDataが設定されることを確認
val originRedValue = viewModel.uiState.value.colorData.rgb.red
val newRedValue = (RGBColor.RED.maxValue - originRedValue).toString()
viewModel.updateInputText(RGBColor.RED, newRedValue)
assertThat(viewModel.uiState.value.colorData.rgb.red.toString()).isEqualTo(newRedValue)
}

@Test
fun updateInputText_cmykColorAndNotNumValue_errorTextIsNotNull() {
// CMYKColorと数値以外の文字列を設定したときにUiStateのErrorTextが設定されることを確認
assertThat(viewModel.updateInputText(CMYKColor.CYAN, "text")).isNotNull()
}

@Test
fun updateInputText_cmykColorAndNumValue_errorTextIsNullAndSettingTextCMYK() {
// CMYKColorと数値の文字列を設定したときにErrorTextがnullかつUiStateのColorDataが設定されることを確認
assertThat(viewModel.uiState.value.textCMYK.cyan).isEqualTo("")
val newCyanValue = "50"
assertThat(viewModel.updateInputText(CMYKColor.CYAN, newCyanValue)).isNull()
assertThat(viewModel.uiState.value.textCMYK.cyan).isEqualTo(newCyanValue)
}

@Test
fun updateInputText_cmykColorAndNumValue_settingColorData() {
// CMYKColorと数値の文字列を設定したときにUiStateのColorDataが設定されることを確認
val originCyanValue = viewModel.uiState.value.colorData.cmyk.cyan
val newCyanValue = (CMYKColor.CYAN.maxValue - originCyanValue).toString()
viewModel.updateInputText(CMYKColor.CYAN, newCyanValue)
assertThat(viewModel.uiState.value.colorData.cmyk.cyan.toString()).isEqualTo(newCyanValue)
}

@Test
fun updateInputText_hsvColorAndNotNumValue_errorTextIsNotNull() {
// HSVColorと数値以外の文字列を設定したときにUiStateのErrorTextが設定されることを確認
assertThat(viewModel.updateInputText(HSVColor.HUE, "text")).isNotNull()
}

@Test
fun updateInputText_hsvColorAndNumValue_errorTextIsNullAndSettingTextHSV() {
// HSVColorと数値の文字列を設定したときにErrorTextがnullかつUiStateのColorDataが設定されることを確認
assertThat(viewModel.uiState.value.textHSV.hue).isEqualTo("")
val newHueValue = "50"
assertThat(viewModel.updateInputText(HSVColor.HUE, newHueValue)).isNull()
assertThat(viewModel.uiState.value.textHSV.hue).isEqualTo(newHueValue)
}

@Test
fun updateInputText_hsvColorAndNumValue_settingColorData() {
// HSVColorと数値の文字列を設定したときにUiStateのColorDataが設定されることを確認
val originHueValue = viewModel.uiState.value.colorData.hsv.hue
val newHueValue = (HSVColor.HUE.maxValue - originHueValue).toString()
viewModel.updateInputText(HSVColor.HUE, newHueValue)
assertThat(viewModel.uiState.value.colorData.hsv.hue.toString()).isEqualTo(newHueValue)
}

@Test
fun updateInputText_hexColorIsInvalid_errorTextIsNotNull() {
// HEXColorと不正な文字列を設定したときにUiStateのErrorTextが設定されることを確認
assertThat(viewModel.updateInputText("TEST")).isNotNull()
}

@Test
fun updateInputText_hexColor_errorTextIsNullAndSettingHEX() {
// HEXColorとRGBの文字列を設定したときにErrorTextがnullかつUiStateのColorDataが設定されることを確認
assertThat(viewModel.uiState.value.hex).isEqualTo("")
val newHEX = "FFFFFF"
assertThat(viewModel.updateInputText(newHEX)).isNull()
assertThat(viewModel.uiState.value.hex).isEqualTo(newHEX)
}

@Test
fun updateInputText_hexColor_settingColorData() {
// HEXColorとRGBの文字列を設定したときにUiStateのColorDataが設定されることを確認
val newHEX = "FFFFFF"
val newRGB = hexToRGB(hex = newHEX)
viewModel.updateInputText(newHEX)
assertThat(viewModel.uiState.value.colorData.rgb.red).isEqualTo(newRGB.red)
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package kosenda.makecolor.feature.viewmodel

import android.content.Context
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
import androidx.navigation.NavBackStackEntry
import androidx.test.core.app.ApplicationProvider
import com.google.common.truth.Truth.assertThat
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import io.mockk.spyk
import kosenda.makecolor.core.domain.FetchCategoriesUseCase
import kosenda.makecolor.core.domain.UpdateOtherColorUseCase
import kosenda.makecolor.core.mock.FakeColorRepository
import kosenda.makecolor.core.mock.MockCategory
import kosenda.makecolor.core.testing.MainDispatcherRule
import kosenda.makecolor.core.ui.data.ColorIndex
import kosenda.makecolor.core.util.colorToRGB
import kosenda.makecolor.core.util.convertDisplayStringListFromCategories
import kosenda.makecolor.core.util.rgbToColorData
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Assert
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@ExperimentalCoroutinesApi
@RunWith(RobolectricTestRunner::class)
class MergeViewModelImplTest {

@get: Rule
val mainDispatcherRule = MainDispatcherRule()

private val context = ApplicationProvider.getApplicationContext<Context>()
private val fetchCategoriesUseCase: FetchCategoriesUseCase = spyk(
FetchCategoriesUseCase(colorRepository = FakeColorRepository())
)
private val viewModel = MergeViewModelImpl(
ioDispatcher = mainDispatcherRule.testDispatcher,
updateOtherColorUseCase = UpdateOtherColorUseCase(),
fetchCategoriesUseCase = fetchCategoriesUseCase,
)

@Test
fun init_firstIndex_updateUiState1() {
// 初期化時にNavBackStackEntryからUiStateが更新されることを確認
val originSelectHex1 = viewModel.uiState.value.selectHex1
val newHex = "Test"
val navBackStackEntry = mockk<NavBackStackEntry>(relaxed = true)
coEvery {
navBackStackEntry.savedStateHandle.get<String>(key = "newHex")
} returns newHex
coEvery {
navBackStackEntry.savedStateHandle.get<Int>(key = "index")
} returns ColorIndex.FIRST.num
viewModel.init(navBackStackEntry)
assertThat(viewModel.uiState.value.selectHex1).isEqualTo(newHex)
assertThat(newHex).isNotEqualTo(originSelectHex1)
}

@Test
fun init_secondIndex_updateUiState2() {
// 初期化時にNavBackStackEntryからUiStateが更新されることを確認
val originSelectHex2 = viewModel.uiState.value.selectHex2
val newHex = "Test"
val navBackStackEntry = mockk<NavBackStackEntry>(relaxed = true)
coEvery {
navBackStackEntry.savedStateHandle.get<String>(key = "newHex")
} returns newHex
coEvery {
navBackStackEntry.savedStateHandle.get<Int>(key = "index")
} returns ColorIndex.SECOND.num
viewModel.init(navBackStackEntry)
assertThat(viewModel.uiState.value.selectHex2).isEqualTo(newHex)
assertThat(newHex).isNotEqualTo(originSelectHex2)
}

@Test
fun init_undefinedIndex_throwIllegalArgumentException() {
// 初期化時にNavBackStackEntryからUiStateが更新されることを確認
val navBackStackEntry = mockk<NavBackStackEntry>(relaxed = true)
coEvery {
navBackStackEntry.savedStateHandle.get<Int>(key = "index")
} returns 0
coEvery {
navBackStackEntry.savedStateHandle.get<String>(key = "newHex")
} returns "Test"
Assert.assertThrows(IllegalArgumentException::class.java) {
viewModel.init(navBackStackEntry)
}
}

@Test
fun fetchCategories_fetchCategoriesUseCase_isCalledAndSetUiState() = runTest {
// デフォルトのカテゴリーが取得されてUiStateが更新されることを確認
coEvery { fetchCategoriesUseCase(any()) } returns MockCategory().list
assertThat(viewModel.uiState.value.categories).isEmpty()
viewModel.fetchCategories(defaultCategories = listOf())
assertThat(viewModel.uiState.value.categories).isNotEmpty()
assertThat(viewModel.uiState.value.selectCategory1).isEqualTo(MockCategory().list.first())
assertThat(viewModel.uiState.value.selectCategory2).isEqualTo(MockCategory().list.first())
assertThat(viewModel.uiState.value.displayCategory)
.isEqualTo(convertDisplayStringListFromCategories(MockCategory().list))
coVerify { fetchCategoriesUseCase(any()) }
}

@Test
fun updateColorData_newColor_isChanged() {
// 色の更新ができることを確認
val isRed = viewModel.uiState.value.colorData == rgbToColorData(colorToRGB(Color.Red))
val newColor = if (isRed) Color.Blue else Color.Red
assertThat(viewModel.uiState.value.colorData)
.isNotEqualTo(rgbToColorData(colorToRGB(newColor)))
viewModel.updateColorData(color = newColor)
assertThat(viewModel.uiState.value.colorData)
.isEqualTo(rgbToColorData(colorToRGB(newColor)))
}

@Ignore("実機でするテスト")
@Test
fun createBitmap_value_isNotNull() {
// Bitmapの生成ができることを確認
assertThat(viewModel.uiState.value.bitmap).isNull()
viewModel.createBitmap(
hex1 = "FFFFFF",
hex2 = "000000",
btmHeight = 100f,
btmWidth = 100f,
density = Density(context),
layoutDirection = LayoutDirection.Rtl,
)
assertThat(viewModel.uiState.value.bitmap).isNotNull()
}

@Ignore("実機でするテスト")
@Test
fun resetBitmap_once_isNull() {
// Bitmapのリセットができることを確認
every { viewModel.createBitmap(any(), any(), any(), any(), any(), any()) } returns mockk("Bitmap")
assertThat(viewModel.uiState.value.bitmap).isNotNull()
viewModel.resetBitmap()
assertThat(viewModel.uiState.value.bitmap).isNull()
}

@Test
fun updateSelectCategory1_index_updateUiState() {
// カテゴリー1が更新されることを確認
coEvery { fetchCategoriesUseCase(any()) } returns MockCategory().list
viewModel.fetchCategories(defaultCategories = listOf())
val originSelectCategory1 = viewModel.uiState.value.selectCategory1
val index = 1
viewModel.updateSelectCategory1(index)
assertThat(viewModel.uiState.value.selectCategory1)
.isNotEqualTo(originSelectCategory1)
assertThat(viewModel.uiState.value.selectCategory1)
.isEqualTo(viewModel.uiState.value.categories[index])
}

@Test
fun updateSelectCategory2_index_updateUiState() {
// カテゴリー2が更新されることを確認
coEvery { fetchCategoriesUseCase(any()) } returns MockCategory().list
viewModel.fetchCategories(defaultCategories = listOf())
val originSelectCategory2 = viewModel.uiState.value.selectCategory2
val index = 1
viewModel.updateSelectCategory2(index)
assertThat(viewModel.uiState.value.selectCategory2)
.isNotEqualTo(originSelectCategory2)
assertThat(viewModel.uiState.value.selectCategory2)
.isEqualTo(viewModel.uiState.value.categories[index])
}
}
Loading

0 comments on commit 0624b9a

Please sign in to comment.