diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..01dcfd1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,38 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +jobs: + test: + runs-on: ubuntu-${{ matrix.ubuntu }} + strategy: + matrix: + ubuntu: ["22.04", "24.04"] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install test deps + run: | + pip install pytest + sudo apt-get install -y bats shellcheck inkscape + + - name: Python unit tests + run: pytest tests/test_merge_prefs.py -v + + - name: Shellcheck + run: | + shellcheck install.sh + shellcheck uninstall.sh + shellcheck scripts/detect_platform.sh + + - name: Bats integration tests + run: bats tests/test_install.bats diff --git a/tests/test_install.bats b/tests/test_install.bats new file mode 100644 index 0000000..2522352 --- /dev/null +++ b/tests/test_install.bats @@ -0,0 +1,135 @@ +#!/usr/bin/env bats +# Integration tests for install.sh and uninstall.sh +# Requires: bats-core (https://github.com/bats-core/bats-core) + +REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)" + +setup() { + # Each test gets a fresh temp home directory + export TEST_HOME + TEST_HOME="$(mktemp -d)" + export HOME="$TEST_HOME" + export XDG_CONFIG_HOME="$TEST_HOME/.config" + + # Inject a fake inkscape so check_deps passes without the real binary + local fake_bin="$TEST_HOME/bin" + mkdir -p "$fake_bin" + printf '#!/bin/sh\necho "Inkscape 1.3.2"\n' > "$fake_bin/inkscape" + chmod +x "$fake_bin/inkscape" + export PATH="$fake_bin:$PATH" +} + +teardown() { + rm -rf "$TEST_HOME" +} + +_run_install() { + bash "$REPO_ROOT/install.sh" --preset="${1:-cc}" --yes 2>&1 +} + +_config_root() { + echo "$TEST_HOME/.config/inkscape" +} + +# ── Backup ──────────────────────────────────────────────────────────────────── + +@test "backup is created on first install" { + mkdir -p "$(_config_root)" + echo '' > "$(_config_root)/preferences.xml" + _run_install cc + local backup + backup=$(ls -1d "$(_config_root)".bak-illuscape-* 2>/dev/null | head -1) + [ -n "$backup" ] + [ -f "$backup/preferences.xml" ] +} + +@test "second install does not overwrite backup" { + mkdir -p "$(_config_root)" + echo '' > "$(_config_root)/preferences.xml" + _run_install cc + sleep 1 + _run_install cc + local backup_count + backup_count=$(ls -1d "$(_config_root)".bak-illuscape-* 2>/dev/null | wc -l) + [ "$backup_count" -eq 1 ] +} + +# ── Keys ────────────────────────────────────────────────────────────────────── + +@test "CC preset installs illustrator-cc.xml" { + _run_install cc + [ -f "$(_config_root)/keys/illustrator-cc.xml" ] +} + +@test "CS6 preset installs illustrator-cs6.xml" { + _run_install cs6 + [ -f "$(_config_root)/keys/illustrator-cs6.xml" ] +} + +@test "CC preset does not install cs6 key file" { + _run_install cc + [ ! -f "$(_config_root)/keys/illustrator-cs6.xml" ] +} + +# ── Palettes ────────────────────────────────────────────────────────────────── + +@test "all palette files are installed" { + _run_install cc + [ -f "$(_config_root)/palettes/Illustrator-Defaults.gpl" ] + [ -f "$(_config_root)/palettes/Illustrator-Grays.gpl" ] + [ -f "$(_config_root)/palettes/Illustrator-Earth.gpl" ] +} + +# ── Templates ───────────────────────────────────────────────────────────────── + +@test "all template files are installed" { + _run_install cc + [ -f "$(_config_root)/templates/Letter.svg" ] + [ -f "$(_config_root)/templates/A4.svg" ] + [ -f "$(_config_root)/templates/Web-1920x1080.svg" ] + [ -f "$(_config_root)/templates/Web-1280x720.svg" ] + [ -f "$(_config_root)/templates/Print-CMYK-Letter.svg" ] + [ -f "$(_config_root)/templates/Print-CMYK-A4.svg" ] +} + +# ── Preferences merge ───────────────────────────────────────────────────────── + +@test "preferences.xml is created when missing" { + _run_install cc + [ -f "$(_config_root)/preferences.xml" ] +} + +@test "CC preset sets px units in preferences.xml" { + _run_install cc + grep -q 'doc="px"' "$(_config_root)/preferences.xml" +} + +@test "CS6 preset sets pt units in preferences.xml" { + _run_install cs6 + grep -q 'doc="pt"' "$(_config_root)/preferences.xml" +} + +# ── Noninteractive ──────────────────────────────────────────────────────────── + +@test "--preset flag skips interactive prompt" { + # If prompt were shown, it would hang — the test itself proves it didn't + run bash "$REPO_ROOT/install.sh" --preset=cc --yes + [ "$status" -eq 0 ] +} + +# ── Uninstall ───────────────────────────────────────────────────────────────── + +@test "uninstall restores preferences.xml from backup" { + mkdir -p "$(_config_root)" + echo '' \ + > "$(_config_root)/preferences.xml" + _run_install cc + bash "$REPO_ROOT/uninstall.sh" + grep -q 'id="original"' "$(_config_root)/preferences.xml" +} + +@test "uninstall removes palette files" { + _run_install cc + bash "$REPO_ROOT/uninstall.sh" + [ ! -f "$(_config_root)/palettes/Illustrator-Defaults.gpl" ] +}