chore: consolidate docker-compose and add integration tests
- Merge infrastructure/docker-compose.yml + docker-compose.app.yml into root docker-compose.yml with profiles (infra/app). - Add healthchecks for mysql/redis/rabbitmq/mci-server/channel-service and depends_on conditions. - Rewrite scripts/local-up.sh to use profiles and wait for healthy states. - Add curl to mci-server and channel-service Docker images for healthchecks. - Add npm test script to admin-web (type-check + build smoke test). - Add scripts/test-external-api.sh covering 11 API endpoints. - Verify Java (7/7), Python (6/6), npm build, external API (11/11), and UI flows.
This commit is contained in:
@@ -6,7 +6,8 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc -b && vite build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"test": "vue-tsc -b && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.18.1",
|
||||
|
||||
@@ -14,6 +14,8 @@ RUN mvn -N install && \
|
||||
|
||||
FROM eclipse-temurin:21-jre-alpine
|
||||
|
||||
RUN apk add --no-cache curl
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/mci-server/target/*.jar app.jar
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
mci-server:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: mci-server/Dockerfile
|
||||
container_name: mci-server
|
||||
ports:
|
||||
- "8080:8080"
|
||||
environment:
|
||||
- SPRING_PROFILES_ACTIVE=dev
|
||||
- SPRING_DATASOURCE_URL=jdbc:mysql://mci-mysql:3306/sino_mci?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
|
||||
- SPRING_DATASOURCE_USERNAME=root
|
||||
- SPRING_DATASOURCE_PASSWORD=root
|
||||
- SPRING_DATA_REDIS_HOST=mci-redis
|
||||
- SPRING_RABBITMQ_HOST=mci-rabbitmq
|
||||
networks:
|
||||
- mci-network
|
||||
|
||||
admin-web:
|
||||
build:
|
||||
context: ./admin-web
|
||||
dockerfile: Dockerfile
|
||||
container_name: mci-admin-web
|
||||
ports:
|
||||
- "80:80"
|
||||
networks:
|
||||
- mci-network
|
||||
|
||||
channel-service:
|
||||
build:
|
||||
context: ./channel-service
|
||||
dockerfile: Dockerfile
|
||||
container_name: mci-channel-service
|
||||
ports:
|
||||
- "8000:8000"
|
||||
environment:
|
||||
- MCI_SERVER_URL=http://mci-server:8080/msg-platform
|
||||
networks:
|
||||
- mci-network
|
||||
|
||||
networks:
|
||||
mci-network:
|
||||
external: true
|
||||
144
docker-compose.yml
Normal file
144
docker-compose.yml
Normal file
@@ -0,0 +1,144 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0.36
|
||||
container_name: mci-mysql
|
||||
profiles: ["infra"]
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: sino_mci
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- mci-mysql-data:/var/lib/mysql
|
||||
networks:
|
||||
- mci-network
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
start_period: 30s
|
||||
|
||||
redis:
|
||||
image: redis:7.2
|
||||
container_name: mci-redis
|
||||
profiles: ["infra"]
|
||||
ports:
|
||||
- "6379:6379"
|
||||
networks:
|
||||
- mci-network
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 10s
|
||||
|
||||
rabbitmq:
|
||||
image: rabbitmq:3.13-management
|
||||
container_name: mci-rabbitmq
|
||||
profiles: ["infra"]
|
||||
environment:
|
||||
RABBITMQ_DEFAULT_USER: guest
|
||||
RABBITMQ_DEFAULT_PASS: guest
|
||||
ports:
|
||||
- "5672:5672"
|
||||
- "15672:15672"
|
||||
networks:
|
||||
- mci-network
|
||||
healthcheck:
|
||||
test: ["CMD", "rabbitmq-diagnostics", "ping"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 15
|
||||
start_period: 30s
|
||||
|
||||
seaweedfs:
|
||||
image: chrislusf/seaweedfs:3.62
|
||||
container_name: mci-seaweedfs
|
||||
profiles: ["infra"]
|
||||
ports:
|
||||
- "9333:9333"
|
||||
- "8888:8888"
|
||||
command: server -dir=/data
|
||||
volumes:
|
||||
- mci-seaweedfs-data:/data
|
||||
networks:
|
||||
- mci-network
|
||||
|
||||
mci-server:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: mci-server/Dockerfile
|
||||
container_name: mci-server
|
||||
profiles: ["app"]
|
||||
ports:
|
||||
- "8080:8080"
|
||||
environment:
|
||||
- SPRING_PROFILES_ACTIVE=dev
|
||||
- SPRING_DATASOURCE_URL=jdbc:mysql://mci-mysql:3306/sino_mci?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
|
||||
- SPRING_DATASOURCE_USERNAME=root
|
||||
- SPRING_DATASOURCE_PASSWORD=root
|
||||
- SPRING_DATA_REDIS_HOST=mci-redis
|
||||
- SPRING_RABBITMQ_HOST=mci-rabbitmq
|
||||
networks:
|
||||
- mci-network
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
rabbitmq:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://localhost:8080/msg-platform/actuator/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 15
|
||||
start_period: 90s
|
||||
|
||||
admin-web:
|
||||
build:
|
||||
context: ./admin-web
|
||||
dockerfile: Dockerfile
|
||||
container_name: mci-admin-web
|
||||
profiles: ["app"]
|
||||
ports:
|
||||
- "80:80"
|
||||
networks:
|
||||
- mci-network
|
||||
depends_on:
|
||||
mci-server:
|
||||
condition: service_healthy
|
||||
|
||||
channel-service:
|
||||
build:
|
||||
context: ./channel-service
|
||||
dockerfile: Dockerfile
|
||||
container_name: mci-channel-service
|
||||
profiles: ["app"]
|
||||
ports:
|
||||
- "8000:8000"
|
||||
environment:
|
||||
- MCI_SERVER_URL=http://mci-server:8080/msg-platform
|
||||
networks:
|
||||
- mci-network
|
||||
depends_on:
|
||||
mci-server:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://localhost:8000/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 30s
|
||||
|
||||
volumes:
|
||||
mci-mysql-data:
|
||||
mci-seaweedfs-data:
|
||||
|
||||
networks:
|
||||
mci-network:
|
||||
driver: bridge
|
||||
BIN
docs/superpowers/specs/ui-send-record-success.png
Normal file
BIN
docs/superpowers/specs/ui-send-record-success.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 224 KiB |
@@ -1,55 +0,0 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0.36
|
||||
container_name: mci-mysql
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: sino_mci
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- mci-mysql-data:/var/lib/mysql
|
||||
networks:
|
||||
- mci-network
|
||||
|
||||
redis:
|
||||
image: redis:7.2
|
||||
container_name: mci-redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
networks:
|
||||
- mci-network
|
||||
|
||||
rabbitmq:
|
||||
image: rabbitmq:3.13-management
|
||||
container_name: mci-rabbitmq
|
||||
environment:
|
||||
RABBITMQ_DEFAULT_USER: guest
|
||||
RABBITMQ_DEFAULT_PASS: guest
|
||||
ports:
|
||||
- "5672:5672"
|
||||
- "15672:15672"
|
||||
networks:
|
||||
- mci-network
|
||||
|
||||
seaweedfs:
|
||||
image: chrislusf/seaweedfs:3.62
|
||||
container_name: mci-seaweedfs
|
||||
ports:
|
||||
- "9333:9333"
|
||||
- "8888:8888"
|
||||
command: server -dir=/data
|
||||
volumes:
|
||||
- mci-seaweedfs-data:/data
|
||||
networks:
|
||||
- mci-network
|
||||
|
||||
volumes:
|
||||
mci-mysql-data:
|
||||
mci-seaweedfs-data:
|
||||
|
||||
networks:
|
||||
mci-network:
|
||||
external: true
|
||||
@@ -4,47 +4,42 @@ set -e
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR/.."
|
||||
|
||||
echo "Creating shared network..."
|
||||
docker network create mci-network 2>/dev/null || true
|
||||
wait_for_healthy() {
|
||||
local service=$1
|
||||
local max_retries=${2:-60}
|
||||
local retry_count=0
|
||||
local container_name
|
||||
|
||||
echo "Starting local infrastructure..."
|
||||
docker compose -f infrastructure/docker-compose.yml up -d
|
||||
echo "Waiting for $service to become healthy..."
|
||||
while [ "$retry_count" -lt "$max_retries" ]; do
|
||||
container_name=$(docker compose --profile infra --profile app ps -q "$service" 2>/dev/null | head -n1)
|
||||
|
||||
echo "Waiting for MySQL..."
|
||||
MAX_RETRIES=60
|
||||
RETRY_COUNT=0
|
||||
until docker exec mci-mysql mysql -uroot -proot -e "SELECT 1" > /dev/null 2>&1; do
|
||||
RETRY_COUNT=$((RETRY_COUNT + 1))
|
||||
if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then
|
||||
echo "MySQL did not become ready within ${MAX_RETRIES} seconds."
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
if [ -n "$container_name" ]; then
|
||||
local status
|
||||
status=$(docker inspect --format='{{.State.Health.Status}}' "$container_name" 2>/dev/null || true)
|
||||
if [ "$status" = "healthy" ]; then
|
||||
echo "$service is healthy."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Waiting for Redis..."
|
||||
RETRY_COUNT=0
|
||||
until docker exec mci-redis redis-cli ping | grep -q "PONG"; do
|
||||
RETRY_COUNT=$((RETRY_COUNT + 1))
|
||||
if [ "$RETRY_COUNT" -ge 30 ]; then
|
||||
echo "Redis did not become ready within 30 seconds."
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
retry_count=$((retry_count + 1))
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo "Waiting for RabbitMQ..."
|
||||
RETRY_COUNT=0
|
||||
until curl -s -o /dev/null -w "%{http_code}" http://guest:guest@localhost:15672/api/overview | grep -q "200"; do
|
||||
RETRY_COUNT=$((RETRY_COUNT + 1))
|
||||
if [ "$RETRY_COUNT" -ge 30 ]; then
|
||||
echo "RabbitMQ did not become ready within 30 seconds."
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
echo "$service did not become healthy within $((max_retries * 2)) seconds."
|
||||
docker compose --profile infra --profile app logs --tail=50 "$service"
|
||||
return 1
|
||||
}
|
||||
|
||||
echo "Local infrastructure is ready."
|
||||
echo "Starting infrastructure services..."
|
||||
docker compose --profile infra up -d
|
||||
|
||||
wait_for_healthy mysql 60
|
||||
wait_for_healthy redis 30
|
||||
wait_for_healthy rabbitmq 60
|
||||
|
||||
echo "Infrastructure is ready."
|
||||
echo "MySQL: jdbc:mysql://localhost:3306/sino_mci"
|
||||
echo "Redis: localhost:6379"
|
||||
echo "RabbitMQ: localhost:5672 / http://localhost:15672"
|
||||
@@ -52,7 +47,13 @@ echo "SeaweedFS: http://localhost:9333"
|
||||
|
||||
if [ "$1" == "--with-apps" ]; then
|
||||
echo "Starting application services..."
|
||||
docker compose -f docker-compose.app.yml up -d --build
|
||||
# Include infra profile so that depends_on conditions can resolve.
|
||||
docker compose --profile infra --profile app up -d --build
|
||||
|
||||
wait_for_healthy mci-server 90
|
||||
wait_for_healthy channel-service 60
|
||||
|
||||
echo "Application services are ready."
|
||||
echo "Admin Web: http://localhost"
|
||||
echo "Backend API: http://localhost:8080/msg-platform"
|
||||
echo "Channel Service: http://localhost:8000"
|
||||
|
||||
159
scripts/test-external-api.sh
Executable file
159
scripts/test-external-api.sh
Executable file
@@ -0,0 +1,159 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR/.."
|
||||
|
||||
BASE_URL="${BASE_URL:-http://localhost/msg-platform}"
|
||||
CHANNEL_URL="${CHANNEL_URL:-http://localhost:8000}"
|
||||
|
||||
command -v curl >/dev/null 2>&1 || { echo "curl is required but not installed."; exit 1; }
|
||||
command -v jq >/dev/null 2>&1 || { echo "jq is required but not installed."; exit 1; }
|
||||
|
||||
PASS_COUNT=0
|
||||
FAIL_COUNT=0
|
||||
|
||||
TENANT_CODE="ext-test-$(date +%s)"
|
||||
|
||||
make_request() {
|
||||
local method=$1
|
||||
local url=$2
|
||||
local payload=$3
|
||||
shift 3
|
||||
local headers=("$@")
|
||||
|
||||
if [ "$method" = "GET" ]; then
|
||||
curl -s -S -X GET "${headers[@]}" "$url"
|
||||
elif [ -n "$payload" ]; then
|
||||
curl -s -S -X "$method" "${headers[@]}" -H "Content-Type: application/json" -d "$payload" "$url"
|
||||
else
|
||||
curl -s -S -X "$method" "${headers[@]}" -H "Content-Type: application/json" "$url"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_code_zero() {
|
||||
local name=$1
|
||||
local response=$2
|
||||
local code
|
||||
code=$(echo "$response" | jq -r '.code // .errcode // empty')
|
||||
|
||||
if [ "$code" = "0" ]; then
|
||||
echo "[PASS] $name"
|
||||
PASS_COUNT=$((PASS_COUNT + 1))
|
||||
return 0
|
||||
else
|
||||
echo "[FAIL] $name (code=$code)"
|
||||
echo " response: $response"
|
||||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 1. Create tenant
|
||||
echo "==> 1. Create tenant"
|
||||
TENANT_RESPONSE=$(make_request POST "$BASE_URL/api/v1/account/tenant" \
|
||||
'{"tenantCode":"'"$TENANT_CODE"'","tenantName":"External API Test"}')
|
||||
assert_code_zero "Create tenant" "$TENANT_RESPONSE"
|
||||
|
||||
# 2. Create channel subject
|
||||
echo "==> 2. Create channel subject"
|
||||
SUBJECT_RESPONSE=$(make_request POST "$BASE_URL/api/v1/channel-subject" \
|
||||
'{"channelType":"wecom","subjectCode":"sino","subjectName":"Sino Test"}' \
|
||||
-H "X-Tenant-Code: $TENANT_CODE")
|
||||
assert_code_zero "Create channel subject" "$SUBJECT_RESPONSE"
|
||||
|
||||
# 3. Create channel account
|
||||
echo "==> 3. Create channel account"
|
||||
ACCOUNT_RESPONSE=$(make_request POST "$BASE_URL/api/v1/channel-account" \
|
||||
'{"accountType":1,"channelType":"wecom","accountId":"ZhangSan","accountName":"张三"}' \
|
||||
-H "X-Tenant-Code: $TENANT_CODE")
|
||||
assert_code_zero "Create channel account" "$ACCOUNT_RESPONSE"
|
||||
ACCOUNT_ID=$(echo "$ACCOUNT_RESPONSE" | jq -r '.data.id')
|
||||
|
||||
# 4. Create conversation
|
||||
echo "==> 4. Create conversation"
|
||||
CONVERSATION_RESPONSE=$(make_request POST "$BASE_URL/api/v1/conversation" \
|
||||
'{"conversationType":2,"channelType":"wecom","channelConversationId":"room-test-'"$(date +%s)"'","conversationName":"Test Group"}' \
|
||||
-H "X-Tenant-Code: $TENANT_CODE")
|
||||
assert_code_zero "Create conversation" "$CONVERSATION_RESPONSE"
|
||||
CONVERSATION_ID=$(echo "$CONVERSATION_RESPONSE" | jq -r '.data.id')
|
||||
|
||||
# 5. Bind account to conversation
|
||||
echo "==> 5. Bind account to conversation"
|
||||
BIND_RESPONSE=$(make_request POST "$BASE_URL/api/v1/conversation/$CONVERSATION_ID/bind-account" \
|
||||
"{\"accountId\":$ACCOUNT_ID,\"bindingType\":1,\"sortOrder\":1}" \
|
||||
-H "X-Tenant-Code: $TENANT_CODE")
|
||||
assert_code_zero "Bind account to conversation" "$BIND_RESPONSE"
|
||||
|
||||
# 6. Test send
|
||||
echo "==> 6. Test send"
|
||||
SEND_RESPONSE=$(make_request POST "$BASE_URL/api/v1/send/test" \
|
||||
"{\"targetType\":\"conversation\",\"targetValue\":{\"conversation_id\":$CONVERSATION_ID},\"contentType\":\"text\",\"content\":{\"text\":\"hello from external api test\"},\"channelStrategy\":{\"channel_type\":\"wecom\",\"strategy\":\"primary\"}}" \
|
||||
-H "X-Tenant-Code: $TENANT_CODE")
|
||||
assert_code_zero "Test send" "$SEND_RESPONSE"
|
||||
TASK_ID=$(echo "$SEND_RESPONSE" | jq -r '.data.taskId')
|
||||
|
||||
# 7. Query send records
|
||||
echo "==> 7. Query send records"
|
||||
RECORDS_RESPONSE=$(make_request GET "$BASE_URL/api/v1/send/$TASK_ID/records" "" \
|
||||
-H "X-Tenant-Code: $TENANT_CODE")
|
||||
assert_code_zero "Query send records" "$RECORDS_RESPONSE"
|
||||
|
||||
# 8. Receive inbound message
|
||||
echo "==> 8. Receive inbound message"
|
||||
EVENT_ID="evt-$(date +%s)-$RANDOM"
|
||||
INBOUND_RESPONSE=$(make_request POST "$BASE_URL/api/v1/inbound/receive" \
|
||||
"{\"eventId\":\"$EVENT_ID\",\"channelType\":\"wecom\",\"channelSubjectId\":1,\"eventType\":\"message\",\"messageSource\":\"realtime\",\"conversationId\":$CONVERSATION_ID,\"accountId\":$ACCOUNT_ID,\"content\":{\"text\":\"hello inbound\"},\"rawPayload\":{},\"businessContext\":{}}" \
|
||||
-H "X-Tenant-Code: $TENANT_CODE")
|
||||
assert_code_zero "Receive inbound message" "$INBOUND_RESPONSE"
|
||||
|
||||
# 9. Channel-service health
|
||||
echo "==> 9. Channel-service health"
|
||||
HEALTH_RESPONSE=$(curl -s -S "$CHANNEL_URL/health")
|
||||
if echo "$HEALTH_RESPONSE" | jq -e '.status == "ok"' >/dev/null 2>&1; then
|
||||
echo "[PASS] Channel-service health"
|
||||
PASS_COUNT=$((PASS_COUNT + 1))
|
||||
else
|
||||
echo "[FAIL] Channel-service health"
|
||||
echo " response: $HEALTH_RESPONSE"
|
||||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||||
fi
|
||||
|
||||
# 10. WeChat personal login start
|
||||
echo "==> 10. WeChat personal login start"
|
||||
LOGIN_RESPONSE=$(make_request POST "$CHANNEL_URL/v1/wechat-personal/login/start" \
|
||||
'{"account_id":"bot-test-'"$(date +%s)"'","account_name":"Test Bot"}')
|
||||
if echo "$LOGIN_RESPONSE" | jq -e '.login_id' >/dev/null 2>&1; then
|
||||
echo "[PASS] WeChat personal login start"
|
||||
PASS_COUNT=$((PASS_COUNT + 1))
|
||||
else
|
||||
echo "[FAIL] WeChat personal login start"
|
||||
echo " response: $LOGIN_RESPONSE"
|
||||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||||
fi
|
||||
|
||||
# 11. WeChat personal send text (after confirming a login)
|
||||
echo "==> 11. WeChat personal send text"
|
||||
BOT_ID="bot-send-$(date +%s)"
|
||||
make_request POST "$CHANNEL_URL/v1/wechat-personal/login/start" \
|
||||
'{"account_id":"'"$BOT_ID"'"}' >/dev/null
|
||||
make_request POST "$CHANNEL_URL/v1/wechat-personal/login/$BOT_ID/confirm" "{}" >/dev/null
|
||||
SEND_TEXT_RESPONSE=$(make_request POST "$CHANNEL_URL/v1/wechat-personal/send/text" \
|
||||
'{"account_id":"'"$BOT_ID"'","conversation_id":"room-test","text":"hello"}')
|
||||
if echo "$SEND_TEXT_RESPONSE" | jq -e '.success == true' >/dev/null 2>&1; then
|
||||
echo "[PASS] WeChat personal send text"
|
||||
PASS_COUNT=$((PASS_COUNT + 1))
|
||||
else
|
||||
echo "[FAIL] WeChat personal send text"
|
||||
echo " response: $SEND_TEXT_RESPONSE"
|
||||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "========================="
|
||||
echo "Total: $((PASS_COUNT + FAIL_COUNT)), Passed: $PASS_COUNT, Failed: $FAIL_COUNT"
|
||||
echo "========================="
|
||||
|
||||
if [ "$FAIL_COUNT" -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user