119 lines
3.9 KiB
Kotlin
119 lines
3.9 KiB
Kotlin
package com.clean.scanner.ui
|
|
|
|
import com.clean.scanner.domain.ScanResult
|
|
import com.clean.scanner.testutil.MainDispatcherRule
|
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
import kotlinx.coroutines.test.advanceUntilIdle
|
|
import kotlinx.coroutines.test.runTest
|
|
import org.junit.Assert.assertEquals
|
|
import org.junit.Assert.assertTrue
|
|
import org.junit.Rule
|
|
import org.junit.Test
|
|
|
|
@OptIn(ExperimentalCoroutinesApi::class)
|
|
class ScannerViewModelTest {
|
|
|
|
@get:Rule
|
|
val mainDispatcherRule = MainDispatcherRule()
|
|
|
|
@Test
|
|
fun onScan_firstSingleScan_updatesStateAndSaves() = runTest {
|
|
val saved = mutableListOf<Pair<String, String>>()
|
|
var now = 1_000L
|
|
val viewModel = ScannerViewModel(
|
|
saveScan = { content, type -> saved += content to type },
|
|
nowProvider = { now }
|
|
)
|
|
|
|
viewModel.onScan(ScanResult(content = "https://example.com", type = "URL"))
|
|
advanceUntilIdle()
|
|
|
|
val state = viewModel.uiState.value
|
|
assertEquals("https://example.com", state.lastResult?.content)
|
|
assertEquals(false, state.analysisEnabled)
|
|
assertEquals(1, state.scanFeedbackNonce)
|
|
assertEquals(0, state.duplicateFeedbackNonce)
|
|
assertEquals(listOf("URL|https://example.com"), state.recentScanKeys)
|
|
assertEquals(listOf("https://example.com" to "URL"), saved)
|
|
}
|
|
|
|
@Test
|
|
fun duplicateScan_afterResume_incrementsDuplicateFeedback() = runTest {
|
|
val saved = mutableListOf<Pair<String, String>>()
|
|
var now = 1_000L
|
|
val viewModel = ScannerViewModel(
|
|
saveScan = { content, type -> saved += content to type },
|
|
nowProvider = { now }
|
|
)
|
|
|
|
val result = ScanResult(content = "ABC", type = "Text")
|
|
viewModel.onScan(result)
|
|
viewModel.resumeScanning()
|
|
|
|
now = 4_000L
|
|
viewModel.onScan(result)
|
|
advanceUntilIdle()
|
|
|
|
val state = viewModel.uiState.value
|
|
assertEquals(2, state.scanFeedbackNonce)
|
|
assertEquals(1, state.duplicateFeedbackNonce)
|
|
assertEquals(2, saved.size)
|
|
}
|
|
|
|
@Test
|
|
fun batchMode_addsUniqueKeepsNewestFirst_andClearWorks() = runTest {
|
|
val saved = mutableListOf<Pair<String, String>>()
|
|
var now = 1_000L
|
|
val viewModel = ScannerViewModel(
|
|
saveScan = { content, type -> saved += content to type },
|
|
nowProvider = { now }
|
|
)
|
|
|
|
viewModel.setBatchMode(true)
|
|
viewModel.onScan(ScanResult(content = "A", type = "Text"))
|
|
|
|
now = 2_000L
|
|
viewModel.onScan(ScanResult(content = "B", type = "Text"))
|
|
|
|
now = 3_600L
|
|
viewModel.onScan(ScanResult(content = "A", type = "Text"))
|
|
advanceUntilIdle()
|
|
|
|
val state = viewModel.uiState.value
|
|
assertEquals(2, state.batchResults.size)
|
|
assertEquals("B", state.batchResults[0].result.content)
|
|
assertEquals(2_000L, state.batchResults[0].timestamp)
|
|
assertEquals("A", state.batchResults[1].result.content)
|
|
assertEquals(1, state.duplicateFeedbackNonce)
|
|
assertEquals(3, state.scanFeedbackNonce)
|
|
assertTrue(state.analysisEnabled)
|
|
|
|
viewModel.clearBatchResults()
|
|
assertTrue(viewModel.uiState.value.batchResults.isEmpty())
|
|
assertEquals(3, saved.size)
|
|
}
|
|
|
|
@Test
|
|
fun sameCodeWithinHoldoff_isIgnored() = runTest {
|
|
val saved = mutableListOf<Pair<String, String>>()
|
|
var now = 1_000L
|
|
val viewModel = ScannerViewModel(
|
|
saveScan = { content, type -> saved += content to type },
|
|
nowProvider = { now }
|
|
)
|
|
|
|
val result = ScanResult(content = "HOLD", type = "Text")
|
|
viewModel.setBatchMode(true)
|
|
viewModel.onScan(result)
|
|
|
|
now = 2_000L
|
|
viewModel.onScan(result)
|
|
advanceUntilIdle()
|
|
|
|
val state = viewModel.uiState.value
|
|
assertEquals(1, state.scanFeedbackNonce)
|
|
assertEquals(1, saved.size)
|
|
assertEquals(1, state.batchResults.size)
|
|
}
|
|
}
|