Files
vessel/backend/internal/api/geolocation_test.go
vikingowl d81430e1aa test: extend test coverage for backend and frontend
Backend:
- Add fetcher_test.go (HTML stripping, URL fetching utilities)
- Add model_registry_test.go (parsing, size ranges, model matching)
- Add database_test.go (CRUD operations, migrations)
- Add tests for geolocation, search, tools, version handlers

Frontend unit tests (469 total):
- OllamaClient: 22 tests for API methods with mocked fetch
- Memory/RAG: tokenizer, chunker, summarizer, embeddings, vector-store
- Services: prompt-resolution, conversation-summary
- Components: Skeleton, BranchNavigator, ConfirmDialog, ThinkingBlock
- Utils: export, import, file-processor, keyboard
- Tools: builtin math parser (44 tests)

E2E tests (28 total):
- Set up Playwright with Chromium
- App loading, sidebar navigation, settings page
- Chat interface, responsive design, accessibility
- Import dialog, project modal interactions

Config changes:
- Add browser conditions to vitest.config.ts for Svelte 5 components
- Add playwright.config.ts for E2E testing
- Add test:e2e scripts to package.json
- Update .gitignore to exclude test artifacts

Closes #8
2026-01-22 11:05:49 +01:00

134 lines
3.3 KiB
Go

package api
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
)
func TestIsPrivateIP(t *testing.T) {
tests := []struct {
name string
ip string
expected bool
}{
// Loopback addresses
{"IPv4 loopback", "127.0.0.1", true},
{"IPv6 loopback", "::1", true},
// Private IPv4 ranges (RFC 1918)
{"10.x.x.x range", "10.0.0.1", true},
{"10.x.x.x high", "10.255.255.255", true},
{"172.16.x.x range", "172.16.0.1", true},
{"172.31.x.x range", "172.31.255.255", true},
{"192.168.x.x range", "192.168.0.1", true},
{"192.168.x.x high", "192.168.255.255", true},
// Public IPv4 addresses
{"Google DNS", "8.8.8.8", false},
{"Cloudflare DNS", "1.1.1.1", false},
{"Random public IP", "203.0.113.50", false},
// Edge cases - not in private ranges
{"172.15.x.x not private", "172.15.0.1", false},
{"172.32.x.x not private", "172.32.0.1", false},
{"192.167.x.x not private", "192.167.0.1", false},
// IPv6 private (fc00::/7)
{"IPv6 private fc", "fc00::1", true},
{"IPv6 private fd", "fd00::1", true},
// IPv6 public
{"IPv6 public", "2001:4860:4860::8888", false},
// Invalid inputs
{"invalid IP", "not-an-ip", false},
{"empty string", "", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := isPrivateIP(tt.ip)
if result != tt.expected {
t.Errorf("isPrivateIP(%q) = %v, want %v", tt.ip, result, tt.expected)
}
})
}
}
func TestGetClientIP(t *testing.T) {
gin.SetMode(gin.TestMode)
tests := []struct {
name string
headers map[string]string
remoteAddr string
expected string
}{
{
name: "X-Forwarded-For single IP",
headers: map[string]string{"X-Forwarded-For": "203.0.113.50"},
remoteAddr: "127.0.0.1:8080",
expected: "203.0.113.50",
},
{
name: "X-Forwarded-For multiple IPs",
headers: map[string]string{"X-Forwarded-For": "203.0.113.50, 70.41.3.18, 150.172.238.178"},
remoteAddr: "127.0.0.1:8080",
expected: "203.0.113.50",
},
{
name: "X-Real-IP header",
headers: map[string]string{"X-Real-IP": "198.51.100.178"},
remoteAddr: "127.0.0.1:8080",
expected: "198.51.100.178",
},
{
name: "X-Forwarded-For takes precedence over X-Real-IP",
headers: map[string]string{"X-Forwarded-For": "203.0.113.50", "X-Real-IP": "198.51.100.178"},
remoteAddr: "127.0.0.1:8080",
expected: "203.0.113.50",
},
{
name: "fallback to RemoteAddr",
headers: map[string]string{},
remoteAddr: "192.168.1.100:54321",
expected: "192.168.1.100",
},
{
name: "X-Forwarded-For with whitespace",
headers: map[string]string{"X-Forwarded-For": " 203.0.113.50 "},
remoteAddr: "127.0.0.1:8080",
expected: "203.0.113.50",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
router := gin.New()
var capturedIP string
router.GET("/test", func(c *gin.Context) {
capturedIP = getClientIP(c)
c.Status(http.StatusOK)
})
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/test", nil)
req.RemoteAddr = tt.remoteAddr
for key, value := range tt.headers {
req.Header.Set(key, value)
}
router.ServeHTTP(w, req)
if capturedIP != tt.expected {
t.Errorf("getClientIP() = %q, want %q", capturedIP, tt.expected)
}
})
}
}