diff --git a/plugins/fish-spec/eval.fish b/plugins/fish-spec/eval.fish new file mode 100644 index 0000000..3dd9c78 --- /dev/null +++ b/plugins/fish-spec/eval.fish @@ -0,0 +1,60 @@ +function eval -S -d "Evaluate parameters as a command" + # keep a copy of the previous $status and use restore_status + # to preserve the status in case the block that is evaluated + # does not modify the status itself. + set -l status_copy $status + function -S restore_status + return $status_copy + end + + if not set -q argv[2] + # like most builtins, we only check for -h/--help + # if we only have a single argument + switch "$argv[1]" + case -h --help + __fish_print_help eval + return 0 + end + end + + # If we are in an interactive shell, eval should enable full + # job control since it should behave like the real code was + # executed. If we don't do this, commands that expect to be + # used interactively, like less, wont work using eval. + + set -l mode + if status --is-interactive-job-control + set mode interactive + else + if status --is-full-job-control + set mode full + else + set mode none + end + end + if status --is-interactive + status --job-control full + end + + # rfish: To eval 'foo', we construct a block "begin ; foo; end <&3 3<&-" + # The 'eval2_inner' is a param to 'begin' itself; I believe it does nothing. + # Note the redirections are also within the quotes. + # + # We then pipe this to 'source 3<&0' which dup2's 3 to stdin. + # + # You might expect that the dup2(3, stdin) should overwrite stdin, + # and therefore prevent 'source' from reading the piped-in block. This doesn't + # happen because when you pipe to a builtin, we don't overwrite stdin with the + # read end of the block; instead we set a separate fd in a variable 'builtin_stdin', + # which is what it reads from. So builtins are magic in that, in pipes, their stdin + # is not fd 0. + + restore_status + echo "begin; $argv "\n" ;end eval2_inner <&3 3<&-" | source 3<&0 + set -l res $status + + status --job-control $mode + functions -e restore_status + + return $res +end diff --git a/plugins/fish-spec/expect.fish b/plugins/fish-spec/expect.fish index ee7a707..8c892fd 100644 --- a/plugins/fish-spec/expect.fish +++ b/plugins/fish-spec/expect.fish @@ -1,15 +1,20 @@ # NAME -# expect - assert a list of expected values match an actual value. +# expect - assert a list of expected values match an actual value # # SYNOPSIS -# expect ... -# -# --to-be-false exit status is falsy -# --to-be-true exit status is truthy -# --to-contain values exist in list -# --to-no-contain values does not exist in list -# --to-equal value equals value -# +# expect + +# OPTIONS +# ... +# +# --to-equal value equals value +# --to-not-equal value does not equals value +# +# --to-contain values exist in list +# --to-not-contain values does not exist in list +# --to-be-true exit status should be truthy +# --to-be-false exit status should be falsy +# ... # # EXAMPLE # import plugins/fish-spec @@ -21,29 +26,33 @@ # end # end # spec.run +# +# AUTHORS +# Bruno Pinto <@pfbruno> +# Jorge Bucaran <@bucaran> #/ function expect - # Abort if last call to `expect` finished with $status 1. This allows to - # stop individual tests from running if at least one expect call fails. - if [ $status -eq 1 ] - return 1 - end + set -l result 0 + # Parse expected / actual lists + set -l actual "" + set -l expected "" + set -l condition "" - for i in (seq (count $argv)) - if [ (echo $argv[$i] | grep '\-\-') ] # Expectation argument found - set -g condition $argv[$i] - set -g expected $argv[1..(math "$i - 1")] - - # No comparison required e.g. --to-be-true - if not [ (count $argv) = $i ] - set -g actual $argv[(math "$i + 1")..-1] - end - - break + for index in (seq (count $argv)) + switch $argv[$index] + # --condition found, split expected/actual lists + case --\* + set expected $argv[1..(math $index-1)] + set condition $argv[$index] + # No comparison required e.g. --to-be-true + if [ $index -lt (count $argv) ] + set actual $argv[(math $index+1)..-1] + end + break end end - # Test conditions and save success/fail $status to return later. + # Test conditions switch $condition case --to-be-false eval "$expected" @@ -65,16 +74,19 @@ function expect or set result $status end test $result -ne 0 - case --to-eq\* + case --to-equal test "$expected" = "$actual" + case --to-not-equal + test "$expected" != "$actual" end + set result $status if [ $result -eq 0 ] - spec.log --ok + # Return a non-empty string to indicate success. + printf "$result" else - spec.log --fail red \n"Expected" yellow "$expected" \ - red \n(echo $condition | tr "-" " " \ - | cut -c 3-) yellow "$actual" + # Return error information separated by \t and tested condition. + printf "%s\n" $expected \t $condition $actual end return $result end diff --git a/plugins/fish-spec/list.erase.fish b/plugins/fish-spec/list.erase.fish index 870f093..729d672 100644 --- a/plugins/fish-spec/list.erase.fish +++ b/plugins/fish-spec/list.erase.fish @@ -13,14 +13,18 @@ # While items are basically any valid sequence of symbols, lists refer # to any global variable or local variable in the scope of the calling # function by name. +# +# AUTHORS +# Jorge Bucaran <@bucaran> #/ function -S list.erase - # List to erase from is at last index by default. + # Assume no items were erased. + set -l result 1 + # At least one list should be at the last index. set -l items $argv[1..-2] set -l lists $argv[-1] if set -l index (contains -i -- --from $argv) - # Everything before --from are items to erase and everything - # after, lists to erase any found items from. + # --from set items $argv[1..(math $index-1)] set lists $argv[(math $index+1)..-1] end @@ -28,7 +32,10 @@ function -S list.erase for list in $lists if set -l index (contains -i -- $item $$list) set -e $list[1][$index] + # Function succeeds if at least an item is erased. + set result 0 end end end + return $result end diff --git a/plugins/fish-spec/spec.eval.fish b/plugins/fish-spec/spec.eval.fish index 616153b..8e6ca32 100644 --- a/plugins/fish-spec/spec.eval.fish +++ b/plugins/fish-spec/spec.eval.fish @@ -1,98 +1,29 @@ # NAME -# spec.eval - eval a function by name and echo its description field +# spec.eval - eval a test function # # SYNOPSIS # spec.eval [OPTIONS...] - +# # OPTIONS -# -# Name / glob of one or more functions to evaluate. By default find all -# functions that match the glob and test each. To run a single function, -# use the -u --unit option as described below. +# See spec.report # -# [-u --unit] -# Evaluate a single function as indicated by . -# -# [-d --depth ] -# Used to calculate the increment rate of padding added to test blocks. -# A depth of N will prepend N*2 spaces to test descriptions. No padding -# is added by default. Use a depth of 0 to NOT output newlines between -# each test log output. -# -# [-s --silent] -# Do NOT output test descriptions. This option is off by default. -# -# DESCRIPTION -# Run the specified function. Add a -d --description field to tests in -# order to log a message before evaluating the function. Use the depth -# option to indicate the indentation factor when logging a message. -# -# The process is split up in these steps: -# -# 1. Extract test name. -# 2. Parse description from function definition if available. -# 3. Parse options -# + Calculate indentation from --depth * $tab. -# + Determine newline output. -# + Skip output if -s --silent is specified. -# -# EXAMPLES -# spec.eval "describe_" --depth 0 -# spec.eval "teardown_" -# spec.eval "it_" -# spec.eval "my_test" --unit +# AUTHORS +# Bruno Pinto <@pfbruno> +# Jorge Bucaran <@bucaran> #/ -function spec.eval -d "Eval a function by name and echo its description field." - # Parse and print description field of a function. - # spec.get.info - function spec.get.info -a name - type $name \ - | head -n 2 \ - | tail -n 1 \ - | cut -d" " -f4- \ - | sed "s/^\'//g" \ - | sed "s/\'\$//g" - end +import plugins/msg - set -l default_color white - # Keep a copy in case -u --unit option is used. - set -l query $argv[1] - # Collect all functions that start with $query's key. - set -l tests (spec.functions $query) - set -l tab 2 - set -l indent "" - set -l newline \n - set -l silent "" +function spec.eval + set -l result $status + set -l test $argv[1] + set -e argv[1] - for index in (seq (count $argv)) - switch $argv[$index] - case -d --depth - set -l depth $argv[(math $index + 1)] - if [ $depth -gt 0 ] - set indent (printf " %.0s" (seq (math $depth \* $tab))) - else - set newline "" - end - case -s --silent - set silent $argv[$index] - case -u --unit - # Evaluate query as a single function instead of a set. - set tests $query - end - end - - set -l result 0 - for test in $tests - if [ -z "$silent" ] - set -l info (spec.get.info $tests) - if [ -n "$info" ] - # Do not print empty lines for tests with empty descriptions. - set info $newline$indent$info - end - spec.log --message $default_color "$info" - end - eval $test - or set result 1 + if functions -q $test + # Run the test yielding control to the user defined spec. + set -l output (eval $test) + set result $status + # Display test results. + spec.view $test $result $argv -- $output end return $result end diff --git a/plugins/fish-spec/spec.functions.fish b/plugins/fish-spec/spec.functions.fish index eecab75..90a12c8 100644 --- a/plugins/fish-spec/spec.functions.fish +++ b/plugins/fish-spec/spec.functions.fish @@ -1,16 +1,106 @@ # NAME -# spec.functions - echo functions existing in the global scope that match -# the key glob. +# spec.functions - return functions in the global scope that match ^key +# # SYNOPSIS -# spec.functions +# spec.functions [OPTIONS] +# +# OPTIONS +# -b --backup +# Create new backup functions for all functions by with a +# +# -r --restore +# Create new functions without . +# +# -q --quiet +# Quiet mode. No output. Return 1 if no functions are found. +# +# -e --erase +# Erase the matched functions. # # EXAMPLES -# spec.functions "describe_" -# spec.functions "before_" +# 1) spec.functions "describe_" +# 2) spec.functions -q "before_" +# +# 3) spec.functions -be "describe_" "it_" -- bak_ +# Backup all describe_* and it_* functions to bak_describe_* and +# bak_it_* and erases the original describe_* and it_* +# +# 4) spec.functions -r bak_ +# Find all bak_* functions and copies them without the prefix bak_. +# +# AUTHORS +# Jorge Bucaran <@bucaran> #/ -function spec.functions -a key - if [ -n "$key" ] - # Skip empty strings to avoid fetching all global functions. - functions -n | grep \^"$key" +function spec.functions + # Parse custom options + set -l backup + set -l prefix + set -l restore + set -l quiet + set -l erase + set -l keys + for index in (seq (count $argv)) + switch $argv[$index] + case -q --quiet + set quiet -q + # N-switch-fallthrough pattern in fish. + case -b\* -r\* -e\* + switch $argv[$index] + case -b -be -eb --backup + set backup -b + if set -l separator (contains -i -- "--" $argv[$index..-1]) + set prefix $argv[(math $separator + 1)] + else + set prefix $argv[(math $index + 2)] + end + end + switch $argv[$index] + case -e -be -eb --erase -re -er + set erase -e + end + switch $argv[$index] + case -r -re -er --restore + # Using restore takes only one argument, + set restore -r + set prefix $argv[(math $index + 1)] + end + case \* + set keys $keys $argv[$index] + end + end + + # Skip empty strings to avoid fetching all global functions. + if [ -n "$keys" ] + if [ -n "$restore" -a -n "$prefix" ] + set keys $prefix + end + + set -l list + for key in $keys + set list $list (functions -n | grep \^"$key") + end + + if [ -n "$list" ] + if [ -n "$erase" -o -n "$prefix" ] + + for item in $list + if [ -n "$backup" -a "$prefix" ] + functions -c $item $prefix$item + end + if [ -n "$restore" -a "$prefix" ] + # Cut prefix from function and create a new copy. + functions -c $item (echo $item | \ + cut -c (echo $prefix | awk '{ print length + 1 }')-) + end + if [ -n "$erase" ] + functions -e $item + end + end + + else if [ -z "$quiet" ] + printf "%s\n" $list + end + return 0 + end end end diff --git a/plugins/fish-spec/spec.log.fish b/plugins/fish-spec/spec.log.fish deleted file mode 100644 index 4535614..0000000 --- a/plugins/fish-spec/spec.log.fish +++ /dev/null @@ -1,56 +0,0 @@ -# NAME -# spec.log - log a message / test result -# -# SYNOPSIS -# spec.log -m | --msg/--message -# -o | --ok -# -f | --fail -# [ ...] -# OPTIONS -# -m --msg --message -# Output the message according to the ... list. -# -# -o --ok -# Echo a . character. Optionally, print a list of ... -# messages. -# -# -f --fail -# Echo a ✘ character. Optionally, print a list of ... -# messages. Use this feature to indicate the expected value, condition -# description and actual value of the failed assertion. For example: -# -# spec.log --fail red "Expected" blue "$value" -# -# NOTES -# This function does not modify the $status variable. -# -# Some tests may specify multiple success conditions, invoking `expect` -# several times per test case. In this case, spec.log will be run once -# each per `expect` call. -# -# Notice that a message in the form [ ...] implies that -# colors occupy odd and strings even indices after the first option. -#/ -function spec.log -d "Log / commit a message or test result." - switch $argv[1] - case -o --ok - set -e argv[1] - set argv green . $argv - case -f --fail - set -e argv[1] - set argv red ✘ $argv - case -m --msg --message - # Default message color. - set -e argv[1] - end - - if [ (count $argv) -gt 0 ] - for i in (seq (count $argv)) - if [ (math "$i % 2") -eq 0 ] - echo -ne $argv[$i](set_color white) - else - set_color $argv[$i] - end - end - end -end diff --git a/plugins/fish-spec/spec.run.fish b/plugins/fish-spec/spec.run.fish index 6b0333e..ab0c762 100644 --- a/plugins/fish-spec/spec.run.fish +++ b/plugins/fish-spec/spec.run.fish @@ -1,16 +1,18 @@ # NAME -# spec.run - run suite of tests +# spec.run - run a suite of tests # # SYNOPSIS -# spec.run [-v --verbose] +# spec.run [OPTIONS] +# +# OPTIONS +# -v --verbose +# Print full test output. # # DESCRIPTION # In order to run tests create the test file, import plugins/spec at # before adding any of the functions described above and call spec.run. # # FUNCTIONS -# import plugins/spec -# # function before_all Run before any tests are run. # function before_each Run before each test. # function describe_* Use to organize different specs. @@ -18,6 +20,18 @@ # function after_each Run after each test. # function after_all Run after all tests are finished. # +# NOTES +# After each test is evaluated, the function is erased from the scope by +# spec.eval to guarantee that subsequent describe blocks will not end up +# calling the previous describe's batch of tests. +# +# The fish-spec library is no different from other Oh-My-Fish plugins. +# Use `import plugins/fish-spec` at the top of your spec file and call +# +# spec.run $argv +# +# After your suite of tests. +# # EXAMPLES # import plugins/fish-spec # function describe_erase @@ -36,27 +50,44 @@ # Jorge Bucaran <@bucaran> #/ function spec.run - set -l result 0 # Optimism - set -l output "--silent" - if contains -- $argv[1] -v --verbose - set output "" - end - # Run 1 or more topmost describe blocks causing fish to load inmediately - # scoped functions, i.e, those inside any invoked describe_ blocks. - spec.eval describe_ --depth 0 $output - spec.eval before_all $output - for test in (spec.functions "it_") - spec.eval before_each $output + set -l result 0 + set -l tests "" + set -l describes (spec.functions describe_) - # Flunk test if any single test fails, but do not stop the suite. - if not spec.eval $test --unit --depth 1 $output - set result 1 + # Load this suite unique set of tests. + for describe in $describes + spec.eval $describe --header $argv + spec.eval before_all $argv + + set tests (spec.functions it_) + set -l failed 0 + + for test in $tests + spec.eval before_each $argv + + if not spec.eval $test --tab 1 $argv + set result 1 # Flunk! + set failed (math 1+$failed) + end + + spec.eval after_each $argv + end + spec.eval after_all $argv + + if contains -- $argv[1] -v --verbose + spec.view --report (count $tests) $failed end - # Make sure to run after_each even if a test fails. - spec.eval after_each $output + # Clean up methods after all tests are finished. + spec.functions -e it_ before_ after_ end - spec.eval after_all $output + if [ -z "$describes" -o -z "$tests" ] + echo "No tests found." + return 1 + end + + spec.functions -e describe_ + return $result end diff --git a/plugins/fish-spec/spec.view.fish b/plugins/fish-spec/spec.view.fish new file mode 100644 index 0000000..dc2677f --- /dev/null +++ b/plugins/fish-spec/spec.view.fish @@ -0,0 +1,118 @@ +# NAME +# spec.view - print test output +# +# SYNOPSIS +# spec.view [OPTIONS] -- +# spec.view -r --report +# +# OPTIONS +# -r --report +# Print a passed / failed diagnostics report. Verbose assumed. +# +# -v --verbose +# Print test full output. +# +# -h --header +# +# -t --tab +# Use to specify the tab indentation of nested tests inside suites. +# +# AUTHORS +# Jorge Bucaran <@bucaran> +#/ +function spec.view + # Redefine these colors to customize the report. + set -l _color_default @white + set -l _color_pass @springgreen + set -l _color_info @lgray + set -l _color_fail @red + set -l _color_fail_info @black:yellow + set -l _color_dump 555 + + set -l verbose "" + if contains -- $argv[1] -r --report + set -l total_tests $argv[2] + set -l failed_tests $argv[3] + + set -l passed_tests (math $total_tests - $failed_tests) + + test $passed_tests -gt 0 + and msg \n $_color_pass "$passed_tests passing" + + test $failed_tests -gt 0 + and msg $_color_fail "$failed_tests failing" + echo # Blank link + + return 0 + end + + # Use test name or -d description field if available. + set -l info (type $argv[1] \ + | head -n 2 \ + | tail -n 1 \ + | cut -d" " -f4- \ + | sed "s/^\'//g" \ + | sed "s/\'\$//g") + + if [ -z "$info" ] + set info (echo $argv[1] | tr "_" " ") + end + + set -l result $argv[2] + set -l output + + # Parse format options. + set -l tab 1 + set -l header "" + if set -q argv[3] + for index in (seq 3 (count $argv)) + switch "$argv[$index]" + case -v --verbose + set verbose -v + case -h --header + set header $info + case -t --tab + set tab $argv[(math $index + 1)] + case -- + if [ $index -lt (count $argv) ] + set output $argv[(math $index + 1)..-1] + end + break + end + end + end + + # Print a header if available. + if [ -n "$header" -a "$verbose" ] + msg $_color_default _$header\_ + end + + # Process test functions with output. Typically it_ tests using `expect`. + if [ -n "$output" ] + set tab (printf " %.0s" (seq $tab)) + # Process succesful tests. + if [ $result -eq 0 ] + if [ -n "$verbose" ] + msg $tab $_color_pass ✔ $_color_info $info + else + echo -n (set_color 00FF7F). + end + else + msg $tab $_color_fail ✖ $_color_fail_info $info + + # Error dump parser, split output by \t. + set -l index (contains -i -- \t $output) + + # Transform condition string to TitleCase + set condition (echo $output[(math $index+1)] \ + | tr "-" " " \ + | cut -c 3- \ + | awk '{for(j=1;j<=NF;j++){ $j=toupper(substr($j,1,1)) substr($j,2) }}1') + + msg $tab __Expected__ + printf (set_color $_color_dump)"$tab %s\n" $output[1..(math $index-1)] + msg $tab $condition + printf (set_color $_color_dump)"$tab %s\n" $output[(math $index+2)..-1] + end + end +end diff --git a/plugins/fish-spec/spec/expect.to_be_false.spec.fish b/plugins/fish-spec/spec/expect.to_be_false.spec.fish index a53942a..5d5681a 100644 --- a/plugins/fish-spec/spec/expect.to_be_false.spec.fish +++ b/plugins/fish-spec/spec/expect.to_be_false.spec.fish @@ -1,16 +1,16 @@ import plugins/fish-spec -function describe_to_be_false -d 'expect --to-be-false' +function describe_expect_to_be_false function before_each set -e result end - function it_returns_1_when_evaluated_value_returns_0 + function it_returns_1_when_evaluated_value_is_0 echo (expect true --to-be-false; set result $status) >/dev/null expect $result --to-equal 1 end - function it_returns_0_when_evaluated_value_returns_1 + function it_returns_0_when_evaluated_value_is_1 echo (expect false --to-be-false; set result $status) >/dev/null expect $result --to-equal 0 end diff --git a/plugins/fish-spec/spec/expect.to_be_true.spec.fish b/plugins/fish-spec/spec/expect.to_be_true.spec.fish index 083b9ee..7096062 100644 --- a/plugins/fish-spec/spec/expect.to_be_true.spec.fish +++ b/plugins/fish-spec/spec/expect.to_be_true.spec.fish @@ -1,6 +1,6 @@ import plugins/fish-spec -function describe_to_be_true -d 'expect --to-be-true' +function describe_expect_to_be_true function before_each set -e result end diff --git a/plugins/fish-spec/spec/expect.to_contain.spec.fish b/plugins/fish-spec/spec/expect.to_contain.spec.fish index 7907178..e81b078 100644 --- a/plugins/fish-spec/spec/expect.to_contain.spec.fish +++ b/plugins/fish-spec/spec/expect.to_contain.spec.fish @@ -1,60 +1,60 @@ import plugins/fish-spec -function describe_to_contain -d 'expect --to-contain' +function describe_expect_to_contain function before_each set -e result end - function it_returns_0_when_arrays_are_the_same + function it_returns_0_when_lists_are_the_same set -l array 1 2 echo (expect $array --to-contain $array; set result $status) >/dev/null expect $result --to-equal 0 end - function it_returns_1_when_arrays_are_different + function it_returns_1_when_lists_are_different set -l array 1 2 echo (expect $array --to-contain 8 9; set result $status) >/dev/null expect $result --to-equal 1 end - function it_returns_0_when_arrays_have_the_same_elements_but_in_different_order + function it_returns_0_when_lists_have_the_same_item_but_in_different_order set -l array 1 2 echo (expect $array --to-contain 2 1; set result $status) >/dev/null expect $result --to-equal 0 end - function it_returns_0_when_expected_array_contains_the_element + function it_returns_0_when_expected_list_contains_the_item set -l array 1 2 echo (expect $array --to-contain 1; set result $status) >/dev/null expect $result --to-equal 0 end - function it_returns_1_when_expected_array_does_not_contain_the_element + function it_returns_1_when_expected_list_does_not_contain_the_item set -l array 1 2 echo (expect $array --to-contain 9; set result $status) >/dev/null expect $result --to-equal 1 end - function it_returns_0_when_expected_array_contains_all_elements + function it_returns_0_when_expected_list_contains_all_items set -l array 1 2 3 echo (expect $array --to-contain 1 2; set result $status) >/dev/null expect $result --to-equal 0 end - function it_returns_1_when_expected_array_does_not_contain_all_elements + function it_returns_1_when_expected_list_does_not_contain_all_items set -l array 1 2 3 echo (expect $array --to-contain 1 2 9; set result $status) >/dev/null expect $result --to-equal 1 end - function it_returns_1_when_expected_array_contains_less_elements + function it_returns_1_when_expected_list_contains_less_items set -l array 1 2 echo (expect $array --to-contain 1 2 9; set result $status) >/dev/null diff --git a/plugins/fish-spec/spec/expect.to_equal.spec.fish b/plugins/fish-spec/spec/expect.to_equal.spec.fish index 70c8b44..843b710 100644 --- a/plugins/fish-spec/spec/expect.to_equal.spec.fish +++ b/plugins/fish-spec/spec/expect.to_equal.spec.fish @@ -1,6 +1,6 @@ import plugins/fish-spec -function describe_to_equal -d 'expect --to-equal' +function describe_expect_to_equal function before_each set -e result end @@ -19,14 +19,14 @@ function describe_to_equal -d 'expect --to-equal' expect $result --to-equal 1 end - function it_returns_0_when_array_elements_are_in_the_same_order + function it_returns_0_when_list_items_are_in_the_same_order set -l array 1 2 echo (expect $array --to-equal 1 2; set result $status) >/dev/null expect $result --to-equal 0 end - function it_returns_1_when_array_elements_are_in_different_order + function it_returns_1_when_list_items_are_in_different_order set -l array 1 2 echo (expect $array --to-equal 2 1; set result $status) >/dev/null diff --git a/plugins/fish-spec/spec/expect.to_not_contain.spec.fish b/plugins/fish-spec/spec/expect.to_not_contain.spec.fish index debabe8..2fe1c4b 100644 --- a/plugins/fish-spec/spec/expect.to_not_contain.spec.fish +++ b/plugins/fish-spec/spec/expect.to_not_contain.spec.fish @@ -1,63 +1,63 @@ import plugins/fish-spec -function describe_to_not_contain -d 'expect --to-not-contain' +function describe_expect_to_not_contain function before_each set -e result end - function it_returns_1_when_arrays_are_the_same - set -l array 1 2 + function it_returns_1_when_lists_are_the_same + set -l list 1 2 - echo (expect $array --to-not-contain $array; set result $status) >/dev/null + echo (expect $list --to-not-contain $list; set result $status) >/dev/null expect $result --to-equal 1 end - function it_returns_0_when_arrays_are_different - set -l array 1 2 + function it_returns_0_when_lists_are_different + set -l list 1 2 - echo (expect $array --to-not-contain 8 9; set result $status) >/dev/null + echo (expect $list --to-not-contain 8 9; set result $status) >/dev/null expect $result --to-equal 0 end - function it_returns_1_when_arrays_have_the_same_elements_but_in_different_order - set -l array 1 2 + function it_returns_1_when_lists_have_the_same_items_but_in_different_order + set -l list 1 2 - echo (expect $array --to-not-contain 2 1; set result $status) >/dev/null + echo (expect $list --to-not-contain 2 1; set result $status) >/dev/null expect $result --to-equal 1 end - function it_returns_1_when_expected_array_contains_the_element - set -l array 1 2 + function it_returns_1_when_expected_list_contains_an_item + set -l list 1 2 - echo (expect $array --to-not-contain 1; set result $status) >/dev/null + echo (expect $list --to-not-contain 1; set result $status) >/dev/null expect $result --to-equal 1 end - function it_returns_0_when_expected_array_does_not_contain_the_element - set -l array 1 2 + function it_returns_0_when_expected_list_does_not_contain_an_item + set -l list 1 2 - echo (expect $array --to-not-contain 9; set result $status) >/dev/null + echo (expect $list --to-not-contain 9; set result $status) >/dev/null expect $result --to-equal 0 end - function it_returns_1_when_expected_array_contains_all_elements - set -l array 1 2 3 + function it_returns_1_when_expected_list_contains_all_items + set -l list 1 2 3 - echo (expect $array --to-not-contain 1 2; set result $status) >/dev/null + echo (expect $list --to-not-contain 1 2; set result $status) >/dev/null expect $result --to-equal 1 end - function it_returns_0_when_expected_array_does_not_contain_all_elements - set -l array 1 2 3 + function it_returns_0_when_expected_array_does_not_contain_any_items + set -l list 1 2 3 - echo (expect $array --to-not-contain 1 2 9; set result $status) >/dev/null + echo (expect $list --to-not-contain 1 2 9; set result $status) >/dev/null expect $result --to-equal 0 end - function it_returns_0_when_expected_array_contains_less_elements - set -l array 1 2 + function it_returns_0_when_expected_array_contains_less_items + set -l list 1 2 - echo (expect $array --to-not-contain 1 2 9; set result $status) + echo (expect $list --to-not-contain 1 2 9; set result $status) expect $result --to-equal 0 end end diff --git a/plugins/fish-spec/spec/list.erase.spec.fish b/plugins/fish-spec/spec/list.erase.spec.fish index af6f180..5924dbe 100644 --- a/plugins/fish-spec/spec/list.erase.spec.fish +++ b/plugins/fish-spec/spec/list.erase.spec.fish @@ -1,56 +1,71 @@ import plugins/fish-spec -function describe_list_erase -d "Testing Oh-My-Fish `list.erase` function..." +function describe_list.erase function before_each set -g nums_until_10 1 2 3 4 5 6 7 8 9 10 set -g odds_until_10 1 3 5 7 9 end - function it_erases_one_element -d "It should erase an element from a list." + function it_erases_one_element list.erase 1 nums_until_10 expect $nums_until_10 --to-not-contain 1 end - function it_erases_one_element_without_from_option \ - -d "It should erase an element with --from option." + function it_erases_one_element_without_from_option list.erase 1 --from nums_until_10 expect $nums_until_10 --to-not-contain 1 end - function it_erases_one_element_from_multiple_lists \ - -d "It should erase an element from multiple lists." + function it_erases_one_element_from_multiple_lists list.erase 1 --from nums_until_10 odds_until_10 expect $nums_until_10 --to-not-contain 1 and expect $odds_until_10 --to-not-contain 1 end - function it_erases_one_element_from_multiple_lists_when_only_one_has_the_element \ - -d "It should erase an element from multiple lists when only one has the element." + function it_erases_one_element_from_multiple_lists_when_only_one_has_the_element list.erase 2 --from nums_until_10 odds_until_10 expect $nums_until_10 --to-not-contain 2 end - function it_erases_multiple_elements \ - -d "It should erase multiple elements." + function it_erases_multiple_elements list.erase 1 2 nums_until_10 expect $nums_until_10 --to-not-contain 1 and expect $nums_until_10 --to-not-contain 2 end - function it_erases_multiple_elements_with_from_syntax \ - -d "It should erase multiple elements with --from option." + function it_erases_multiple_elements_with_from_syntax list.erase 1 2 --from nums_until_10 expect $nums_until_10 --to-not-contain 1 and expect $nums_until_10 --to-not-contain 2 end - function it_erases_multiple_elements_from_multiple_lists \ - -d "It should erase multiple elements from multiple lists." + function it_erases_multiple_elements_from_multiple_lists list.erase 1 2 --from nums_until_10 odds_until_10 expect $nums_until_10 --to-not-contain 1 and expect $nums_until_10 --to-not-contain 2 and expect $odds_until_10 --to-not-contain 1 end + + function it_returns_0_if_any_items_are_erased + list.erase 10 --from nums_until_10 + expect $status --to-equal 0 + end + + function it_returns_1_if_no_items_are_erased + list.erase 100 200 300 --from nums_until_10 + expect $status --to-equal 1 + end + + function it_returns_1_if_no_items_are_erased_from_any_lists + list.erase 100 200 300 --from nums_until_10 odds_until_10 + expect $status --to-equal 1 + end + + function it_returns_0_if_items_are_erased_from_some_but_not_all_lists + list.erase 1 2 3 --from nums_until_10 odds_until_10 + expect $status --to-equal 0 + end + end spec.run $argv diff --git a/plugins/fish-spec/spec/spec.spec.fish b/plugins/fish-spec/spec/spec.spec.fish new file mode 100644 index 0000000..f1116e6 --- /dev/null +++ b/plugins/fish-spec/spec/spec.spec.fish @@ -0,0 +1,130 @@ +import plugins/fish-spec + +function describe_fish-spec -d "Fish-Spec" + function it_has_an_output_if_suite_is_blank + set -l suite " + import plugins/fish-spec + spec.run + " + expect (run_nested_suite $suite) --to-equal "No tests found." + end + + function it_has_an_output_if_there_are_no_tests + set -l suite " + import plugins/fish-spec + function describe_blank_suite + end + spec.run + " + expect (run_nested_suite $suite) --to-equal "No tests found." + end + + function it_runs_all_describe_blocks + set -l describe_one 0 1 0 + set -l describe_two 1 0 0 + set -l describe_expects 1 1 0 + set -l suites + + for return_code_index in (seq (count $describe_one)) + set suites $suites " + import plugins/fish-spec + function describe_blank_suite + function it_returns_0_1_0_1_in_that_order + return $describe_one[$return_code_index] + end + end + function describe_another_blank_suite + function it_returns_1_0_0_1_in_that_order + return $describe_two[$return_code_index] + end + end + spec.run + " + end + for index in (seq (count $suites)) + run_nested_suite $suites[$index] + expect $status --to-equal $describe_expects[$index] + or return 1 + end + end + + function it_runs_all_it_blocks + set -l suite " + import plugins/fish-spec + + function describe_suite + function it_is_executed + return 0 + end + + function it_is_also_executed + return 0 + end + + function it_is_also_executed + return 1 + end + end + + spec.run + " + run_nested_suite $suite + expect $status --to-equal 1 + end + + function it_adds_a_dot_for_a_successful_expectation + set -l suite " + import plugins/fish-spec + + function describe_suite + function it_is_executed + expect 'success' --to-equal 'success' + end + end + + spec.run + " + set -l output (run_nested_suite $suite) + set -l dot (echo -ne (set_color 00FF7F).) + expect "$output" --to-equal $dot + end + + function it_adds_a_dot_for_each_successful_test + set -l suite " + import plugins/fish-spec + + function describe_suite + function it_is_executed + expect 'success' --to-equal 'success' + end + function it_is_executed_again + expect 'success' --to-equal 'success' + end + end + + spec.run + " + set -l output (run_nested_suite $suite) + set -l dot (echo -ne (set_color 00FF7F).) + expect "$output" --to-equal $dot$dot + end +end + +function run_nested_suite -a suite + # Erase and backup original suite functions to avoid an infinite loop. + spec.functions -eb it_ describe_ -- "backup." + + # Run nested suite + eval $suite + set -l result $status + + # Erase functions created by the nested suite + spec.functions -e it_ describe_ + + # Restore original suite functions + spec.functions -re backup. + + return $result +end + +# spec.run $argv diff --git a/script/run-tests.fish b/script/run-tests.fish index f3b43e0..39eab3f 100755 --- a/script/run-tests.fish +++ b/script/run-tests.fish @@ -1,5 +1,7 @@ #!/usr/bin/env fish - -for test in (find * -type f -print | grep 'spec.fish') - fish $test +set -l result 0 +for test in (find * -type f -print | grep "spec.fish") + fish $test $argv + or set result 1 end +exit $result diff --git a/spec/oh-my-fish.spec.fish b/spec/oh-my-fish.spec.fish index 00c0e8a..cdde09d 100755 --- a/spec/oh-my-fish.spec.fish +++ b/spec/oh-my-fish.spec.fish @@ -13,25 +13,19 @@ function describe_oh_my_fish -d "Oh-My-Fish test spec..." set fish_function_path $fish_function_path_bak end - function it_has_a_default_custom_directory \ - -d "It should have a default custom directory" - + function it_has_a_default_custom_directory set -e fish_custom load_oh_my_fish expect $fish_custom --to-eq "$HOME/.oh-my-fish/custom" end - function it_allows_the_custom_folder_location_to_be_customized \ - -d "It should allow modifying the location of the custom directory" - + function it_allows_the_custom_folder_location_to_be_customized set -g fish_custom /tmp load_oh_my_fish expect $fish_custom --to-eq '/tmp' end - function it_loads_all_custom_files \ - -d "It should load all custom files" - + function it_loads_all_custom_files set -g fish_custom /tmp echo 'set -gx TEST_LOAD_CUSTOM_FILE file_loaded' > $fish_custom/test.load @@ -39,18 +33,14 @@ function describe_oh_my_fish -d "Oh-My-Fish test spec..." expect $TEST_LOAD_CUSTOM_FILE --to-eq 'file_loaded' end - function it_loads_all_oh_my_fish_functions \ - -d "It should load all default functions" - + function it_loads_all_oh_my_fish_functions list.erase "$fish_path/functions/" --from fish_function_path load_oh_my_fish expect $fish_function_path --to-contain $fish_path/functions/ end - function it_loads_all_selected_plugins \ - -d "It should load all user selected plugins" - + function it_loads_all_selected_plugins list.erase "$fish_path/plugins/bak" \ "$fish_path/plugins/z" --from fish_function_path @@ -60,9 +50,7 @@ function describe_oh_my_fish -d "Oh-My-Fish test spec..." expect $fish_function_path --to-contain $fish_path/plugins/z end - function it_loads_the_selected_theme \ - -d "It should load the user selected theme" - + function it_loads_the_selected_theme list.erase "$fish_path/themes/l" --from fish_function_path set fish_theme l @@ -70,9 +58,7 @@ function describe_oh_my_fish -d "Oh-My-Fish test spec..." expect $fish_function_path --to-contain $fish_path/themes/l end - function it_reloads_with_status_of_0 \ - -d "It should reload the framework with \$status of 0" - + function it_reloads_with_status_of_0 load_oh_my_fish expect $status --to-equal 0 end @@ -82,5 +68,4 @@ function load_oh_my_fish . $fish_path/oh-my-fish.fish end -# Begin test suite ❯❯❯ spec.run $argv