#!/usr/bin/env bats init_repo() { local repo_dir="$1" local main_branch="$2" mkdir "$repo_dir" cd "$repo_dir" git init -b "$main_branch" git config user.email "john.doe@example.com" git config user.name "John Doe" echo ".git-check-assertions-cache" >>.gitignore git add .gitignore git commit -m "add .git-check-assertions-cache to gitignore" touch readme git add readme git commit -m "add readme" } setup() { set -euo pipefail bats_load_library bats-support bats_load_library bats-assert bats_load_library bats-file DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")" >/dev/null 2>&1 && pwd)" PATH="$DIR/../bin:$PATH" init_repo "$BATS_TEST_TMPDIR/repo" main } commit_with_assertion() { git commit --allow-empty -F - <<-EOF test \`\`\`git-check-assertions $1 \`\`\` EOF } @test "should not run any assertion blocks when on main" { commit_with_assertion "[success] touch ../test" run git-check-assertions assert_success assert_file_not_exists ../test } @test "should print success after completing" { run git-check-assertions assert_success assert_output --partial "Success!" } @test "should refuse to run when the index has changes" { echo "staged" >>readme git add readme run git-check-assertions assert_failure assert_output --partial "Uncommitted changes. Refusing to run." } @test "should refuse to run when the working tree has changes" { echo "unstaged" >>readme run git-check-assertions assert_failure assert_output --partial "Uncommitted changes. Refusing to run." } @test "should refuse to run when there are untracked files" { echo "new" >untracked run git-check-assertions assert_failure assert_output --partial "Uncommitted changes. Refusing to run." } @test "should not run any assertion blocks from main when on a feature branch" { commit_with_assertion "[success] touch ../test" git checkout -b feature git commit --allow-empty -m "feature" run git-check-assertions assert_success assert_file_not_exists ../test } @test "should not run any assertion blocks from master when on a feature branch" { init_repo "$BATS_TEST_TMPDIR/repo-master" master commit_with_assertion "[success] touch ../test" git checkout -b feature git commit --allow-empty -m "feature" run git-check-assertions assert_success assert_file_not_exists ../test } @test "should run all succeeding assertion blocks on the feature branch and finally return to the original branch" { git checkout -b feature commit_with_assertion "[success] touch ../test1" commit_with_assertion "[success] touch ../test2" run git-check-assertions assert_success assert_file_exists ../test1 assert_file_exists ../test2 run git symbolic-ref --short HEAD assert_output "feature" } @test "multiple git-check-assertions blocks in one commit message run in order" { git checkout -b feature git commit --allow-empty -F - <<-EOF test \`\`\`git-check-assertions [success] touch ../test1 \`\`\` \`\`\`git-check-assertions [success] touch ../test2 \`\`\` EOF run git-check-assertions assert_success assert_output --partial "git-check-assertions block 1:" assert_output --partial "git-check-assertions block 2:" assert_file_exists ../test1 assert_file_exists ../test2 } @test "should restore the commit between assertion blocks in one commit message" { git checkout -b feature echo old >readme git add readme git commit -m "old" echo new >readme git add readme git commit -F - <<-EOF update \`\`\`git-check-assertions [success] git checkout HEAD~ \`\`\` \`\`\`git-check-assertions [success] grep new readme \`\`\` EOF run git-check-assertions assert_success } @test "should stop at the first failing assertion block and return to the original branch" { git checkout -b feature commit_with_assertion "[success] touch ../test1 && exit 3" commit_with_assertion "[success] touch ../test2" run git-check-assertions assert_failure assert_file_exists ../test1 assert_file_not_exists ../test2 run git symbolic-ref --short HEAD assert_output "feature" } @test "should restore worktree when finished" { git checkout -b feature commit_with_assertion '[success] echo blah >> readme' run git-check-assertions assert_success assert_size_zero readme } @test "should restore worktree between commits" { git checkout -b feature commit_with_assertion '[success] echo blah >> readme' commit_with_assertion '[success] cp readme ../test' run git-check-assertions assert_success assert_size_zero ../test } @test "should restore worktree after a failure" { git checkout -b feature commit_with_assertion $'[success] echo blah >> readme\n[success] exit 3' run git-check-assertions assert_failure assert_size_zero readme } @test "should restore index when finished" { git checkout -b feature commit_with_assertion $'[success] echo blah >> readme\n[success] git add readme' run git-check-assertions assert_success assert_size_zero readme } @test "should restore index between commits" { git checkout -b feature commit_with_assertion $'[success] echo blah >> readme\n[success] git add readme' commit_with_assertion '[success] cp readme ../test' run git-check-assertions assert_success assert_size_zero ../test } @test "should restore index after a failure" { git checkout -b feature commit_with_assertion $'[success] echo blah >> readme\n[success] git add readme\n[success] exit 3' run git-check-assertions assert_failure assert_size_zero readme } @test "should skip cached commits on subsequent runs" { git checkout -b feature commit_with_assertion "[success] touch ../test" run git-check-assertions assert_success assert_file_exists ../test rm ../test run git-check-assertions assert_success assert_file_not_exists ../test } @test "should not cache failed commits" { git checkout -b feature commit_with_assertion "[success] touch ../test && exit 3" run git-check-assertions assert_failure assert_file_exists ../test rm ../test run git-check-assertions assert_failure assert_file_exists ../test } @test "should skip cached commits when multiple commits are cached" { git checkout -b feature commit_with_assertion "[success] touch ../test1" commit_with_assertion "[success] touch ../test2" run git-check-assertions assert_success assert_file_exists ../test1 assert_file_exists ../test2 rm ../test1 ../test2 run git-check-assertions assert_success assert_file_not_exists ../test1 assert_file_not_exists ../test2 } @test "assertions should run against the version of the code inside of the commit" { git checkout -b feature echo commit1 >readme git add readme commit_with_assertion '[success] grep commit1 readme' echo commit2 >readme git add readme commit_with_assertion '[success] grep commit2 readme' run git-check-assertions assert_success } @test "you can use git checkout in an assertion to assert against a mixed version of the code" { git checkout -b feature echo hello >src echo 'grep hello src' >tests git add src tests git commit -m 'add src and tests' echo goodbye >src echo 'grep goodbye src' >tests git add src tests commit_with_assertion $'[success] git checkout HEAD~ src\n[failure] bash tests' run git-check-assertions assert_success assert_file_contains src goodbye } @test "a [success] command should succeed if the executed command succeeded" { git checkout -b feature commit_with_assertion '[success] exit 0' run git-check-assertions assert_success } @test "a [success] command should fail if the executed command failed" { git checkout -b feature commit_with_assertion '[success] exit 1' run git-check-assertions assert_failure assert_output --partial "Expected command to succeed, but it failed." } @test "a [failure] command should succeed if the executed command failed" { git checkout -b feature commit_with_assertion '[failure] exit 1' run git-check-assertions assert_success } @test "a [failure] command should fail if the executed command succeeded" { git checkout -b feature commit_with_assertion '[failure] exit 0' run git-check-assertions assert_failure assert_output --partial "Expected command to fail, but it succeeded." } @test "an output line should succeed if the output contains the given string" { git checkout -b feature commit_with_assertion $'[success] echo hello\nhello' run git-check-assertions assert_success } @test "an output line should fail if the output does not contain the given string" { git checkout -b feature commit_with_assertion $'[success] echo hello\ngoodbye' run git-check-assertions assert_failure assert_output --partial "Expected output to contain: goodbye" assert_output --partial "Actual output: hello" } @test "an output line should also check stderr output" { git checkout -b feature commit_with_assertion $'[success] sh -c "echo err 1>&2"\nerr' run git-check-assertions assert_success } @test "multiple output lines should all be checked against the same command output" { git checkout -b feature commit_with_assertion $'[success] printf "hello\\n"\nhell\nello' run git-check-assertions assert_success } @test "an output line should fail with the missing substring" { git checkout -b feature commit_with_assertion $'[success] echo hello\nxyz' run git-check-assertions assert_failure assert_output --partial "Expected output to contain: xyz" assert_output --partial "Actual output: hello" } @test "executed commands should print command output" { git checkout -b feature commit_with_assertion '[success] sh -c "echo -n hello; echo -n world"' run git-check-assertions assert_success assert_output --partial "helloworld" }