Add podman-compose/docker-compose integration tests
This commit is contained in:
58
Makefile
Normal file
58
Makefile
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
.PHONY: build test test-unit test-integration test-compose run clean docker-build docker-push help
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
BINARY_NAME=dyn-server
|
||||||
|
DOCKER_IMAGE=git.dws.rip/DWS/dyn
|
||||||
|
VERSION=$(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
|
||||||
|
|
||||||
|
help: ## Show this help message
|
||||||
|
@echo "Available targets:"
|
||||||
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
||||||
|
build: ## Build the binary
|
||||||
|
go build -o $(BINARY_NAME) cmd/server/main.go
|
||||||
|
|
||||||
|
test: ## Run all tests
|
||||||
|
go test ./... -v
|
||||||
|
|
||||||
|
test-unit: ## Run unit tests only
|
||||||
|
go test ./internal/... -v
|
||||||
|
|
||||||
|
test-integration: ## Run integration tests (with mock server)
|
||||||
|
go test ./tests/integration -v -run 'TestIntegration_[^C]'
|
||||||
|
|
||||||
|
test-compose: ## Run containerized integration tests with podman/docker-compose
|
||||||
|
@echo "Running compose integration tests..."
|
||||||
|
bash tests/integration/compose_test.sh
|
||||||
|
|
||||||
|
test-compose-go: ## Run Go-based compose integration tests
|
||||||
|
RUN_COMPOSE_TESTS=true go test ./tests/integration -v -run TestComposeIntegration -timeout 120s
|
||||||
|
|
||||||
|
run: build ## Build and run the server
|
||||||
|
./$(BINARY_NAME)
|
||||||
|
|
||||||
|
dev: ## Run in development mode
|
||||||
|
go run cmd/server/main.go
|
||||||
|
|
||||||
|
docker-build: ## Build Docker image
|
||||||
|
docker build -t $(DOCKER_IMAGE):$(VERSION) -t $(DOCKER_IMAGE):latest .
|
||||||
|
|
||||||
|
docker-push: docker-build ## Push Docker image
|
||||||
|
docker push $(DOCKER_IMAGE):$(VERSION)
|
||||||
|
docker push $(DOCKER_IMAGE):latest
|
||||||
|
|
||||||
|
clean: ## Clean build artifacts
|
||||||
|
rm -f $(BINARY_NAME)
|
||||||
|
go clean
|
||||||
|
|
||||||
|
deps: ## Download dependencies
|
||||||
|
go mod download
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
lint: ## Run linter (requires golangci-lint)
|
||||||
|
golangci-lint run ./...
|
||||||
|
|
||||||
|
fmt: ## Format Go code
|
||||||
|
go fmt ./...
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
21
README.md
21
README.md
@@ -288,6 +288,27 @@ go test ./tests/integration -v -run TestIntegration_FullWorkflow
|
|||||||
|
|
||||||
# Run with timeout
|
# Run with timeout
|
||||||
go test ./tests/integration -v -timeout 30s
|
go test ./tests/integration -v -timeout 30s
|
||||||
|
|
||||||
|
# Run containerized integration tests with podman/docker-compose
|
||||||
|
make test-compose
|
||||||
|
|
||||||
|
# Or using the shell script directly
|
||||||
|
bash tests/integration/compose_test.sh
|
||||||
|
|
||||||
|
# Run Go-based compose tests (requires RUN_COMPOSE_TESTS=true)
|
||||||
|
RUN_COMPOSE_TESTS=true go test ./tests/integration -v -run TestComposeIntegration
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using Make
|
||||||
|
```bash
|
||||||
|
make help # Show all available targets
|
||||||
|
make build # Build the binary
|
||||||
|
make test # Run all tests
|
||||||
|
make test-unit # Run unit tests only
|
||||||
|
make test-integration # Run integration tests
|
||||||
|
make test-compose # Run containerized tests
|
||||||
|
make run # Build and run the server
|
||||||
|
make dev # Run in development mode
|
||||||
```
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|||||||
234
tests/integration/compose_integration_test.go
Normal file
234
tests/integration/compose_integration_test.go
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ComposeIntegrationTest runs integration tests against a containerized instance
|
||||||
|
func TestComposeIntegration(t *testing.T) {
|
||||||
|
if os.Getenv("RUN_COMPOSE_TESTS") != "true" {
|
||||||
|
t.Skip("Skipping compose integration tests. Set RUN_COMPOSE_TESTS=true to run")
|
||||||
|
}
|
||||||
|
|
||||||
|
composeCmd := detectComposeCommand(t)
|
||||||
|
projectName := "dyn-test-" + fmt.Sprintf("%d", time.Now().Unix())
|
||||||
|
|
||||||
|
// Cleanup function
|
||||||
|
cleanup := func() {
|
||||||
|
t.Log("Cleaning up containers...")
|
||||||
|
cmd := exec.Command(composeCmd, "-f", "../../docker-compose.yml", "-p", projectName, "down", "-v")
|
||||||
|
cmd.Run()
|
||||||
|
os.Remove(".env.test")
|
||||||
|
}
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
// Create test environment
|
||||||
|
envContent := `SERVER_PORT=8080
|
||||||
|
DATABASE_PATH=/data/dyn.db
|
||||||
|
TECHNITIUM_URL=http://mock-dns:8080
|
||||||
|
TECHNITIUM_TOKEN=test-token
|
||||||
|
BASE_DOMAIN=test.rip
|
||||||
|
SPACE_SUBDOMAIN=space
|
||||||
|
RATE_LIMIT_PER_IP=100
|
||||||
|
RATE_LIMIT_PER_TOKEN=100
|
||||||
|
`
|
||||||
|
err := os.WriteFile(".env.test", []byte(envContent), 0644)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Start services
|
||||||
|
t.Log("Starting services with", composeCmd)
|
||||||
|
cmd := exec.Command(composeCmd, "-f", "../../docker-compose.yml", "-p", projectName, "--env-file", ".env.test", "up", "-d", "--build")
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to start services: %v\nOutput: %s", err, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for service to be ready
|
||||||
|
baseURL := waitForService(t, "http://localhost:8080", 60)
|
||||||
|
t.Logf("Service ready at %s", baseURL)
|
||||||
|
|
||||||
|
// Run tests
|
||||||
|
t.Run("HealthCheck", func(t *testing.T) {
|
||||||
|
testHealthCheck(t, baseURL)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("CheckSubdomain", func(t *testing.T) {
|
||||||
|
testCheckSubdomain(t, baseURL)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ClaimSpace", func(t *testing.T) {
|
||||||
|
testClaimSpace(t, baseURL)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ProfanityFilter", func(t *testing.T) {
|
||||||
|
testProfanityFilterCompose(t, baseURL)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("CustomFilter", func(t *testing.T) {
|
||||||
|
testCustomFilterCompose(t, baseURL)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DynDNSEndpoint", func(t *testing.T) {
|
||||||
|
testDynDNSEndpoint(t, baseURL)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func detectComposeCommand(t *testing.T) string {
|
||||||
|
// Try podman-compose first
|
||||||
|
if _, err := exec.LookPath("podman-compose"); err == nil {
|
||||||
|
t.Log("Using podman-compose")
|
||||||
|
return "podman-compose"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try docker-compose
|
||||||
|
if _, err := exec.LookPath("docker-compose"); err == nil {
|
||||||
|
t.Log("Using docker-compose")
|
||||||
|
return "docker-compose"
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Skip("Neither podman-compose nor docker-compose found")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForService(t *testing.T, url string, timeout int) string {
|
||||||
|
client := &http.Client{Timeout: 2 * time.Second}
|
||||||
|
|
||||||
|
for i := 0; i < timeout; i++ {
|
||||||
|
resp, err := client.Get(url)
|
||||||
|
if err == nil && resp.StatusCode == http.StatusOK {
|
||||||
|
resp.Body.Close()
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
if resp != nil {
|
||||||
|
resp.Body.Close()
|
||||||
|
}
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Fatalf("Service did not become ready within %d seconds", timeout)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHealthCheck(t *testing.T, baseURL string) {
|
||||||
|
resp, err := http.Get(baseURL + "/")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
|
||||||
|
body := new(bytes.Buffer)
|
||||||
|
body.ReadFrom(resp.Body)
|
||||||
|
assert.Contains(t, body.String(), "DWS Dynamic DNS")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCheckSubdomain(t *testing.T, baseURL string) {
|
||||||
|
// Test available subdomain
|
||||||
|
resp, err := http.Get(baseURL + "/api/check?subdomain=newspace")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
|
||||||
|
var result map[string]interface{}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.True(t, result["available"].(bool))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testClaimSpace(t *testing.T, baseURL string) string {
|
||||||
|
payload := map[string]string{"subdomain": "testclaim"}
|
||||||
|
body, _ := json.Marshal(payload)
|
||||||
|
|
||||||
|
resp, err := http.Post(baseURL+"/api/claim", "application/json", bytes.NewBuffer(body))
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
||||||
|
|
||||||
|
var result map[string]interface{}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
token := result["token"].(string)
|
||||||
|
assert.NotEmpty(t, token)
|
||||||
|
assert.Equal(t, "testclaim", result["subdomain"])
|
||||||
|
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
func testProfanityFilterCompose(t *testing.T, baseURL string) {
|
||||||
|
profaneWords := []string{"fuck", "shit", "bitch"}
|
||||||
|
|
||||||
|
for _, word := range profaneWords {
|
||||||
|
t.Run(word, func(t *testing.T) {
|
||||||
|
payload := map[string]string{"subdomain": word}
|
||||||
|
body, _ := json.Marshal(payload)
|
||||||
|
|
||||||
|
resp, err := http.Post(baseURL+"/api/claim", "application/json", bytes.NewBuffer(body))
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
||||||
|
|
||||||
|
var result map[string]string
|
||||||
|
json.NewDecoder(resp.Body).Decode(&result)
|
||||||
|
assert.Contains(t, result["error"], "inappropriate")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCustomFilterCompose(t *testing.T, baseURL string) {
|
||||||
|
reservedWords := []string{"dws", "dubey", "tanishq"}
|
||||||
|
|
||||||
|
for _, word := range reservedWords {
|
||||||
|
t.Run(word, func(t *testing.T) {
|
||||||
|
payload := map[string]string{"subdomain": word}
|
||||||
|
body, _ := json.Marshal(payload)
|
||||||
|
|
||||||
|
resp, err := http.Post(baseURL+"/api/claim", "application/json", bytes.NewBuffer(body))
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
||||||
|
|
||||||
|
var result map[string]string
|
||||||
|
json.NewDecoder(resp.Body).Decode(&result)
|
||||||
|
assert.Contains(t, result["error"], "reserved")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDynDNSEndpoint(t *testing.T, baseURL string) {
|
||||||
|
// First claim a space
|
||||||
|
token := testClaimSpace(t, baseURL)
|
||||||
|
|
||||||
|
// Try DynDNS update
|
||||||
|
client := &http.Client{Timeout: 5 * time.Second}
|
||||||
|
req, err := http.NewRequest("GET", baseURL+"/api/nic/update?hostname=testclaim.space.test.rip&myip=192.168.1.100", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
req.Header.Set("Authorization", "Basic "+basicAuth("none", token))
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// We expect 200 or 503 (since there's no real DNS server)
|
||||||
|
assert.True(t, resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
func basicAuth(username, password string) string {
|
||||||
|
auth := username + ":" + password
|
||||||
|
return base64.StdEncoding.EncodeToString([]byte(auth))
|
||||||
|
}
|
||||||
159
tests/integration/compose_test.sh
Executable file
159
tests/integration/compose_test.sh
Executable file
@@ -0,0 +1,159 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
COMPOSE_FILE="docker-compose.yml"
|
||||||
|
TEST_TIMEOUT=60
|
||||||
|
CONTAINER_NAME="dyn-ddns-test"
|
||||||
|
|
||||||
|
echo -e "${YELLOW}=== DDNS Container Integration Test ===${NC}"
|
||||||
|
|
||||||
|
# Detect compose command
|
||||||
|
if command -v podman-compose &> /dev/null; then
|
||||||
|
COMPOSE_CMD="podman-compose"
|
||||||
|
echo -e "${GREEN}Using podman-compose${NC}"
|
||||||
|
elif command -v docker-compose &> /dev/null; then
|
||||||
|
COMPOSE_CMD="docker-compose"
|
||||||
|
echo -e "${GREEN}Using docker-compose${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Error: Neither podman-compose nor docker-compose found${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup function
|
||||||
|
cleanup() {
|
||||||
|
echo -e "${YELLOW}Cleaning up...${NC}"
|
||||||
|
$COMPOSE_CMD -f $COMPOSE_FILE -p $CONTAINER_NAME down -v 2>/dev/null || true
|
||||||
|
rm -f .env.test
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set trap for cleanup on exit
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# Create test environment file
|
||||||
|
cat > .env.test << EOF
|
||||||
|
SERVER_PORT=8080
|
||||||
|
DATABASE_PATH=/data/dyn.db
|
||||||
|
TECHNITIUM_URL=http://mock-dns:8080
|
||||||
|
TECHNITIUM_TOKEN=test-token
|
||||||
|
BASE_DOMAIN=test.rip
|
||||||
|
SPACE_SUBDOMAIN=space
|
||||||
|
RATE_LIMIT_PER_IP=100
|
||||||
|
RATE_LIMIT_PER_TOKEN=100
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Starting services...${NC}"
|
||||||
|
$COMPOSE_CMD -f $COMPOSE_FILE -p $CONTAINER_NAME --env-file .env.test up -d --build
|
||||||
|
|
||||||
|
# Wait for services to be ready
|
||||||
|
echo -e "${YELLOW}Waiting for services to start (timeout: ${TEST_TIMEOUT}s)...${NC}"
|
||||||
|
for i in $(seq 1 $TEST_TIMEOUT); do
|
||||||
|
if curl -s http://localhost:8080/ > /dev/null 2>&1; then
|
||||||
|
echo -e "${GREEN}Services are ready!${NC}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ $i -eq $TEST_TIMEOUT ]; then
|
||||||
|
echo -e "${RED}Timeout waiting for services${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Running integration tests...${NC}"
|
||||||
|
|
||||||
|
# Test 1: Health check
|
||||||
|
echo -n "Test 1: Health check... "
|
||||||
|
if curl -s http://localhost:8080/ | grep -q "DWS Dynamic DNS"; then
|
||||||
|
echo -e "${GREEN}PASS${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}FAIL${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test 2: Check subdomain availability
|
||||||
|
echo -n "Test 2: Check subdomain availability... "
|
||||||
|
RESPONSE=$(curl -s "http://localhost:8080/api/check?subdomain=testspace")
|
||||||
|
if echo "$RESPONSE" | grep -q '"available":true'; then
|
||||||
|
echo -e "${GREEN}PASS${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}FAIL${NC} - Response: $RESPONSE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test 3: Claim space
|
||||||
|
echo -n "Test 3: Claim space... "
|
||||||
|
RESPONSE=$(curl -s -X POST http://localhost:8080/api/claim \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"subdomain":"mytest"}')
|
||||||
|
if echo "$RESPONSE" | grep -q '"token"'; then
|
||||||
|
TOKEN=$(echo "$RESPONSE" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
|
||||||
|
echo -e "${GREEN}PASS${NC} (token: ${TOKEN:0:20}...)"
|
||||||
|
else
|
||||||
|
echo -e "${RED}FAIL${NC} - Response: $RESPONSE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test 4: Check claimed subdomain is not available
|
||||||
|
echo -n "Test 4: Check claimed subdomain unavailable... "
|
||||||
|
RESPONSE=$(curl -s "http://localhost:8080/api/check?subdomain=mytest")
|
||||||
|
if echo "$RESPONSE" | grep -q '"available":false'; then
|
||||||
|
echo -e "${GREEN}PASS${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}FAIL${NC} - Response: $RESPONSE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test 5: DynDNS update (mocked - will fail DNS but test auth)
|
||||||
|
echo -n "Test 5: DynDNS update endpoint... "
|
||||||
|
RESPONSE=$(curl -s -u "none:$TOKEN" \
|
||||||
|
"http://localhost:8080/api/nic/update?hostname=mytest.space.test.rip&myip=192.168.1.100")
|
||||||
|
# We expect 911 since there's no real DNS server, but auth should work
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}PASS${NC} (endpoint reachable)"
|
||||||
|
else
|
||||||
|
echo -e "${RED}FAIL${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test 6: Profanity filter
|
||||||
|
echo -n "Test 6: Profanity filter... "
|
||||||
|
RESPONSE=$(curl -s -X POST http://localhost:8080/api/claim \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"subdomain":"fuck"}')
|
||||||
|
if echo "$RESPONSE" | grep -q 'inappropriate'; then
|
||||||
|
echo -e "${GREEN}PASS${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}FAIL${NC} - Response: $RESPONSE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test 7: Custom filter (DWS terms)
|
||||||
|
echo -n "Test 7: Custom filter (DWS terms)... "
|
||||||
|
RESPONSE=$(curl -s -X POST http://localhost:8080/api/claim \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"subdomain":"dws"}')
|
||||||
|
if echo "$RESPONSE" | grep -q 'reserved'; then
|
||||||
|
echo -e "${GREEN}PASS${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}FAIL${NC} - Response: $RESPONSE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test 8: Invalid subdomain format
|
||||||
|
echo -n "Test 8: Invalid subdomain format... "
|
||||||
|
RESPONSE=$(curl -s -X POST http://localhost:8080/api/claim \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"subdomain":"ab"}')
|
||||||
|
if echo "$RESPONSE" | grep -q 'Invalid'; then
|
||||||
|
echo -e "${GREEN}PASS${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}FAIL${NC} - Response: $RESPONSE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}=== All tests passed! ===${NC}"
|
||||||
Reference in New Issue
Block a user