-
Notifications
You must be signed in to change notification settings - Fork 70
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
Support for testing colored strings #278
Comments
Actually, it is already possible to compare colored text by using a custom matcher. I created this matcher to remove all invisible control characters before searching the text: # Custom matcher used to find a string inside of a text containing ANSI escape codes.
match_colored_text() {
# Source: https://unix.stackexchange.com/a/18979/348102
sanitized_text="$(echo "${match_colored_text:?}" | perl -e '
while (<>) {
s/ \e[ #%()*+\-.\/]. |
\r | # Remove extra carriage returns also
(?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd
(?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
(?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
\e.|[\x80-\x9f] //xg;
1 while s/[^\b][\b]//g; # remove all non-backspace followed by backspace
print;
}
')"
echo "${sanitized_text}" | grep -q "$1"
} Then i used it like this: Describe "should have help option..."
Parameters
"Short" "-h"
"Long" "--help"
End
Example "$1 ($2)"
Set 'errexit:on'
When call "${LIBRARY_PATH}" $2
The status should be success
# Here i use a custom matcher function because the text has ANSI colors by default,
# and this makes impossible to the `eq` matcher to find text.
The output should satisfy match_colored_text "OPTIONS:"
The output should satisfy match_colored_text "USAGE:"
End
End If you REALLY really need to compare even the colors (which i discourage and isn't best practice, since the user could disable them entirely on their terminal [and sometimes your code should too]) you could write a custom matcher (maybe in Perl?) that checks that even the colors are the same. In the end...Putting all together (if you choose to check that text is equal regardless of colors) in your case the code should look like this: # Custom matcher used to find a string inside of a text containing ANSI escape codes.
match_colored_text() {
# Source: https://unix.stackexchange.com/a/18979/348102
sanitized_text="$(echo "${match_colored_text:?}" | perl -e '
while (<>) {
s/ \e[ #%()*+\-.\/]. |
\r | # Remove extra carriage returns also
(?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd
(?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
(?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
\e.|[\x80-\x9f] //xg;
1 while s/[^\b][\b]//g; # remove all non-backspace followed by backspace
print;
}
')"
echo "${sanitized_text}" | grep -q "$1"
}
Describe 'script.sh'
It 'invokes correctly'
When call ./script.sh
The output should satisfy match_colored_text "Hello World"
End
End |
UPDATEI managed to get it working both with and without interpreting escape codes: In the following
The following is a working (but slightly different) test i used in this project of mine: %const LIBRARY_PATH: src/myscript.sh
# Custom matcher used to find a string inside of a plain text.
match_plain_text() {
# Source: https://unix.stackexchange.com/a/18979/348102
sanitized_text="$(echo "${match_plain_text:?}" | perl -e '
while (<>) {
s/ \e[ #%()*+\-.\/]. |
\r | # Remove extra carriage returns also
(?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd
(?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
(?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
\e.|[\x80-\x9f] //xg;
1 while s/[^\b][\b]//g; # remove all non-backspace followed by backspace
print;
}
')"
echo "${sanitized_text}" | grep -q "$1"
}
# Custom matcher used to find a string inside of a text containing ANSI escape codes.
match_rich_text() {
if [ -z "${1}" ]; then
printf "ERROR: You cannot pass an empty string!\n" >&2;
return 1;
fi
# shellcheck disable=SC2059
rich_search_term="$(printf "$1")"
match="$(echo "${match_rich_text:-}" | perl -ne "print if /\Q${rich_search_term}/")"
[ -n "${match}" ]
}
Describe "Testing text with or without colors:"
Example "WITHOUT Colors:"
Set 'errexit:on'
When call "${LIBRARY_PATH}" --help
The status should be success
# Here i use a custom matcher function because the text has ANSI colors by default,
# and this makes impossible to the `eq` matcher to find text.
The output should satisfy match_plain_text "OPTIONS:"
The output should satisfy match_plain_text "USAGE:"
End
Example "WITH Colors:"
Set 'errexit:on'
When call "${LIBRARY_PATH}" --help
The status should be success
# Works with inline characters
The output should satisfy match_rich_text "\033[1mOPTIONS\033[0m:"
# But works with already rendered characters too!
bold="$(printf '\033[1m')"
reset="$(printf '\033[0m')"
The output should satisfy match_rich_text "${bold}USAGE${reset}:"
End
End You could even make the custom matchers available globally (to all tests) by putting those two functions inside the |
A script with colored output like this
Fails the following test
The text was updated successfully, but these errors were encountered: