Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more configuration to test() #518

Merged
merged 2 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add more configuration to test()
  • Loading branch information
ajalt committed May 21, 2024
commit 601d6c2af3b5796ca553049717bbc9c37583f1be
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Added `CompletionGenerator` to manually generate completions for a command.
- Added `Context.exitProcess` which you can use to prevent the process from exiting during tests.
- Added core module that supports watchOS, tvOS, and wasmWasi targets and has no dependencies.
- Added more options to `CliktCommand.test` to control the terminal interactivity. ([#517](https://github.com/ajalt/clikt/pull/517))

### Changed
- In a subcommand with `argument().multiple()`, the behavior is now the same regardless of the value of `allowMultipleSubcommands`: if a token matches a subcommand name, it's now treated as a subcommand rather than a positional argument.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.ajalt.clikt.command

import com.github.ajalt.clikt.core.*
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.installMordant
import com.github.ajalt.clikt.parsers.CommandLineParser
import com.github.ajalt.clikt.testing.CliktCommandTestResult
import com.github.ajalt.clikt.testing.test
Expand All @@ -24,8 +25,8 @@ abstract class SuspendingCliktCommand(
/**
* Test this command, returning a result that captures the output and result status code.
*
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed with [print] or
* [println] is not.
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed
* with [print] or [println] is not.
*
* @param argv The command line to send to the command
* @param stdin Content of stdin that will be read by prompt options. Multiple inputs should be separated by `\n`.
Expand All @@ -35,6 +36,9 @@ abstract class SuspendingCliktCommand(
* @param ansiLevel Defaults to no colored output; set to [AnsiLevel.TRUECOLOR] to include ANSI codes in the output.
* @param width The width of the terminal, used to wrap text
* @param height The height of the terminal
* @param hyperlinks Whether to enable hyperlink support in the terminal
* @param outputInteractive Whether the output is interactive
* @param inputInteractive Whether the input is interactive
*/
suspend fun SuspendingCliktCommand.test(
argv: String,
Expand All @@ -44,16 +48,22 @@ suspend fun SuspendingCliktCommand.test(
ansiLevel: AnsiLevel = AnsiLevel.NONE,
width: Int = 79,
height: Int = 24,
hyperlinks: Boolean = ansiLevel != AnsiLevel.NONE,
outputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
inputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
): CliktCommandTestResult {
val argvArray = CommandLineParser.tokenize(argv)
return test(argvArray, stdin, envvars, includeSystemEnvvars, ansiLevel, width, height)
return test(
argvArray, stdin, envvars, includeSystemEnvvars, ansiLevel, width, height,
hyperlinks, outputInteractive, inputInteractive
)
}

/**
* Test this command, returning a result that captures the output and result status code.
*
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed with [print] or
* [println] is not.
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed
* with [print] or [println] is not.
*
* @param argv The command line to send to the command
* @param stdin Content of stdin that will be read by prompt options. Multiple inputs should be separated by `\n`.
Expand All @@ -63,6 +73,9 @@ suspend fun SuspendingCliktCommand.test(
* @param ansiLevel Defaults to no colored output; set to [AnsiLevel.TRUECOLOR] to include ANSI codes in the output.
* @param width The width of the terminal, used to wrap text
* @param height The height of the terminal
* @param hyperlinks Whether to enable hyperlink support in the terminal
* @param outputInteractive Whether the output is interactive
* @param inputInteractive Whether the input is interactive
*/
suspend fun SuspendingCliktCommand.test(
argv: Array<String>,
Expand All @@ -72,15 +85,21 @@ suspend fun SuspendingCliktCommand.test(
ansiLevel: AnsiLevel = AnsiLevel.NONE,
width: Int = 79,
height: Int = 24,
hyperlinks: Boolean = ansiLevel != AnsiLevel.NONE,
outputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
inputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
): CliktCommandTestResult {
return test(argv.asList(), stdin, envvars, includeSystemEnvvars, ansiLevel, width, height)
return test(
argv.asList(), stdin, envvars, includeSystemEnvvars, ansiLevel, width, height,
hyperlinks, outputInteractive, inputInteractive
)
}

/**
* Test this command, returning a result that captures the output and result status code.
*
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed with [print] or
* [println] is not.
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed
* with [print] or [println] is not.
*
* @param argv The command line to send to the command
* @param stdin Content of stdin that will be read by prompt options. Multiple inputs should be separated by `\n`.
Expand All @@ -90,6 +109,9 @@ suspend fun SuspendingCliktCommand.test(
* @param ansiLevel Defaults to no colored output; set to [AnsiLevel.TRUECOLOR] to include ANSI codes in the output.
* @param width The width of the terminal, used to wrap text
* @param height The height of the terminal
* @param hyperlinks Whether to enable hyperlink support in the terminal
* @param outputInteractive Whether the output is interactive
* @param inputInteractive Whether the input is interactive
*/
suspend fun SuspendingCliktCommand.test(
argv: List<String>,
Expand All @@ -99,8 +121,12 @@ suspend fun SuspendingCliktCommand.test(
ansiLevel: AnsiLevel = AnsiLevel.NONE,
width: Int = 79,
height: Int = 24,
hyperlinks: Boolean = ansiLevel != AnsiLevel.NONE,
outputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
inputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
): CliktCommandTestResult {
return test(argv, stdin, envvars, includeSystemEnvvars, ansiLevel, width, height) {
parse(it)
}
return test(
argv, stdin, envvars, includeSystemEnvvars, ansiLevel, width, height,
hyperlinks, outputInteractive, inputInteractive
) { parse(it) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ data class CliktCommandTestResult(
* @param ansiLevel Defaults to no colored output; set to [AnsiLevel.TRUECOLOR] to include ANSI codes in the output.
* @param width The width of the terminal, used to wrap text
* @param height The height of the terminal
* @param hyperlinks Whether to enable hyperlink support in the terminal
* @param outputInteractive Whether the output is interactive
* @param inputInteractive Whether the input is interactive
*/
fun CliktCommand.test(
argv: String,
Expand All @@ -45,16 +48,22 @@ fun CliktCommand.test(
ansiLevel: AnsiLevel = AnsiLevel.NONE,
width: Int = 79,
height: Int = 24,
hyperlinks: Boolean = ansiLevel != AnsiLevel.NONE,
outputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
inputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
): CliktCommandTestResult {
val argvArray = CommandLineParser.tokenize(argv)
return test(argvArray, stdin, envvars, includeSystemEnvvars, ansiLevel, width, height)
return test(
argvArray, stdin, envvars, includeSystemEnvvars, ansiLevel, width, height,
hyperlinks, outputInteractive, inputInteractive
)
}

/**
* Test this command, returning a result that captures the output and result status code.
*
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed with [print] or
* [println] is not.
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed
* with [print] or [println] is not.
*
* @param argv The command line to send to the command
* @param stdin Content of stdin that will be read by prompt options. Multiple inputs should be separated by `\n`.
Expand All @@ -64,6 +73,9 @@ fun CliktCommand.test(
* @param ansiLevel Defaults to no colored output; set to [AnsiLevel.TRUECOLOR] to include ANSI codes in the output.
* @param width The width of the terminal, used to wrap text
* @param height The height of the terminal
* @param hyperlinks Whether to enable hyperlink support in the terminal
* @param outputInteractive Whether the output is interactive
* @param inputInteractive Whether the input is interactive
*/
@JvmName("varargTest")
fun CliktCommand.test(
Expand All @@ -74,15 +86,21 @@ fun CliktCommand.test(
ansiLevel: AnsiLevel = AnsiLevel.NONE,
width: Int = 79,
height: Int = 24,
hyperlinks: Boolean = ansiLevel != AnsiLevel.NONE,
outputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
inputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
): CliktCommandTestResult {
return test(argv.asList(), stdin, envvars, includeSystemEnvvars, ansiLevel, width, height)
return test(
argv.asList(), stdin, envvars, includeSystemEnvvars, ansiLevel, width, height,
hyperlinks, outputInteractive, inputInteractive
)
}

/**
* Test this command, returning a result that captures the output and result status code.
*
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed with [print] or
* [println] is not.
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed
* with [print] or [println] is not.
*
* @param argv The command line to send to the command
* @param stdin Content of stdin that will be read by prompt options. Multiple inputs should be separated by `\n`.
Expand All @@ -92,6 +110,9 @@ fun CliktCommand.test(
* @param ansiLevel Defaults to no colored output; set to [AnsiLevel.TRUECOLOR] to include ANSI codes in the output.
* @param width The width of the terminal, used to wrap text
* @param height The height of the terminal
* @param hyperlinks Whether to enable hyperlink support in the terminal
* @param outputInteractive Whether the output is interactive
* @param inputInteractive Whether the input is interactive
*/
fun CliktCommand.test(
argv: Array<String>,
Expand All @@ -101,15 +122,21 @@ fun CliktCommand.test(
ansiLevel: AnsiLevel = AnsiLevel.NONE,
width: Int = 79,
height: Int = 24,
hyperlinks: Boolean = ansiLevel != AnsiLevel.NONE,
outputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
inputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
): CliktCommandTestResult {
return test(argv.asList(), stdin, envvars, includeSystemEnvvars, ansiLevel, width, height)
return test(
argv.asList(), stdin, envvars, includeSystemEnvvars, ansiLevel, width, height,
hyperlinks, outputInteractive, inputInteractive
)
}

/**
* Test this command, returning a result that captures the output and result status code.
*
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed with [print] or
* [println] is not.
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed
* with [print] or [println] is not.
*
* @param argv The command line to send to the command
* @param stdin Content of stdin that will be read by prompt options. Multiple inputs should be separated by `\n`.
Expand All @@ -119,6 +146,9 @@ fun CliktCommand.test(
* @param ansiLevel Defaults to no colored output; set to [AnsiLevel.TRUECOLOR] to include ANSI codes in the output.
* @param width The width of the terminal, used to wrap text
* @param height The height of the terminal
* @param hyperlinks Whether to enable hyperlink support in the terminal
* @param outputInteractive Whether the output is interactive
* @param inputInteractive Whether the input is interactive
*/
fun CliktCommand.test(
argv: List<String>,
Expand All @@ -128,17 +158,21 @@ fun CliktCommand.test(
ansiLevel: AnsiLevel = AnsiLevel.NONE,
width: Int = 79,
height: Int = 24,
hyperlinks: Boolean = ansiLevel != AnsiLevel.NONE,
outputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
inputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
): CliktCommandTestResult {
return test(argv, stdin, envvars, includeSystemEnvvars, ansiLevel, width, height) {
parse(it)
}
return test(
argv, stdin, envvars, includeSystemEnvvars, ansiLevel, width,
height, hyperlinks, outputInteractive, inputInteractive
) { parse(it) }
}

/**
* Test this command, returning a result that captures the output and result status code.
*
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed with [print] or
* [println] is not.
* Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed
* with [print] or [println] is not.
*
* @param argv The command line to send to the command
* @param stdin Content of stdin that will be read by prompt options. Multiple inputs should be separated by `\n`.
Expand All @@ -148,6 +182,9 @@ fun CliktCommand.test(
* @param ansiLevel Defaults to no colored output; set to [AnsiLevel.TRUECOLOR] to include ANSI codes in the output.
* @param width The width of the terminal, used to wrap text
* @param height The height of the terminal
* @param hyperlinks Whether to enable hyperlink support in the terminal
* @param outputInteractive Whether the output is interactive
* @param inputInteractive Whether the input is interactive
* @param parse The function to call to parse the command line and run the command
*/
inline fun <T : BaseCliktCommand<T>> BaseCliktCommand<T>.test(
Expand All @@ -158,10 +195,15 @@ inline fun <T : BaseCliktCommand<T>> BaseCliktCommand<T>.test(
ansiLevel: AnsiLevel = AnsiLevel.NONE,
width: Int = 79,
height: Int = 24,
hyperlinks: Boolean = ansiLevel != AnsiLevel.NONE,
outputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
inputInteractive: Boolean = ansiLevel != AnsiLevel.NONE,
parse: (argv: List<String>) -> Unit,
): CliktCommandTestResult {
var exitCode = 0
val recorder = TerminalRecorder(ansiLevel, width, height)
val recorder = TerminalRecorder(
ansiLevel, width, height, hyperlinks, outputInteractive, inputInteractive
)
recorder.inputLines = stdin.split("\n").toMutableList()
configureContext {
val originalReader = envvarReader
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.github.ajalt.clikt.testing

import com.github.ajalt.clikt.core.terminal
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.options.prompt
import com.github.ajalt.mordant.rendering.AnsiLevel
import io.kotest.matchers.shouldBe
import kotlin.js.JsName
import kotlin.test.Test
Expand Down Expand Up @@ -70,4 +72,30 @@ class TestingUtilsTest {
result.output shouldBe "O1: O2: err\n"
result.statusCode shouldBe 0
}

@Test
@JsName("test_TerminalInfo_configuration")
fun `test TerminalInfo configuration`() {
class C : TestCommand() {
override fun run_() {
with(currentContext.terminal.info) {
ansiLevel shouldBe AnsiLevel.NONE
width shouldBe 11
height shouldBe 22
ansiHyperLinks shouldBe true
outputInteractive shouldBe true
inputInteractive shouldBe true
}
}
}
C().test(
"",
ansiLevel = AnsiLevel.NONE,
width = 11,
height = 22,
hyperlinks = true,
outputInteractive = true,
inputInteractive = true,
)
}
}
Loading