Skip to content

Tests

Tests #558

Workflow file for this run

name: Tests
on:
workflow_dispatch:
push:
branches: [main]
pull_request:
branches: [main]
merge_group:
permissions:
contents: read
# Cancel in-progress runs for pull requests when developers push
# additional changes
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
# Unit/component tests run under LuaJIT with a mocked vim global (busted), so
# they do not need a real Neovim binary β€” hence no neovim-version matrix here.
# Real-Neovim coverage lives in the integration-tests job below.
unit-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
persist-credentials: false
# Build deps: PUC Lua builds from source, and the test rocks compile C modules.
- name: Install build dependencies
run: |
sudo apt-get -o Acquire::Retries=3 update
sudo apt-get -o Acquire::Retries=3 install -y build-essential libreadline-dev unzip
- name: Set up mise
uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1
- name: Install release tooling dependencies
env:
NPM_CONFIG_IGNORE_SCRIPTS: "true"
run: npm ci --prefix scripts
- name: Run release tooling tests
run: npm --prefix scripts run test:release-please-runner
# Cache the rock tree (rebuilt from luarocks.org otherwise); a miss just rebuilds.
- name: Cache Lua test rocks
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: .luarocks
key: luarocks-${{ runner.os }}-${{ hashFiles('mise.toml') }}
- name: Install Lua test rocks
run: mise run setup
- name: Run luacheck
run: mise run check
- name: Run tests
run: mise run test
- name: Check formatting
run: mise run format-check
- name: Generate coverage report
run: |
if [ -f "luacov.stats.out" ]; then
./.luarocks/bin/luacov
echo "Creating lcov.info from luacov.report.out"
{
echo "TN:"
grep -E "^Summary$" -A1000 luacov.report.out | grep -E "^[^ ].*:" | while read -r line; do
file=$(echo "$line" | cut -d':' -f1)
echo "SF:$file"
percent=$(echo "$line" | grep -oE "[0-9\.]+%" | tr -d '%')
if [ -n "$percent" ]; then
echo "DA:1,1"
echo "LF:1"
echo "LH:$percent"
fi
echo "end_of_record"
done
} > lcov.info
{
echo "## πŸ“Š Test Coverage Report"
echo ""
if [ -f "luacov.report.out" ]; then
overall_coverage=$(grep -E "Total.*%" luacov.report.out | grep -oE "[0-9]+\.[0-9]+%" | head -1)
if [ -n "$overall_coverage" ]; then
echo "**Overall Coverage: $overall_coverage**"
echo ""
fi
echo "| File | Coverage |"
echo "|------|----------|"
grep -E "^[^ ].*:" luacov.report.out | while read -r line; do
file=$(echo "$line" | cut -d':' -f1)
percent=$(echo "$line" | grep -oE "[0-9]+\.[0-9]+%" | head -1)
if [ -n "$percent" ]; then
# Add emoji based on coverage level
percent_num="${percent%.*}"
if [ "$percent_num" -ge 90 ]; then
emoji="🟒"
elif [ "$percent_num" -ge 70 ]; then
emoji="🟑"
else
emoji="πŸ”΄"
fi
echo "| \`$file\` | $emoji $percent |"
fi
done
else
echo "❌ No coverage report generated"
fi
} >> "$GITHUB_STEP_SUMMARY"
else
{
echo "## πŸ“Š Test Coverage Report"
echo ""
echo "❌ No coverage data found - tests may not have run with coverage enabled"
} >> "$GITHUB_STEP_SUMMARY"
fi
integration-tests:
runs-on: ubuntu-latest
needs: unit-tests
strategy:
matrix:
neovim-version: ["stable"]
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
persist-credentials: false
# Neovim here comes from action-setup-vim (matrix-driven), independent of
# the mise.toml neovim pin used for local dev.
- name: Setup Neovim
uses: rhysd/action-setup-vim@8e931b9954b19d4203d5caa5ff5521f3bc21dcc7 # v1.4.2
with:
neovim: true
version: ${{ matrix.neovim-version }}
- name: Install test dependencies
run: |
git clone --depth 1 https://github.com/nvim-lua/plenary.nvim ~/.local/share/nvim/site/pack/vendor/start/plenary.nvim
ln -s "$(pwd)" ~/.local/share/nvim/site/pack/vendor/start/claudecode.nvim
- name: Run integration tests
run: ./scripts/run_integration_tests_individually.sh
# Real-Neovim regression gate for issue #238 (reject-with-:q). The unit spec
# only exercises the WinClosed handler logic against a mock; this drives a
# genuine `:q` and self-reports via cquit (exit 0 = fixed, 1 = regressed).
- name: Reject-on-quit regression gate (#238)
run: nvim --headless -u NONE -l scripts/repro_issue_238.lua
required:
name: Required
runs-on: ubuntu-latest
needs:
- unit-tests
- integration-tests
if: ${{ always() }}
steps:
- name: Check required jobs
env:
UNIT_TESTS_RESULT: ${{ needs.unit-tests.result }}
INTEGRATION_TESTS_RESULT: ${{ needs.integration-tests.result }}
run: |
echo "unit-tests: $UNIT_TESTS_RESULT"
echo "integration-tests: $INTEGRATION_TESTS_RESULT"
if [ "$UNIT_TESTS_RESULT" != "success" ] || [ "$INTEGRATION_TESTS_RESULT" != "success" ]; then
echo "One or more required jobs failed."
exit 1
fi