Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/Services/Product/tests/docker-compose.test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
version: '3.8'

services:
productdb:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: productdb
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 2s
timeout: 5s
retries: 10

product-service:
build:
context: ../../../
dockerfile: Services/Product/Product.API/Dockerfile
ports:
- "5004:5004"
depends_on:
productdb:
condition: service_healthy
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ConnectionStrings__DefaultConnection=Host=productdb;Database=productdb;Username=postgres;Password=postgres
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/5004' || exit 1"]
interval: 2s
timeout: 5s
retries: 15

api-gateway:
build:
context: ../../../
dockerfile: ApiGateway/Dockerfile
ports:
- "5000:5000"
depends_on:
product-service:
condition: service_healthy
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ReverseProxy__Clusters__product-cluster__Destinations__destination1__Address=http://product-service:5004/
140 changes: 140 additions & 0 deletions src/Services/Product/tests/smoke-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/bin/bash
set -e

GATEWAY_URL="${GATEWAY_URL:-http://localhost:5000}"
SERVICE_URL="${SERVICE_URL:-http://localhost:5004}"
JWT_SECRET="QuickApp_Microservices_SuperSecret_Key_For_Dev_Only_Min_32_Chars!"
PASS=0
FAIL=0

# Generate a JWT token
generate_jwt() {
local header='{"alg":"HS256","typ":"JWT"}'
local payload="{\"sub\":\"test-user\",\"iss\":\"quickapp-identity\",\"aud\":\"quickapp-api\",\"exp\":$(($(date +%s) + 3600))}"

local header_b64=$(echo -n "$header" | base64 -w0 | tr '+/' '-_' | tr -d '=')
local payload_b64=$(echo -n "$payload" | base64 -w0 | tr '+/' '-_' | tr -d '=')
local signature=$(echo -n "${header_b64}.${payload_b64}" | openssl dgst -sha256 -hmac "$JWT_SECRET" -binary | base64 -w0 | tr '+/' '-_' | tr -d '=')

echo "${header_b64}.${payload_b64}.${signature}"
}

assert_status() {
local description="$1"
local expected="$2"
local actual="$3"

if [ "$actual" = "$expected" ]; then
echo "PASS: $description (HTTP $actual)"
PASS=$((PASS + 1))
else
echo "FAIL: $description — expected $expected, got $actual"
FAIL=$((FAIL + 1))
fi
}

# Wait for services to be ready
wait_for_service() {
local url="$1"
local name="$2"
local retries=30
local i=0
echo "Waiting for $name at $url ..."
while [ $i -lt $retries ]; do
if curl -sf -o /dev/null "$url"; then
echo "$name is ready"
return 0
fi
i=$((i + 1))
sleep 1
done
echo "ERROR: $name not ready after ${retries}s"
return 1
}

wait_for_service "$SERVICE_URL/healthz" "product-service"
wait_for_service "$GATEWAY_URL/healthz" "api-gateway"

TOKEN=$(generate_jwt)
echo "Generated JWT token"
echo "Testing against gateway: $GATEWAY_URL"
echo "Testing against service: $SERVICE_URL"
echo "---"

# Test 1: Health check (direct to service — public)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$SERVICE_URL/healthz")
assert_status "GET /healthz (direct) → 200" "200" "$STATUS"
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.

# Test 2: GET /api/product without token → 401 (direct)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$SERVICE_URL/api/product")
assert_status "GET /api/product without token (direct) → 401" "401" "$STATUS"

# Test 3: GET /api/products without token → 401 (through gateway)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$GATEWAY_URL/api/products")
assert_status "GET /api/products without token (gateway) → 401" "401" "$STATUS"

# Test 4: Create a category with valid JWT → 201
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$GATEWAY_URL/api/products/categories" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Electronics","description":"Electronic devices","icon":"electronics-icon"}')
STATUS=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')
assert_status "POST /api/products/categories with JWT → 201" "201" "$STATUS"

# Extract category ID
CATEGORY_ID=$(echo "$BODY" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
echo "Created category ID: $CATEGORY_ID"

# Test 5: Create a product with valid JWT → 201
if [ -z "$CATEGORY_ID" ]; then
echo "FAIL: POST /api/products — skipped, no category ID from previous step"
FAIL=$((FAIL + 1))
PRODUCT_ID=""
else
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$GATEWAY_URL/api/products" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"name\":\"Test Product\",\"description\":\"A test product\",\"icon\":\"test-icon\",\"buyingPrice\":10.50,\"sellingPrice\":15.99,\"unitsInStock\":100,\"isActive\":true,\"isDiscontinued\":false,\"parentId\":null,\"productCategoryId\":$CATEGORY_ID}")
STATUS=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')
assert_status "POST /api/products with JWT → 201" "201" "$STATUS"

# Extract product ID
PRODUCT_ID=$(echo "$BODY" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
echo "Created product ID: $PRODUCT_ID"
fi

# Test 6: GET /api/products with valid JWT → 200 (list includes product)
RESPONSE=$(curl -s -w "\n%{http_code}" "$GATEWAY_URL/api/products" \
-H "Authorization: Bearer $TOKEN")
STATUS=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')
assert_status "GET /api/products with JWT → 200" "200" "$STATUS"

# Verify the product is in the list
if echo "$BODY" | grep -q "Test Product"; then
echo "PASS: Response contains 'Test Product'"
PASS=$((PASS + 1))
else
echo "FAIL: Response does not contain 'Test Product'"
FAIL=$((FAIL + 1))
fi

# Test 7: GET /api/products/{id} with valid JWT → 200
if [ -z "$PRODUCT_ID" ]; then
echo "FAIL: GET /api/products/{id} — skipped, no product ID from previous step"
FAIL=$((FAIL + 1))
else
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$GATEWAY_URL/api/products/$PRODUCT_ID" \
-H "Authorization: Bearer $TOKEN")
assert_status "GET /api/products/$PRODUCT_ID with JWT → 200" "200" "$STATUS"
fi

echo "---"
echo "Results: $PASS passed, $FAIL failed"

if [ $FAIL -gt 0 ]; then
exit 1
fi
echo "All smoke tests passed!"