refactor(skills): extract SkillListFilter and SkillScanPresentation
Separate pure skill filtering and scan presentation helpers. Wire into SkillsScreen with unit test coverage.
This commit is contained in:
1 parent
6876db0393
commit
9eaf9663f3
5 files changed
+323
-54
No files matched your search
@@ -0,0 +1,130 @@
|
||||
package com.m57.hermescontrol.ui.skills
|
||||
|
||||
import com.m57.hermescontrol.data.model.Skill
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class SkillListFilterTest {
|
||||
private val sampleSkills =
|
||||
listOf(
|
||||
Skill(
|
||||
name = "code-review",
|
||||
category = "dev",
|
||||
description = "Automated code review assistant",
|
||||
enabled = true,
|
||||
source = "built-in",
|
||||
),
|
||||
Skill(
|
||||
name = "deploy-bot",
|
||||
category = "ops",
|
||||
description = "Deploy to production environments",
|
||||
enabled = false,
|
||||
source = "hub",
|
||||
),
|
||||
Skill(
|
||||
name = "image-gen",
|
||||
category = "creative",
|
||||
description = "Generate creative assets",
|
||||
enabled = true,
|
||||
source = "hub",
|
||||
),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `filterSkills empty query and all statuses returns all`() {
|
||||
val result =
|
||||
SkillListFilter.filterSkills(
|
||||
skills = sampleSkills,
|
||||
query = "",
|
||||
selectedStatus = SkillFilter.ALL_STATUSES,
|
||||
selectedCategory = CATEGORY_ALL,
|
||||
sourceFilter = null,
|
||||
)
|
||||
assertEquals(3, result.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `filterSkills filters by search query on name and description`() {
|
||||
val nameResult =
|
||||
SkillListFilter.filterSkills(
|
||||
skills = sampleSkills,
|
||||
query = "code",
|
||||
selectedStatus = SkillFilter.ALL_STATUSES,
|
||||
selectedCategory = CATEGORY_ALL,
|
||||
sourceFilter = null,
|
||||
)
|
||||
assertEquals(1, nameResult.size)
|
||||
assertEquals("code-review", nameResult[0].name)
|
||||
|
||||
val descResult =
|
||||
SkillListFilter.filterSkills(
|
||||
skills = sampleSkills,
|
||||
query = "production",
|
||||
selectedStatus = SkillFilter.ALL_STATUSES,
|
||||
selectedCategory = CATEGORY_ALL,
|
||||
sourceFilter = null,
|
||||
)
|
||||
assertEquals(1, descResult.size)
|
||||
assertEquals("deploy-bot", descResult[0].name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `filterSkills filters by enabled and disabled status`() {
|
||||
val enabledResult =
|
||||
SkillListFilter.filterSkills(
|
||||
skills = sampleSkills,
|
||||
query = "",
|
||||
selectedStatus = SkillFilter.ENABLED,
|
||||
selectedCategory = CATEGORY_ALL,
|
||||
sourceFilter = null,
|
||||
)
|
||||
assertEquals(2, enabledResult.size)
|
||||
assertTrue(enabledResult.all { it.enabled })
|
||||
|
||||
val disabledResult =
|
||||
SkillListFilter.filterSkills(
|
||||
skills = sampleSkills,
|
||||
query = "",
|
||||
selectedStatus = SkillFilter.DISABLED,
|
||||
selectedCategory = CATEGORY_ALL,
|
||||
sourceFilter = null,
|
||||
)
|
||||
assertEquals(1, disabledResult.size)
|
||||
assertEquals("deploy-bot", disabledResult[0].name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `filterSkills filters by category and source`() {
|
||||
val catResult =
|
||||
SkillListFilter.filterSkills(
|
||||
skills = sampleSkills,
|
||||
query = "",
|
||||
selectedStatus = SkillFilter.ALL_STATUSES,
|
||||
selectedCategory = "ops",
|
||||
sourceFilter = null,
|
||||
)
|
||||
assertEquals(1, catResult.size)
|
||||
assertEquals("deploy-bot", catResult[0].name)
|
||||
|
||||
val sourceResult =
|
||||
SkillListFilter.filterSkills(
|
||||
skills = sampleSkills,
|
||||
query = "",
|
||||
selectedStatus = SkillFilter.ALL_STATUSES,
|
||||
selectedCategory = CATEGORY_ALL,
|
||||
sourceFilter = "built-in",
|
||||
)
|
||||
assertEquals(1, sourceResult.size)
|
||||
assertEquals("code-review", sourceResult[0].name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `extractCategories and extractSources return distinct sorted values`() {
|
||||
val categories = SkillListFilter.extractCategories(sampleSkills)
|
||||
assertEquals(listOf("creative", "dev", "ops"), categories)
|
||||
|
||||
val sources = SkillListFilter.extractSources(sampleSkills)
|
||||
assertEquals(listOf("built-in", "hub"), sources)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.m57.hermescontrol.ui.skills
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.m57.hermescontrol.R
|
||||
import com.m57.hermescontrol.theme.HermesStatusColors
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Test
|
||||
|
||||
class SkillScanPresentationTest {
|
||||
private val dummyColors =
|
||||
HermesStatusColors(
|
||||
success = Color(0xFF00FF00),
|
||||
successContainer = Color(0xFF003300),
|
||||
onSuccess = Color.White,
|
||||
warning = Color(0xFFFFFF00),
|
||||
warningContainer = Color(0xFF333300),
|
||||
onWarning = Color.Black,
|
||||
error = Color(0xFFFF0000),
|
||||
errorContainer = Color(0xFF330000),
|
||||
onError = Color.White,
|
||||
info = Color(0xFF0000FF),
|
||||
infoContainer = Color(0xFF000033),
|
||||
onInfo = Color.White,
|
||||
neutral = Color.Gray,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `resolveVerdictKind maps safe dangerous and fallback`() {
|
||||
assertEquals(ScanVerdictKind.SAFE, SkillScanPresentation.resolveVerdictKind("safe"))
|
||||
assertEquals(ScanVerdictKind.DANGEROUS, SkillScanPresentation.resolveVerdictKind("dangerous"))
|
||||
assertEquals(ScanVerdictKind.WARNING, SkillScanPresentation.resolveVerdictKind("unknown"))
|
||||
assertEquals(ScanVerdictKind.WARNING, SkillScanPresentation.resolveVerdictKind(null))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `resolveVerdictColor returns corresponding semantic color`() {
|
||||
assertEquals(dummyColors.success, SkillScanPresentation.resolveVerdictColor("safe", dummyColors))
|
||||
assertEquals(dummyColors.error, SkillScanPresentation.resolveVerdictColor("dangerous", dummyColors))
|
||||
assertEquals(dummyColors.warning, SkillScanPresentation.resolveVerdictColor("suspicious", dummyColors))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `resolvePolicyKind and labels map allow ask block and fallback`() {
|
||||
assertEquals(ScanPolicyKind.ALLOW, SkillScanPresentation.resolvePolicyKind("allow"))
|
||||
assertEquals(ScanPolicyKind.ASK, SkillScanPresentation.resolvePolicyKind("ask"))
|
||||
assertEquals(ScanPolicyKind.BLOCK, SkillScanPresentation.resolvePolicyKind("block"))
|
||||
assertEquals(ScanPolicyKind.OTHER, SkillScanPresentation.resolvePolicyKind("custom"))
|
||||
|
||||
assertEquals(R.string.skills_hub_scan_policy_allow, SkillScanPresentation.resolvePolicyLabelRes("allow"))
|
||||
assertEquals(R.string.skills_hub_scan_policy_ask, SkillScanPresentation.resolvePolicyLabelRes("ask"))
|
||||
assertEquals(R.string.skills_hub_scan_policy_block, SkillScanPresentation.resolvePolicyLabelRes("block"))
|
||||
assertNull(SkillScanPresentation.resolvePolicyLabelRes("other"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `resolveSeverityColor maps critical high medium low and fallback`() {
|
||||
assertEquals(dummyColors.error, SkillScanPresentation.resolveSeverityColor("critical", dummyColors))
|
||||
assertEquals(dummyColors.error, SkillScanPresentation.resolveSeverityColor("high", dummyColors))
|
||||
assertEquals(dummyColors.warning, SkillScanPresentation.resolveSeverityColor("medium", dummyColors))
|
||||
assertEquals(dummyColors.neutral, SkillScanPresentation.resolveSeverityColor("low", dummyColors))
|
||||
assertEquals(dummyColors.neutral, SkillScanPresentation.resolveSeverityColor("info", dummyColors))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user