Files
kargs/src/test/kotlin/org/kargs/tests/SubcommandTest.kt
2025-11-18 23:22:34 -05:00

160 lines
5.5 KiB
Kotlin

package org.kargs.tests
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.kargs.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.assertFalse
import kotlin.test.assertNull
class SubcommandTest {
@Test
fun `subcommand creation with valid parameters`() {
val cmd = TestUtils.TestSubcommand("build", "Build the project", listOf("b", "compile"))
assertEquals("build", cmd.name)
assertEquals("Build the project", cmd.description)
assertEquals(listOf("b", "compile"), cmd.aliases)
}
@Test
fun `subcommand throws on blank name`() {
assertThrows<IllegalArgumentException> {
TestUtils.TestSubcommand("", "Description")
}
assertThrows<IllegalArgumentException> {
TestUtils.TestSubcommand(" ", "Description") // whitespace only
}
}
@Test
fun `subcommand registers properties correctly`() {
val cmd = TestUtils.TestSubcommand()
// Properties should be registered automatically via delegates
assertTrue(cmd.options.isNotEmpty())
assertTrue(cmd.flags.isNotEmpty())
assertTrue(cmd.arguments.isNotEmpty())
// Check specific properties are registered
assertTrue(cmd.options.any { it.longName == "required" })
assertTrue(cmd.flags.any { it.longName == "verbose" })
assertTrue(cmd.arguments.any { it.name == "input" })
}
@Test
fun `subcommand validation works`() {
val cmd = TestUtils.TestSubcommand()
// Should have validation errors for required fields
val errors = cmd.validate()
assertTrue(errors.isNotEmpty())
assertTrue(errors.any { it.contains("required") })
// Set required values through parsing (the proper way)
val requiredOption = cmd.options.find { it.longName == "required" }
val inputArgument = cmd.arguments.find { it.name == "input" }
requiredOption?.parseValue("value")
inputArgument?.parseValue("input.txt")
// Should now be valid
val errorsAfter = cmd.validate()
assertTrue(errorsAfter.isEmpty())
}
@Test
fun `subcommand help generation`() {
val cmd = TestUtils.TestSubcommand("test", "Test command for validation")
val helpOutput = TestUtils.captureOutput {
cmd.printHelp()
}
assertTrue(helpOutput.contains("Usage: test [options]"))
assertTrue(helpOutput.contains("Test command for validation"))
assertTrue(helpOutput.contains("Options:"))
assertTrue(helpOutput.contains("--required"))
assertTrue(helpOutput.contains("Flags:"))
assertTrue(helpOutput.contains("--verbose"))
assertTrue(helpOutput.contains("Arguments:"))
assertTrue(helpOutput.contains("input"))
}
@Test
fun `subcommand property access works`() {
val cmd = TestUtils.TestSubcommand()
// Initially null/default values
assertNull(cmd.requiredOpt)
assertEquals(false, cmd.verboseFlag)
assertNull(cmd.inputArg)
// Set values through parsing (simulating real usage)
val requiredOption = cmd.options.find { it.longName == "required" }
val verboseFlag = cmd.flags.find { it.longName == "verbose" }
val inputArgument = cmd.arguments.find { it.name == "input" }
requiredOption?.parseValue("test")
verboseFlag?.setFlag()
inputArgument?.parseValue("file.txt")
// Values should be accessible
assertEquals("test", cmd.requiredOpt)
assertEquals(true, cmd.verboseFlag)
assertEquals("file.txt", cmd.inputArg)
}
@Test
fun `subcommand property types are correct`() {
val cmd = TestUtils.TestSubcommand()
// Check that we can find properties by their characteristics
val stringOption = cmd.options.find { it.longName == "string" }
val intOption = cmd.options.find { it.longName == "number" }
val rangeOption = cmd.options.find { it.longName == "range" }
val choiceOption = cmd.options.find { it.longName == "choice" }
assertTrue(stringOption != null)
assertTrue(intOption != null)
assertTrue(rangeOption != null)
assertTrue(choiceOption != null)
// Test parsing different types
stringOption?.parseValue("hello")
intOption?.parseValue("42")
rangeOption?.parseValue("5")
choiceOption?.parseValue("b")
assertEquals("hello", cmd.stringOpt)
assertEquals(42, cmd.intOpt)
assertEquals(5, cmd.rangeOpt)
assertEquals("b", cmd.choiceOpt)
}
@Test
fun `subcommand execution tracking works`() {
val cmd = TestUtils.TestSubcommand()
assertFalse(cmd.executed)
assertTrue(cmd.executionData.isEmpty())
// Set some values and execute
val requiredOption = cmd.options.find { it.longName == "required" }
val inputArgument = cmd.arguments.find { it.name == "input" }
requiredOption?.parseValue("test")
inputArgument?.parseValue("input.txt")
cmd.execute()
assertTrue(cmd.executed)
assertTrue(cmd.executionData.isNotEmpty())
assertEquals("test", cmd.executionData["requiredOpt"])
assertEquals("input.txt", cmd.executionData["inputArg"])
}
}