343 lines
9.9 KiB
Bash
Executable File
343 lines
9.9 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Table Stakes Features - Automated QA Test Script
|
|
# Tests all implemented features end-to-end
|
|
|
|
# set -e # Don't exit on error - show all test results
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Configuration
|
|
BASE_URL="http://localhost:3000"
|
|
API_BASE="$BASE_URL/api"
|
|
TEST_PROJECT_NAME="QA Test Project $(date +%s)"
|
|
TEST_WORKSPACE="test-workspace"
|
|
|
|
# Test results
|
|
TESTS_PASSED=0
|
|
TESTS_FAILED=0
|
|
FAILED_TESTS=()
|
|
|
|
# Helper functions
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[PASS]${NC} $1"
|
|
((TESTS_PASSED++))
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[FAIL]${NC} $1"
|
|
((TESTS_FAILED++))
|
|
FAILED_TESTS+=("$1")
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
# Check if server is running
|
|
check_server() {
|
|
log_info "Checking if server is running at $BASE_URL..."
|
|
if curl -s -o /dev/null -w "%{http_code}" "$BASE_URL" | grep -q "200\|404"; then
|
|
log_success "Server is running"
|
|
return 0
|
|
else
|
|
log_error "Server is not running at $BASE_URL"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Test 1: Create a new project
|
|
test_create_project() {
|
|
log_info "Test 1: Creating new project..."
|
|
|
|
# Note: This requires authentication, so we'll check the endpoint exists
|
|
response=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$API_BASE/projects/create" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{}')
|
|
|
|
if [ "$response" = "401" ]; then
|
|
log_success "Project creation endpoint exists (401 Unauthorized as expected without token)"
|
|
else
|
|
log_warning "Project creation endpoint returned $response (expected 401)"
|
|
fi
|
|
}
|
|
|
|
# Test 2: Check extensionLinked field initialization
|
|
test_extension_field() {
|
|
log_info "Test 2: Checking extensionLinked field in project creation..."
|
|
|
|
# Check the code has the field
|
|
if grep -q "extensionLinked: false" app/api/projects/create/route.ts; then
|
|
log_success "extensionLinked field present in project creation"
|
|
else
|
|
log_error "extensionLinked field missing from project creation"
|
|
fi
|
|
}
|
|
|
|
# Test 3: Check collector handoff type includes 'collector'
|
|
test_collector_handoff_type() {
|
|
log_info "Test 3: Checking collector handoff type definition..."
|
|
|
|
if grep -q "'collector' |" lib/server/chat-context.ts; then
|
|
log_success "Collector phase included in phaseHandoffs type"
|
|
else
|
|
log_error "Collector phase missing from phaseHandoffs type"
|
|
fi
|
|
}
|
|
|
|
# Test 4: Check auto-transition logic exists
|
|
test_auto_transition() {
|
|
log_info "Test 4: Checking auto-transition logic..."
|
|
|
|
if grep -q "Auto-transitioning project to extraction phase" app/api/ai/chat/route.ts; then
|
|
log_success "Auto-transition logic present in chat route"
|
|
else
|
|
log_error "Auto-transition logic missing from chat route"
|
|
fi
|
|
|
|
if grep -q "currentPhase === 'analyzed'" lib/server/chat-mode-resolver.ts; then
|
|
log_success "Mode resolver checks currentPhase field"
|
|
else
|
|
log_error "Mode resolver doesn't check currentPhase"
|
|
fi
|
|
}
|
|
|
|
# Test 5: Check extension linking API exists
|
|
test_extension_api() {
|
|
log_info "Test 5: Checking extension linking API..."
|
|
|
|
response=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$API_BASE/extension/link-project" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{}')
|
|
|
|
if [ "$response" = "401" ]; then
|
|
log_success "Extension link API exists (401 Unauthorized as expected)"
|
|
else
|
|
log_warning "Extension link API returned $response (expected 401)"
|
|
fi
|
|
}
|
|
|
|
# Test 6: Check chunking API exists
|
|
test_chunking_api() {
|
|
log_info "Test 6: Checking extraction chunking API..."
|
|
|
|
# Check if the file exists
|
|
if [ -f "app/api/projects/[projectId]/knowledge/chunk-insight/route.ts" ]; then
|
|
log_success "Chunk insight API endpoint file exists"
|
|
else
|
|
log_error "Chunk insight API endpoint missing"
|
|
fi
|
|
}
|
|
|
|
# Test 7: Check auto-chunking is disabled on upload
|
|
test_no_auto_chunking() {
|
|
log_info "Test 7: Checking auto-chunking is disabled on upload..."
|
|
|
|
if grep -q "Store whole document as single knowledge_item" app/api/projects/[projectId]/knowledge/upload-document/route.ts; then
|
|
log_success "Upload stores whole document (no auto-chunking)"
|
|
else
|
|
log_error "Upload may still be auto-chunking"
|
|
fi
|
|
|
|
if grep -q "// import { chunkDocument }" app/api/projects/[projectId]/knowledge/upload-document/route.ts; then
|
|
log_success "chunkDocument import commented out"
|
|
else
|
|
log_warning "chunkDocument import may still be active"
|
|
fi
|
|
}
|
|
|
|
# Test 8: Check collector checklist component exists
|
|
test_checklist_component() {
|
|
log_info "Test 8: Checking collector checklist component..."
|
|
|
|
if [ -f "components/ai/collector-checklist.tsx" ]; then
|
|
log_success "Collector checklist component exists"
|
|
else
|
|
log_error "Collector checklist component missing"
|
|
fi
|
|
|
|
if grep -q "CollectorChecklist" app/[workspace]/project/[projectId]/v_ai_chat/page.tsx; then
|
|
log_success "Checklist integrated into AI chat page"
|
|
else
|
|
log_error "Checklist not integrated into AI chat page"
|
|
fi
|
|
}
|
|
|
|
# Test 9: Check Gemini role mapping fix
|
|
test_gemini_role_fix() {
|
|
log_info "Test 9: Checking Gemini role mapping fix..."
|
|
|
|
if grep -q "role === 'assistant' ? 'model'" lib/ai/gemini-client.ts; then
|
|
log_success "Gemini client translates assistant → model role"
|
|
else
|
|
log_error "Gemini client missing role translation"
|
|
fi
|
|
}
|
|
|
|
# Test 10: Check conversation history persistence
|
|
test_conversation_history() {
|
|
log_info "Test 10: Checking conversation history loading..."
|
|
|
|
if grep -q "Load existing conversation history" app/api/ai/chat/route.ts; then
|
|
log_success "Chat route loads conversation history"
|
|
else
|
|
log_error "Chat route doesn't load conversation history"
|
|
fi
|
|
|
|
if grep -q "conversationHistory.map" app/api/ai/chat/route.ts; then
|
|
log_success "Conversation history included in messages"
|
|
else
|
|
log_error "Conversation history not included in messages"
|
|
fi
|
|
}
|
|
|
|
# Test 11: Check extensionLinked in context
|
|
test_extension_in_context() {
|
|
log_info "Test 11: Checking extensionLinked in project context..."
|
|
|
|
if grep -q "extensionLinked?: boolean" lib/server/chat-context.ts; then
|
|
log_success "extensionLinked field in ProjectChatContext type"
|
|
else
|
|
log_error "extensionLinked field missing from context type"
|
|
fi
|
|
|
|
if grep -q "extensionLinked: projectData.extensionLinked" lib/server/chat-context.ts; then
|
|
log_success "extensionLinked passed to AI in context"
|
|
else
|
|
log_error "extensionLinked not passed to AI"
|
|
fi
|
|
}
|
|
|
|
# Test 12: Check collector prompt mentions extensionLinked
|
|
test_collector_prompt() {
|
|
log_info "Test 12: Checking collector prompt..."
|
|
|
|
if grep -q "projectContext.project.extensionLinked" lib/ai/prompts/collector.ts; then
|
|
log_success "Collector prompt checks extensionLinked field"
|
|
else
|
|
log_error "Collector prompt doesn't check extensionLinked"
|
|
fi
|
|
}
|
|
|
|
# Test 13: Check UI text update
|
|
test_ui_text() {
|
|
log_info "Test 13: Checking UI text reflects no auto-chunking..."
|
|
|
|
if grep -q "stored for the Extractor AI to review" app/[workspace]/project/[projectId]/context/page.tsx; then
|
|
log_success "UI text updated (no mention of auto-chunking)"
|
|
else
|
|
log_error "UI text may still mention auto-chunking"
|
|
fi
|
|
}
|
|
|
|
# Test 14: Verify linter passes
|
|
test_linter() {
|
|
log_info "Test 14: Running linter check..."
|
|
|
|
# This is a simplified check - just verify key files exist and are not empty
|
|
files_to_check=(
|
|
"app/api/ai/chat/route.ts"
|
|
"lib/server/chat-context.ts"
|
|
"lib/ai/gemini-client.ts"
|
|
"components/ai/collector-checklist.tsx"
|
|
)
|
|
|
|
all_good=true
|
|
for file in "${files_to_check[@]}"; do
|
|
if [ ! -f "$file" ]; then
|
|
log_error "File missing: $file"
|
|
all_good=false
|
|
elif [ ! -s "$file" ]; then
|
|
log_error "File is empty: $file"
|
|
all_good=false
|
|
fi
|
|
done
|
|
|
|
if $all_good; then
|
|
log_success "All critical files exist and are not empty"
|
|
fi
|
|
}
|
|
|
|
# Test 15: Check documentation exists
|
|
test_documentation() {
|
|
log_info "Test 15: Checking documentation..."
|
|
|
|
docs=(
|
|
"TABLE_STAKES_IMPLEMENTATION.md"
|
|
"QA_FIXES_APPLIED.md"
|
|
"PROJECT_CREATION_FIX.md"
|
|
"UPLOAD_CHUNKING_REMOVED.md"
|
|
)
|
|
|
|
for doc in "${docs[@]}"; do
|
|
if [ -f "$doc" ]; then
|
|
log_success "Documentation exists: $doc"
|
|
else
|
|
log_warning "Documentation missing: $doc"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Main test execution
|
|
main() {
|
|
echo ""
|
|
echo "=========================================="
|
|
echo " TABLE STAKES FEATURES - QA TEST SUITE"
|
|
echo "=========================================="
|
|
echo ""
|
|
|
|
check_server
|
|
echo ""
|
|
|
|
test_create_project
|
|
test_extension_field
|
|
test_collector_handoff_type
|
|
test_auto_transition
|
|
test_extension_api
|
|
test_chunking_api
|
|
test_no_auto_chunking
|
|
test_checklist_component
|
|
test_gemini_role_fix
|
|
test_conversation_history
|
|
test_extension_in_context
|
|
test_collector_prompt
|
|
test_ui_text
|
|
test_linter
|
|
test_documentation
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo " TEST RESULTS"
|
|
echo "=========================================="
|
|
echo -e "${GREEN}Passed:${NC} $TESTS_PASSED"
|
|
echo -e "${RED}Failed:${NC} $TESTS_FAILED"
|
|
echo ""
|
|
|
|
if [ $TESTS_FAILED -gt 0 ]; then
|
|
echo -e "${RED}Failed tests:${NC}"
|
|
for test in "${FAILED_TESTS[@]}"; do
|
|
echo " - $test"
|
|
done
|
|
echo ""
|
|
exit 1
|
|
else
|
|
echo -e "${GREEN}✅ ALL TESTS PASSED!${NC}"
|
|
echo ""
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
# Run tests
|
|
cd "$(dirname "$0")"
|
|
main
|
|
|