231 lines
14 KiB
Bash
Executable File
231 lines
14 KiB
Bash
Executable File
#!/bin/bash
|
|
# test_visual_artifacts_md.sh - Verify bundle/context/visual-artifacts.md (task-6)
|
|
# RED: Run before file is created (should fail)
|
|
# GREEN: Run after file is created (should pass)
|
|
|
|
REPO=/home/ken/workspace/research-workbench
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
check_file_exists() {
|
|
local path="$1"
|
|
if [ -f "$REPO/$path" ]; then
|
|
echo "PASS: '$path' exists"
|
|
((PASS++))
|
|
else
|
|
echo "FAIL: '$path' should exist but is missing"
|
|
((FAIL++))
|
|
fi
|
|
}
|
|
|
|
check_contains() {
|
|
local file="$1"
|
|
local description="$2"
|
|
local pattern="$3"
|
|
if grep -qF -- "$pattern" "$REPO/$file" 2>/dev/null; then
|
|
echo "PASS: $file contains '$description'"
|
|
((PASS++))
|
|
else
|
|
echo "FAIL: $file is missing '$description'"
|
|
((FAIL++))
|
|
fi
|
|
}
|
|
|
|
check_regex() {
|
|
local file="$1"
|
|
local description="$2"
|
|
local pattern="$3"
|
|
if grep -qE "$pattern" "$REPO/$file" 2>/dev/null; then
|
|
echo "PASS: $file matches '$description'"
|
|
((PASS++))
|
|
else
|
|
echo "FAIL: $file is missing '$description' (pattern: $pattern)"
|
|
((FAIL++))
|
|
fi
|
|
}
|
|
|
|
TARGET="bundle/context/visual-artifacts.md"
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# File existence
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
echo "=== Checking $TARGET exists ==="
|
|
check_file_exists "$TARGET"
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Intro section
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "=== Checking Intro section ==="
|
|
check_regex "$TARGET" "intro / overview heading" "^# |^## "
|
|
check_contains "$TARGET" "visual fenced code block tag" '```visual'
|
|
check_regex "$TARGET" "sandboxed iframe mention" 'sandbox|iframe|sandboxed'
|
|
check_regex "$TARGET" "pre-loaded libraries mention" 'pre.loaded|preloaded|pre-loaded'
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# When to Generate section
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "=== Checking When to Generate section ==="
|
|
check_regex "$TARGET" "When to Generate heading" 'When to Generate|When to Use'
|
|
check_regex "$TARGET" "comparing options trigger" 'compar'
|
|
check_regex "$TARGET" "trends trigger" 'trend'
|
|
check_regex "$TARGET" "locations trigger" 'locat'
|
|
check_regex "$TARGET" "scoring/ranking trigger" 'scor|rank'
|
|
check_regex "$TARGET" "budget/breakdown trigger" 'budget|breakdown'
|
|
check_regex "$TARGET" "dashboard trigger" 'dashboard'
|
|
check_regex "$TARGET" "proactive / don't wait to be asked" "proactive|don.t wait|without being asked"
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Available Libraries section
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "=== Checking Available Libraries section ==="
|
|
check_regex "$TARGET" "Available Libraries heading" 'Available Lib|Libraries.*pre'
|
|
check_regex "$TARGET" "Tabler CSS entry" 'Tabler'
|
|
check_regex "$TARGET" "Chart.js entry" 'Chart\.js|Chart'
|
|
check_contains "$TARGET" "Chart global variable" '`Chart`'
|
|
check_regex "$TARGET" "Leaflet.js entry" 'Leaflet'
|
|
check_contains "$TARGET" "L global variable" '`L`'
|
|
check_regex "$TARGET" "React v19 entry" 'React.*19|React v19'
|
|
check_contains "$TARGET" "React global" '`React`'
|
|
check_contains "$TARGET" "ReactDOM global" '`ReactDOM`'
|
|
check_regex "$TARGET" "Babel entry" 'Babel'
|
|
check_regex "$TARGET" "JSX compilation" 'JSX|jsx'
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Output Format section
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "=== Checking Output Format section ==="
|
|
check_regex "$TARGET" "Output Format heading" 'Output Format'
|
|
check_contains "$TARGET" "visual tag in output example" '```visual'
|
|
check_regex "$TARGET" "title field" '"title"'
|
|
check_regex "$TARGET" "code field" '"code"'
|
|
check_regex "$TARGET" "data field" '"data"'
|
|
check_regex "$TARGET" "height field" '"height"'
|
|
check_regex "$TARGET" "height default 300" '300'
|
|
check_regex "$TARGET" "height max 800" '800'
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Code Formats section
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "=== Checking Code Formats section ==="
|
|
check_regex "$TARGET" "Code Formats heading" 'Code Format'
|
|
check_regex "$TARGET" "JSX auto-detection" 'JSX|React.*detect|detect.*React'
|
|
check_regex "$TARGET" "HTML detection" 'HTML.*detect|detect.*HTML|<div|<table'
|
|
check_regex "$TARGET" "Plain JS format" 'Plain JS|plain.*js|JS.*function'
|
|
check_regex "$TARGET" "Babel compilation" 'Babel.*compil|compil.*Babel'
|
|
check_regex "$TARGET" "App component auto-render" 'App.*component|auto.render|auto-render'
|
|
check_contains "$TARGET" "#root element" '#root'
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Code Scope section
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "=== Checking Code Scope section ==="
|
|
check_regex "$TARGET" "Code Scope heading" 'Code Scope|Available.*Scope|Scope.*Variables'
|
|
check_contains "$TARGET" "data variable in scope" '`data`'
|
|
check_contains "$TARGET" "mcp variable in scope" '`mcp`'
|
|
check_contains "$TARGET" "root variable in scope" '`root`'
|
|
check_contains "$TARGET" "Chart variable in scope" '`Chart`'
|
|
check_contains "$TARGET" "L variable in scope" '`L`'
|
|
check_regex "$TARGET" "mcp.sendMessage" 'sendMessage|mcp\.sendMessage'
|
|
check_regex "$TARGET" "mcp.callTool" 'callTool|mcp\.callTool'
|
|
check_regex "$TARGET" "mcp.resize" 'resize|mcp\.resize'
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Example Patterns section - all 5
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "=== Checking Example 1: Comparison Table ==="
|
|
check_regex "$TARGET" "Example 1 heading" 'Comparison Table|Example.*1'
|
|
check_regex "$TARGET" "Hybrid Cars title" 'Hybrid Cars Under|Hybrid Cars.*10K'
|
|
check_regex "$TARGET" "table headers (Model/Year/Price/Miles/MPG)" 'Model|Year|Price|Miles|MPG'
|
|
check_regex "$TARGET" "Prius sample data" 'Prius'
|
|
check_regex "$TARGET" "data.items reference" 'data\.items|data\[.items'
|
|
check_regex "$TARGET" "green price color" '#7af7a2|7af7a2'
|
|
check_regex "$TARGET" "blue link color" '#7aa2f7|7aa2f7'
|
|
check_regex "$TARGET" "height 280" '"height".*280|280.*height|height.*280'
|
|
|
|
echo ""
|
|
echo "=== Checking Example 2: Bar Chart ==="
|
|
check_regex "$TARGET" "Example 2 heading" 'Bar Chart|Example.*2'
|
|
check_regex "$TARGET" "Price Comparison title" 'Price Comparison by Model|Price Comparison'
|
|
check_regex "$TARGET" "Chart.js new Chart" 'new Chart'
|
|
check_regex "$TARGET" "type bar" "type.*bar|bar.*type|type.*'bar'"
|
|
check_regex "$TARGET" "data.labels reference" 'data\.labels'
|
|
check_regex "$TARGET" "data.values reference" 'data\.values'
|
|
check_regex "$TARGET" "blue rgba color" 'rgba.*122.*162.*247|rgba\(122'
|
|
check_regex "$TARGET" "onClick with mcp.sendMessage" 'onClick|mcp\.sendMessage.*label|mcp\.sendMessage.*more about'
|
|
check_regex "$TARGET" "height 380 for chart" '"height".*380|380.*height|height.*380'
|
|
|
|
echo ""
|
|
echo "=== Checking Example 3: Location Map ==="
|
|
check_regex "$TARGET" "Example 3 heading" 'Location Map|Map|Example.*3'
|
|
check_regex "$TARGET" "Dealers Near Woodinville title" 'Dealers Near Woodinville|Woodinville'
|
|
check_regex "$TARGET" "L.map usage" 'L\.map'
|
|
check_regex "$TARGET" "CARTO dark tile layer" 'CARTO|cartocdn|carto'
|
|
check_regex "$TARGET" "markers from data.markers" 'data\.markers'
|
|
check_regex "$TARGET" "bindPopup" 'bindPopup'
|
|
check_regex "$TARGET" "marker click mcp.sendMessage" 'mcp\.sendMessage.*title|click.*mcp|marker.*mcp'
|
|
check_regex "$TARGET" "fitBounds for multiple markers" 'fitBounds'
|
|
|
|
echo ""
|
|
echo "=== Checking Example 4: React Dashboard ==="
|
|
check_regex "$TARGET" "Example 4 heading" 'React Dashboard|Dashboard|Example.*4'
|
|
check_regex "$TARGET" "Research Summary Dashboard title" 'Research Summary Dashboard|Research Summary'
|
|
check_regex "$TARGET" "StatCard component" 'StatCard'
|
|
check_regex "$TARGET" "App component" 'function App|const App|App ='
|
|
check_regex "$TARGET" "useState for sort" 'useState'
|
|
check_regex "$TARGET" "sort by price or miles" "sort|price.*miles|miles.*price"
|
|
check_regex "$TARGET" "Tabler btn classes" 'btn-primary|btn-secondary|btn tabler|tabler.*btn'
|
|
check_regex "$TARGET" "height 450" '"height".*450|450.*height|height.*450'
|
|
|
|
echo ""
|
|
echo "=== Checking Example 5: Decision Matrix ==="
|
|
check_regex "$TARGET" "Example 5 heading" 'Decision Matrix|Example.*5'
|
|
check_regex "$TARGET" "Car Decision Matrix title" 'Car Decision Matrix|Decision Matrix'
|
|
check_regex "$TARGET" "weight sliders (range input)" 'range.*slider|slider.*range|type.*range|range.*0.*10'
|
|
check_regex "$TARGET" "criteria (Price, MPG, Reliability)" 'Price|MPG|Reliab'
|
|
check_regex "$TARGET" "weighted scores calculation" 'weight.*score|score.*weight|weighted'
|
|
check_regex "$TARGET" "best highlighted green" 'best.*green|green.*best|highlight.*green|green.*highlight'
|
|
check_regex "$TARGET" "height 400" '"height".*400|400.*height|height.*400'
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Constraints section
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "=== Checking Constraints section ==="
|
|
check_regex "$TARGET" "Constraints heading" 'Constraint'
|
|
check_regex "$TARGET" "self-contained / no API fetches" 'self.contained|no.*fetch|no.*API fetch|no.*external fetch'
|
|
check_regex "$TARGET" "dark theme constraint" 'dark.*theme|theme.*dark'
|
|
check_regex "$TARGET" "responsive width constraint" 'responsive|percentage|max.width'
|
|
check_regex "$TARGET" "no external fetches" 'no.*external|external.*fetch'
|
|
check_regex "$TARGET" "click-to-explore" 'click.to.explore|click.*explore|explore.*click'
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Visuals vs A2UI decision table
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "=== Checking Visuals vs A2UI section ==="
|
|
check_regex "$TARGET" "Visuals vs A2UI heading" 'Visuals.*A2UI|A2UI.*Visuals|visual.*vs.*a2ui|vs.*A2UI'
|
|
check_regex "$TARGET" "toggle filters -> A2UI" 'filter|toggle'
|
|
check_regex "$TARGET" "simple table -> A2UI" 'simple.*table|table.*simple|<5.*row|5.*row'
|
|
check_regex "$TARGET" "interactive charts -> visual" 'interactive.*chart|chart.*interactive'
|
|
check_regex "$TARGET" "sortable tables -> visual" 'sortable'
|
|
check_regex "$TARGET" "maps -> visual" 'map'
|
|
check_regex "$TARGET" "dashboards -> visual" 'dashboard'
|
|
check_regex "$TARGET" "decision matrices -> visual" 'decision.*matrix|matrix'
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Summary
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "=============================="
|
|
echo "Results: $PASS passed, $FAIL failed"
|
|
echo "=============================="
|
|
|
|
[ $FAIL -eq 0 ] && exit 0 || exit 1
|