156 lines
4.5 KiB
Go
156 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestVerifyCapcha(t *testing.T) {
|
|
t.Run("valid token", func(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
t.Errorf("method = %s, want POST", r.Method)
|
|
}
|
|
if r.URL.Path != "/113476d322/siteverify" {
|
|
t.Errorf("path = %s, want /113476d322/siteverify", r.URL.Path)
|
|
}
|
|
if ct := r.Header.Get("Content-Type"); ct != "application/json" {
|
|
t.Errorf("content type = %s, want application/json", ct)
|
|
}
|
|
|
|
var payload map[string]string
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
t.Fatalf("decoding payload: %v", err)
|
|
}
|
|
if payload["secret"] != "sk-test" {
|
|
t.Errorf("secret = %q, want sk-test", payload["secret"])
|
|
}
|
|
if payload["response"] != "token-123" {
|
|
t.Errorf("response = %q, want token-123", payload["response"])
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"success":true}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
s := newTestServer()
|
|
s.config.CapchaInstance = srv.URL
|
|
s.config.CapchaSiteKey = "113476d322"
|
|
s.config.CapchaKeySecret = "sk-test"
|
|
|
|
if err := s.verifyCapcha(t.Context(), "token-123"); err != nil {
|
|
t.Fatalf("verifyCapcha returned error: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("rejected token", func(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"success":false,"error":"invalid token"}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
s := newTestServer()
|
|
s.config.CapchaInstance = srv.URL
|
|
s.config.CapchaKeySecret = "sk-test"
|
|
|
|
err := s.verifyCapcha(t.Context(), "bad-token")
|
|
if err == nil {
|
|
t.Fatal("verifyCapcha succeeded, want error")
|
|
}
|
|
if !strings.Contains(err.Error(), "invalid token") {
|
|
t.Errorf("error = %q, want it to contain the service error", err)
|
|
}
|
|
})
|
|
|
|
t.Run("missing token", func(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
t.Error("captcha service should not be called without a token")
|
|
}))
|
|
defer srv.Close()
|
|
|
|
s := newTestServer()
|
|
s.config.CapchaInstance = srv.URL
|
|
s.config.CapchaKeySecret = "sk-test"
|
|
|
|
if err := s.verifyCapcha(t.Context(), ""); err == nil {
|
|
t.Fatal("verifyCapcha succeeded, want error")
|
|
}
|
|
})
|
|
|
|
t.Run("missing secret", func(t *testing.T) {
|
|
s := newTestServer()
|
|
s.config.CapchaKeySecret = ""
|
|
|
|
if err := s.verifyCapcha(t.Context(), "token-123"); err == nil {
|
|
t.Fatal("verifyCapcha succeeded, want error")
|
|
}
|
|
})
|
|
|
|
t.Run("service error", func(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
http.Error(w, "boom", http.StatusInternalServerError)
|
|
}))
|
|
defer srv.Close()
|
|
|
|
s := newTestServer()
|
|
s.config.CapchaInstance = srv.URL
|
|
s.config.CapchaKeySecret = "sk-test"
|
|
|
|
if err := s.verifyCapcha(t.Context(), "token-123"); err == nil {
|
|
t.Fatal("verifyCapcha succeeded, want error")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestContactFormRequiresCapToken(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"success":false,"error":"invalid token"}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
s := newTestServer()
|
|
s.config.CapchaInstance = srv.URL
|
|
s.config.CapchaKeySecret = "sk-test"
|
|
s.config.TelegramBotToken = ""
|
|
s.config.TelegramChatID = ""
|
|
|
|
// Forged submission without a cap-token must be rejected.
|
|
body := url.Values{
|
|
"name": {"Test"},
|
|
"email": {"test@example.com"},
|
|
"message": {"Hallo"},
|
|
}
|
|
req := httptest.NewRequest(http.MethodPost, "/contact", strings.NewReader(body.Encode()))
|
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
req.Header.Set("X-Forwarded-For", "203.0.113.10")
|
|
rec := httptest.NewRecorder()
|
|
|
|
s.contactHandler(rec, req)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200", rec.Code)
|
|
}
|
|
respBody := rec.Body.String()
|
|
if strings.Contains(respBody, "Bedankt voor uw bericht") {
|
|
t.Fatal("submission without a cap-token was accepted")
|
|
}
|
|
if !strings.Contains(respBody, "mens-verificatie is mislukt") {
|
|
t.Fatalf("expected verification error message, got: %s", respBody)
|
|
}
|
|
}
|
|
|
|
func newTestServer() *Server {
|
|
s := NewServer()
|
|
// Keep tests independent from any ambient Telegram configuration.
|
|
s.config.TelegramBotToken = ""
|
|
s.config.TelegramChatID = ""
|
|
return s
|
|
}
|