mirror of
https://github.com/open-gitagent/langship.sh.git
synced 2026-08-03 07:21:04 +02:00
feat(web): initialize Next.js project with Tailwind CSS and TypeScript setup
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
package orchestrator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestHealthCheckRestate_okWhen200(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/restate/health" {
|
||||
t.Errorf("path: %s", r.URL.Path)
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
if err := HealthCheckRestate(srv.URL); err != nil {
|
||||
t.Fatalf("expected nil, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthCheckRestate_failsOnNon2xx(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
if err := HealthCheckRestate(srv.URL); err == nil {
|
||||
t.Fatal("expected error on 503")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthCheckRestate_failsWhenUnreachable(t *testing.T) {
|
||||
if err := HealthCheckRestate("http://127.0.0.1:1"); err == nil {
|
||||
t.Fatal("expected unreachable error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterDeployment_postsExpectedBody(t *testing.T) {
|
||||
var seen struct {
|
||||
path string
|
||||
body []byte
|
||||
contentType string
|
||||
}
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
seen.path = r.URL.Path
|
||||
seen.contentType = r.Header.Get("Content-Type")
|
||||
buf := make([]byte, 256)
|
||||
n, _ := r.Body.Read(buf)
|
||||
seen.body = buf[:n]
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
if err := RegisterDeployment(context.Background(), srv.URL, "http://flow:9080"); err != nil {
|
||||
t.Fatalf("unexpected: %v", err)
|
||||
}
|
||||
if seen.path != "/deployments" {
|
||||
t.Errorf("path: %q", seen.path)
|
||||
}
|
||||
if seen.contentType != "application/json" {
|
||||
t.Errorf("content-type: %q", seen.contentType)
|
||||
}
|
||||
var body map[string]any
|
||||
if err := json.Unmarshal(seen.body, &body); err != nil {
|
||||
t.Fatalf("body json: %v", err)
|
||||
}
|
||||
if body["uri"] != "http://flow:9080" || body["force"] != true {
|
||||
t.Errorf("body: %+v", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterDeployment_returnsErrorOn5xx(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
_, _ = w.Write([]byte("oops"))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
if err := RegisterDeployment(context.Background(), srv.URL, "http://flow:9080"); err == nil {
|
||||
t.Fatal("expected error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterDeploymentWithRetry_succeedsAfterFailures(t *testing.T) {
|
||||
var attempts int32
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
n := atomic.AddInt32(&attempts, 1)
|
||||
if n < 3 {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
if err := RegisterDeploymentWithRetry(context.Background(), srv.URL, "http://flow:9080", 5, 5*time.Millisecond); err != nil {
|
||||
t.Fatalf("expected success after retries, got %v", err)
|
||||
}
|
||||
if atomic.LoadInt32(&attempts) != 3 {
|
||||
t.Fatalf("expected 3 attempts, got %d", attempts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterDeploymentWithRetry_givesUpAfterMaxAttempts(t *testing.T) {
|
||||
var attempts int32
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
atomic.AddInt32(&attempts, 1)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
err := RegisterDeploymentWithRetry(context.Background(), srv.URL, "http://flow:9080", 3, 1*time.Millisecond)
|
||||
if err == nil {
|
||||
t.Fatal("expected failure")
|
||||
}
|
||||
if got := atomic.LoadInt32(&attempts); got != 3 {
|
||||
t.Fatalf("attempts: got %d, want 3", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterDeploymentWithRetry_respectsContextCancel(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
if err := RegisterDeploymentWithRetry(ctx, srv.URL, "http://flow:9080", 100, 50*time.Millisecond); err == nil {
|
||||
t.Fatal("expected error from cancelled context")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user