diff --git a/package.json b/package.json index 9cd7e90ad..55ed8d372 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "rebundle": "node tools/cli/bundlers/bundle-web.js rebundle", "test": "npm run test:schemas && npm run test:refs && npm run test:install && npm run validate:schemas && npm run lint && npm run lint:md && npm run format:check", "test:coverage": "c8 --reporter=text --reporter=html npm run test:schemas", + "test:e2e:install": "bash test/test-cli-install-e2e.sh", "test:install": "node test/test-installation-components.js", "test:refs": "node test/test-file-refs-csv.js", "test:schemas": "node test/test-agent-schema.js", diff --git a/test/test-cli-install-e2e.sh b/test/test-cli-install-e2e.sh new file mode 100755 index 000000000..94fd411fc --- /dev/null +++ b/test/test-cli-install-e2e.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# CLI install smoke E2E test. +# Verifies non-interactive install succeeds in a clean temp project. + +set -euo pipefail + +echo "========================================" +echo "CLI Install Smoke E2E" +echo "========================================" +echo "" + +GREEN='\033[0;32m' +RED='\033[0;31m' +NC='\033[0m' + +PASSED=0 +FAILED=0 + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +TEMP_DIR="$(mktemp -d)" + +cleanup() { + rm -rf "$TEMP_DIR" +} +trap cleanup EXIT + +PROJECT_DIR="$TEMP_DIR/e2e-project" +mkdir -p "$PROJECT_DIR" + +echo "Test 1: Non-interactive install succeeds and creates BMAD layout" +if OUTPUT=$(node "$REPO_ROOT/tools/cli/bmad-cli.js" install \ + --directory "$PROJECT_DIR" \ + --modules bmm \ + --tools none \ + --yes \ + --user-name "E2E User" \ + --communication-language English \ + --document-output-language English \ + --output-folder _bmad-output 2>&1); then + if [ -d "$PROJECT_DIR/_bmad" ] && [ -f "$PROJECT_DIR/_bmad/_config/manifest.yaml" ]; then + if echo "$OUTPUT" | grep -q "clack.box is not a function"; then + echo -e "${RED}✗${NC} Install output still contains clack.box runtime error" + FAILED=$((FAILED + 1)) + else + echo -e "${GREEN}✓${NC} Install succeeded and created expected structure" + PASSED=$((PASSED + 1)) + fi + else + echo -e "${RED}✗${NC} Install completed but expected files were not created" + FAILED=$((FAILED + 1)) + fi +else + echo -e "${RED}✗${NC} Install command failed" + echo "$OUTPUT" + FAILED=$((FAILED + 1)) +fi +echo "" + +echo "========================================" +echo "Test Results:" +echo -e " Passed: ${GREEN}$PASSED${NC}" +echo -e " Failed: ${RED}$FAILED${NC}" +echo "========================================" + +if [ "$FAILED" -eq 0 ]; then + echo -e "\n${GREEN}✨ CLI install smoke E2E passed!${NC}\n" + exit 0 +fi + +echo -e "\n${RED}❌ CLI install smoke E2E failed${NC}\n" +exit 1 diff --git a/tools/cli/lib/prompts.js b/tools/cli/lib/prompts.js index 24500700b..020d55233 100644 --- a/tools/cli/lib/prompts.js +++ b/tools/cli/lib/prompts.js @@ -575,7 +575,26 @@ async function cancel(message = 'Operation cancelled') { */ async function box(content, title, options) { const clack = await getClack(); - clack.box(content, title, options); + + // @clack/prompts v1 does not expose `box`. Keep compatibility with older + // wrappers by degrading to `note`, then plain logging if needed. + if (typeof clack.box === 'function') { + clack.box(content, title, options); + return; + } + + if (typeof clack.note === 'function') { + clack.note(content, title || 'Info'); + return; + } + + if (clack.log && typeof clack.log.message === 'function') { + clack.log.message(title ? `${title}\n${content}` : content); + return; + } + + // Final defensive fallback if prompt APIs are unavailable. + console.log(title ? `${title}\n${content}` : content); } /**