mbland/slack-github-issues

View on GitHub
scripts/test

Summary

Maintainability
Test Coverage
#! /bin/bash
#
# Run automated tests
#
# Usage:
#   {{go}} {{cmd}} [--coverage|--edit|--list|--mocha-help] [<glob>...]
#
# Options:
#   --coverage    Collect test coverage data using istanbul
#   --edit        Open matching test files using `{{go}} edit`
#   --list        List test suite names without executing them
#   --mocha-help  Show output from `mocha --help`
#
# In addition to the above option flags, all underlying mocha flags are
# available.
#
# Without <glob> arguments, runs (or edits, or lists) all tests. With one or
# more <glob> arguments, only runs tests matching 'tests/<glob>-test.js'.
#
# The '--coverage' flag will place its output in a directory called 'coverage'.
# An HTML report will be available at 'coverage/lcov-report/index.html'.

declare -r __GO_TEST_FLAGS=('--coverage' '--edit' '--list' '--mocha-help')
declare -r __GO_TEST_GLOB_ARGS=('tests' '-test.js')
declare -r __GO_MOCHA_FLAGS_WITH_ARGS=(
  '-O' '--reporter-options'
  '-R' '--reporter'
  '-g' '--grep'
  '-f' '--fgrep'
  '-r' '--require'
  '-s' '--slow'
  '-t' '--timeout'
  '-u' '--ui'
  '-w' '--watch'
  '--compilers'
  '--globals'
  '--opts'
  '--retries'
  '--watch-extensions'
)

_test_mocha_flags() {
  local flag_line_pattern='^ *-'
  local line

  mocha -h | while read -r line; do
    if [[ "$line" =~ $flag_line_pattern ]]; then
      local line="${line#*-}"
      line="${line%%[ <]*}"
      echo "-${line/,/}"
    fi
  done
}

_test_tab_completion() {
  local word_index="$1"
  shift
  local args=("$@")
  local word="${args[$word_index]}"

  if [[ "$word_index" -eq '0' ]]; then
    if [[ "${1:0:1}" == '-' ]]; then
      compgen -W "${__GO_TEST_FLAGS[*]} $(_test_mocha_flags)" -- "$1"
      return
    else
      echo '-'
    fi
  fi
  @go 'glob' '--complete' "$((word_index + ${#__GO_TEST_GLOB_ARGS[@]}))" \
    "${__GO_TEST_GLOB_ARGS[@]}" "${args[@]}"
}

_test_is_mocha_flag_with_arg() {
  local i

  for ((i=0; i != "${#__GO_MOCHA_FLAGS_WITH_ARGS[@]}"; ++i)); do
    if [[ "${__GO_MOCHA_FLAGS_WITH_ARGS[$i]}" == "$1" ]]; then
      return 0
    fi
  done
  return 1
}

_test_parse_command_line() {
  while [[ "$#" -ne 0 ]]; do
    if [[ "${1:0:1}" == '-' ]]; then
      if [[ "${#glob_patterns[@]}" -ne '0' ]]; then
        printf "Please specify all flags before glob patterns." >&2
        return 1
      fi

      __test_mocha_flags+=("$1")
      if _test_is_mocha_flag_with_arg "$1"; then
        __test_mocha_flags+=("$2")
        shift
      fi
    else
      __test_glob_patterns+=("$1")
    fi
    shift
  done
}

_test_run_mocha() {
  local __test_mocha_flags=()
  local __test_glob_patterns=()
  local help_flag_pattern='-(h|-help)'
  local argv=()

  _test_parse_command_line "$@"

  if [[ "${__test_mocha_flags[*]}" =~ $help_flag_pattern ]]; then
    mocha -h
    return
  fi

  argv=("${__test_mocha_flags[@]}"
    $(@go 'glob' "${__GO_TEST_GLOB_ARGS[@]}" "${__test_glob_patterns[@]}"))

  if [[ "$__COVERAGE_RUN" == 'true' ]]; then
    istanbul -- cover node_modules/.bin/_mocha "${argv[@]}"
  else
    mocha "${argv[@]}"
  fi
}

_test_coverage() {
  local report_path="${_GO_ROOTDIR}/coverage/lcov-report/index.html"
  local lcov_info_path="${_GO_ROOTDIR}/coverage/lcov.info"

  rm -f "$report_path"
  __COVERAGE_RUN='true' _test_run_mocha "${@:2}"

  if [[ ! -r "$report_path" ]]; then
    return 1
  elif [[ -z "$CI" ]]; then
    echo "Report saved as: $report_path"
    if command -v open >/dev/null; then
      open "$report_path"
    fi
  else
    if ! coveralls < "$lcov_info_path"; then
      echo "Failed to send coverage report to Coveralls." >&2
      return 1
    fi
    echo -n 'Coverage report sent to Coveralls: '
    echo 'https://coveralls.io/github/mbland/go-script-bash'

    if [[ -n "$CODECLIMATE_REPO_TOKEN" ]]; then
      if ! codeclimate-test-reporter < "$lcov_info_path"; then
        echo 'Failed to send coverage report to Code Climate.' >&2
        return 1
      fi
      echo -n 'Coverage report sent to Code Climate: '
      echo 'https://codeclimate.com/github/mbland/slack-emoji-issues'
    fi
  fi
}

_test() {
  if [[ "$1" == '--complete' ]]; then
    # Tab completions
    shift
    _test_tab_completion "$@"
    return
  fi

  if [[ "$1" == '--coverage' ]]; then
    _test_coverage
  elif [[ "$1" == '--list' ]]; then
    shift
    @go 'glob' '--trim' "${__GO_TEST_GLOB_ARGS[@]}" "$@"
  elif [[ "$1" == '--edit' ]]; then
    shift
    local tests=($(@go 'glob' "${__GO_TEST_GLOB_ARGS[@]}" "$@"))
    @go 'edit' "${tests[@]}"
  elif [[ "$1" == '--mocha-help' ]]; then
    mocha -h
  else
    _test_run_mocha "$@"
  fi
}

_test "$@"