#!/usr/bin/env bash # tests.sh — mem0server endpoint tests # Usage: bash tests.sh [BASE_URL] # Default base: http://192.168.0.200:8420 BASE="${1:-http://192.168.0.200:8420}" PASS=0 FAIL=0 LAST_JSON="" LAST_STATUS="" MEMORY_MARKER="mem0-test-case" # Colours GREEN='\033[0;32m' RED='\033[0;31m' CYAN='\033[0;36m' BOLD='\033[1m' RESET='\033[0m' sep() { echo -e "\n${CYAN}${BOLD}━━━ $* ━━━${RESET}"; } ok() { echo -e "${GREEN}✓ $*${RESET}"; ((PASS++)); } fail() { echo -e "${RED}✗ $*${RESET}"; ((FAIL++)); } run() { local label="$1"; shift local expected="200" if [[ "$1" =~ ^[0-9]{3}$ ]]; then expected="$1" shift fi echo -e "\n${BOLD}▶ $label${RESET}" local body body=$(curl -s -w "\n__STATUS__%{http_code}" "$@") local status status=$(echo "$body" | tail -1 | sed 's/__STATUS__//') local json json=$(echo "$body" | sed '$d') echo "$json" | jq . 2>/dev/null || echo "$json" LAST_STATUS="$status" LAST_JSON="$json" if [[ "$status" == "$expected" ]]; then ok "HTTP $status" else fail "HTTP $status (expected $expected)" fi } assert_json() { local label="$1" expr="$2" if echo "$LAST_JSON" | jq -e "$expr" >/dev/null 2>&1; then ok "$label" else fail "$label (jq: $expr)" fi } assert_contains() { local label="$1" substring="$2" if echo "$LAST_JSON" | grep -qF "$substring"; then ok "$label" else fail "$label (missing '$substring')" fi } sep "HEALTH" run "GET /health" "$BASE/health" assert_json "health -> collections object" '.collections | type == "object"' assert_json "health -> prompts present" '.prompts | type == "object"' sep "DASHBOARD" run "GET /dashboard" "$BASE/dashboard" assert_contains "dashboard contains HTML" " 0' run "DELETE /knowledge/by-source — midi_spec.pdf" \ -X DELETE "$BASE/knowledge/by-source" \ -H "Content-Type: application/json" \ -d '{"source_file": "midi_spec.pdf", "user_id": "knowledge_base"}' assert_json "knowledge by-source removed MIDI entries" '.deleted | tonumber > 0' sep "/search (merged)" run "POST /search — Python programming" \ -X POST "$BASE/search" \ -H "Content-Type: application/json" \ -d '{"query": "Python programming", "user_id": "testuser", "limit": 8}' assert_json "merged search results array" '.results | type == "array"' assert_json "merged search items have _source" 'if (.results | length) == 0 then true else (.results[] | has("_source")) end' run "POST /search — Gesell economic theory" \ -X POST "$BASE/search" \ -H "Content-Type: application/json" \ -d '{"query": "Gesell economic theory", "user_id": "knowledge_base", "limit": 5}' assert_json "merged search results array (Gesell)" '.results | type == "array"' assert_json "merged Gesell results tag _source" 'if (.results | length) == 0 then true else (.results[] | has("_source")) end' sep "ERROR HANDLING" run "POST /memories — missing text" 400 \ -X POST "$BASE/memories" \ -H "Content-Type: application/json" \ -d '{"user_id": "testuser"}' run "POST /memories — infer:false ignored" \ -X POST "$BASE/memories" \ -H "Content-Type: application/json" \ -d '{"text": "This should still go through LLM extraction", "user_id": "testuser", "infer": false}' run "POST /search — empty query" \ -X POST "$BASE/search" \ -H "Content-Type: application/json" \ -d '{"query": "", "user_id": "testuser"}' assert_json "empty search returns results array" '.results | type == "array"' assert_json "empty search returns zero results" '.results | length == 0' sep "RESULTS" echo -e "\n${BOLD}Passed: ${GREEN}$PASS${RESET} ${BOLD}Failed: ${RED}$FAIL${RESET}\n"