From 286fb3f7ad5cfe633774bc908e590cdfb4ec3038 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 6 Jun 2026 02:42:12 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=AA=20Add=20unit=20tests=20for=20idsta?= =?UTF-8?q?ck-status=20and=20integrate=20into=20smoke=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added `test/test-status.sh` to thoroughly test `idstack-status` against various states, including missing setups, mock timeline generation, learning logs, and exports. Also moved tests out of `integration-test.sh` and hooked `test-status.sh` inside `smoke-test.sh` for reliable regression checking. Co-authored-by: savvides <1580637+savvides@users.noreply.github.com> --- test/integration-test.sh | 21 ------- test/smoke-test.sh | 5 ++ test/test-status.sh | 120 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 21 deletions(-) create mode 100755 test/test-status.sh diff --git a/test/integration-test.sh b/test/integration-test.sh index bf45ca7..0442df2 100755 --- a/test/integration-test.sh +++ b/test/integration-test.sh @@ -81,27 +81,6 @@ check "no file returns empty" \ echo "" -# --- idstack-status --- -echo "## idstack-status" - -check "no timeline shows empty state message" \ - "rm -f .idstack/timeline.jsonl && $IDSTACK_DIR/bin/idstack-status | grep -q 'No course data yet'" - -# Rebuild timeline for status tests -$IDSTACK_DIR/bin/idstack-timeline-log '{"skill":"needs-analysis","event":"completed","training_justified":true}' -$IDSTACK_DIR/bin/idstack-timeline-log '{"skill":"course-quality-review","event":"completed","score":65,"dimensions":{"teaching_presence":7,"social_presence":3,"cognitive_presence":5}}' - -check "shows skills completed checkboxes" \ - "$IDSTACK_DIR/bin/idstack-status | grep -q '\[x\] /needs-analysis'" - -check "shows quality trend" \ - "$IDSTACK_DIR/bin/idstack-status | grep -q 'Quality trend: 65'" - -check "suggests next skill" \ - "$IDSTACK_DIR/bin/idstack-status | grep -q 'Suggested next'" - -echo "" - # --- idstack-gen-skills --- echo "## idstack-gen-skills" diff --git a/test/smoke-test.sh b/test/smoke-test.sh index b18ec85..5152e11 100755 --- a/test/smoke-test.sh +++ b/test/smoke-test.sh @@ -140,6 +140,11 @@ if [ -x "$IDSTACK_DIR/test/test-manifest-merge.sh" ]; then check "manifest-merge unit tests pass" "'$IDSTACK_DIR/test/test-manifest-merge.sh'" fi +# idstack-status unit tests +if [ -x "$IDSTACK_DIR/test/test-status.sh" ]; then + check "idstack-status unit tests pass" "'$IDSTACK_DIR/test/test-status.sh'" +fi + # Version classifier (shared by setup + bin/idstack-doctor) must classify # multi-digit versions correctly. Pinned to catch the pattern-fragility # regression Gemini flagged twice. diff --git a/test/test-status.sh b/test/test-status.sh new file mode 100755 index 0000000..1db8436 --- /dev/null +++ b/test/test-status.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env bash +# Unit tests for bin/idstack-status. +# Run from the repo root (or sourced by smoke-test.sh). + +set -e + +PASS=0 +FAIL=0 +TOTAL=0 + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +STATUS="$REPO_ROOT/bin/idstack-status" + +assert() { + TOTAL=$((TOTAL + 1)) + if eval "$2" >/dev/null 2>&1; then + PASS=$((PASS + 1)) + echo " PASS: $1" + else + FAIL=$((FAIL + 1)) + echo " FAIL: $1" + fi +} + +# Skip the suite if python3 is missing (the tool requires python3). +if ! command -v python3 >/dev/null 2>&1; then + echo "test-status: python3 not available, skipping" + exit 0 +fi + +if [ ! -x "$STATUS" ]; then + echo "test-status: $STATUS missing or not executable" + exit 1 +fi + +WORK=$(mktemp -d) +trap 'rm -rf "$WORK"' EXIT + +# idstack-status looks for files relative to current working directory +cd "$WORK" + +echo "test-status" +echo "" + +# --- Test 1: No state --- +assert "no timeline shows empty state message" "$STATUS | grep -q 'No course data yet'" + +# --- Test 2: Project name from manifest --- +mkdir -p .idstack +cat > .idstack/project.json <<'JSON' +{ + "project_name": "Test Course 123" +} +JSON +cat > .idstack/timeline.jsonl <<'JSON' +{"skill":"needs-analysis","event":"completed","training_justified":true} +JSON +assert "project name from manifest" "$STATUS | grep -q 'Project: Test Course 123'" + +# --- Test 3: Timeline parsing --- +cat > .idstack/timeline.jsonl <<'JSON' +{"skill":"needs-analysis","event":"completed","training_justified":true} +{"skill":"course-quality-review","event":"completed","score":65,"dimensions":{"teaching_presence":7,"social_presence":3,"cognitive_presence":5}} +{"skill":"course-quality-review","event":"completed","score":85,"dimensions":{"teaching_presence":8,"social_presence":7,"cognitive_presence":8}} +JSON +assert "shows skills completed checkboxes" "$STATUS | grep -q '\[x\] /needs-analysis'" +assert "shows quality trend" "$STATUS | grep -q 'Quality trend: 65 -> 85'" +assert "suggests next skill" "$STATUS | grep -q 'Suggested next: /learning-objectives'" + +# --- Test 4: Learnings log --- +cat > .idstack/learnings.jsonl <<'JSON' +{"skill":"needs-analysis","type":"operational","insight":"Learned X"} +{"skill":"needs-analysis","type":"pattern","insight":"Learned Y"} +JSON +assert "shows learnings count" "$STATUS | grep -q 'Learnings: 2 discoveries stored'" + +# --- Test 5: Exports directory --- +mkdir -p .idstack/exports/test-course-123 +touch .idstack/exports/test-course-123/index.html +touch .idstack/exports/test-course-123/other-report.html +assert "reports section present" "$STATUS | grep -q 'Reports (open in a browser for the human view)'" +assert "index.html listed" "$STATUS | grep -q 'test-course-123/index.html'" +assert "other report listed" "$STATUS | grep -q 'test-course-123/other-report.html'" + +# --- Test 6: Readiness flag - INCOMPLETE --- +# Using readiness should show incomplete when missing skills +assert "readiness incomplete due to missing reviews" "$STATUS --readiness | grep -q 'INCOMPLETE'" + +# --- Test 7: Readiness flag - NOT-READY --- +# Complete the timeline for readiness +cat >> .idstack/timeline.jsonl <<'JSON' +{"skill":"red-team","event":"completed"} +{"skill":"accessibility-review","event":"completed"} +JSON + +# Default manifest with poor scores +cat > .idstack/project.json <<'JSON' +{ + "project_name": "Test Course 123", + "quality_review": {"overall_score": 60}, + "red_team_audit": {"findings_summary": {"critical": 2}}, + "accessibility_review": {"score": {"overall": 70}} +} +JSON +assert "readiness not-ready due to low scores" "$STATUS --readiness | grep -q 'NOT-READY'" + +# --- Test 8: Readiness flag - READY TO EXPORT --- +cat > .idstack/project.json <<'JSON' +{ + "project_name": "Test Course 123", + "quality_review": {"overall_score": 80}, + "red_team_audit": {"findings_summary": {"critical": 0}}, + "accessibility_review": {"score": {"overall": 90}} +} +JSON +assert "readiness ready to export" "$STATUS --readiness | grep -q 'READY TO EXPORT'" + +echo "" +echo "test-status: $PASS/$TOTAL passed, $FAIL failed" +[ "$FAIL" -eq 0 ] && exit 0 || exit 1