#!/bin/sh # Smoke-tests the local installer: installs into out/install-test (never # ~/.local, never registering with Claude), checks the files, the launcher's # argument check, and that noid-mcp answers initialize and tools/list. It # never launches the GUI. Exits 0 only when everything passed. set -eu repo=$(cd "$(dirname "$0")/.." && pwd) cd "$repo" prefix="$repo/out/install-test" failures=0 fail() { echo "test-install: FAIL: $1" >&2 failures=$((failures + 1)) } rm -rf "$prefix" sh scripts/install-local.sh --prefix "$prefix" app="$prefix/share/noid/app" for f in "$prefix/bin/noid" "$prefix/bin/noid-mcp" "$prefix/share/applications/noid.desktop" \ "$app/main.js" "$app/mcp.js" "$app/index.html" "$app/preload.js" \ "$app/out/renderer/main.js" "$app/node_modules/chokidar" "$app/node_modules/readdirp" \ "$prefix/share/noid/electron/electron"; do [ -e "$f" ] || fail "missing $f" done [ -x "$prefix/bin/noid" ] || fail "bin/noid is not executable" [ -x "$prefix/bin/noid-mcp" ] || fail "bin/noid-mcp is not executable" grep -q "^Exec=$prefix/bin/noid --welcome$" "$prefix/share/applications/noid.desktop" \ || fail "the desktop entry's Exec line is wrong" # noid with a non-folder argument fails fast, without starting the app. if "$prefix/bin/noid" "$prefix/does-not-exist" 2>/dev/null; then fail "bin/noid accepted a non-folder" else status=$? [ "$status" -eq 1 ] || fail "bin/noid exited $status for a non-folder, expected 1" fi # --help, -h, bad options and extra folders are handled by the launcher itself, # before anything is started. A launch would create the log under # XDG_STATE_HOME, so its absence shows no Electron was started. XDG_STATE_HOME="$prefix/state" export XDG_STATE_HOME for flag in --help -h; do out=$("$prefix/bin/noid" "$flag" 2>/dev/null) || fail "bin/noid $flag exited non-zero" case "$out" in *"Usage: noid"*"--welcome"*) ;; *) fail "bin/noid $flag printed no usage on stdout: $out" ;; esac done status=0 err=$("$prefix/bin/noid" --bogus 2>&1 >/dev/null) || status=$? [ "$status" -eq 2 ] || fail "bin/noid --bogus exited $status, expected 2" case "$err" in *"unknown option"*) ;; *) fail "bin/noid --bogus gave no 'unknown option' on stderr: $err" ;; esac mkdir -p "$prefix/d1" "$prefix/d2" status=0 "$prefix/bin/noid" "$prefix/d1" "$prefix/d2" >/dev/null 2>&1 || status=$? [ "$status" -eq 2 ] || fail "bin/noid with two folders exited $status, expected 2" [ ! -e "$prefix/state" ] || fail "bin/noid started something (it wrote under XDG_STATE_HOME)" # noid-mcp --help prints its usage and returns without serving. mcp_help=$(timeout 30 "$prefix/bin/noid-mcp" --help) || fail "noid-mcp --help failed or timed out" case "$mcp_help" in *"Usage: noid-mcp"*) ;; *) fail "noid-mcp --help printed no usage: $mcp_help" ;; esac # noid-mcp speaks MCP over stdio: initialize, then tools/list. reply=$(printf '%s\n%s\n%s\n' \ '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"test-install","version":"0"}}}' \ '{"jsonrpc":"2.0","method":"notifications/initialized"}' \ '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \ | timeout 30 "$prefix/bin/noid-mcp" --agent test) || fail "noid-mcp exited non-zero or timed out" case "$reply" in *vault_info*) ;; *) fail "noid-mcp's tools/list has no vault_info: $reply" ;; esac if [ "$failures" -ne 0 ]; then echo "test-install: $failures failure(s)" >&2 exit 1 fi echo "test-install: ok"