package unfurl
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFetchKagiKite_Success(t *testing.T) {
// Mock Kagi HTML response
mockHTML := `
FAA orders 10% flight cuts at 40 airports - Kagi News
`
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(mockHTML))
}))
defer server.Close()
ctx := context.Background()
result, err := fetchKagiKite(ctx, server.URL, 5*time.Second, "TestBot/1.0")
require.NoError(t, err)
assert.Equal(t, "article", result.Type)
assert.Equal(t, "FAA orders 10% flight cuts", result.Title)
assert.Equal(t, "Flight restrictions announced", result.Description)
assert.Contains(t, result.ThumbnailURL, "kagiproxy.com")
assert.Equal(t, "kagi", result.Provider)
assert.Equal(t, "kite.kagi.com", result.Domain)
}
func TestFetchKagiKite_NoImage(t *testing.T) {
mockHTML := `
Test Story
No images here
`
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(mockHTML))
}))
defer server.Close()
ctx := context.Background()
result, err := fetchKagiKite(ctx, server.URL, 5*time.Second, "TestBot/1.0")
assert.Error(t, err)
assert.Nil(t, result)
assert.Contains(t, err.Error(), "no image found")
}
func TestFetchKagiKite_FallbackToTitle(t *testing.T) {
mockHTML := `
Fallback Title
`
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(mockHTML))
}))
defer server.Close()
ctx := context.Background()
result, err := fetchKagiKite(ctx, server.URL, 5*time.Second, "TestBot/1.0")
require.NoError(t, err)
assert.Equal(t, "Fallback Title", result.Title)
assert.Contains(t, result.ThumbnailURL, "kagiproxy.com")
}
func TestFetchKagiKite_ImageWithAltText(t *testing.T) {
mockHTML := `
News Story
`
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(mockHTML))
}))
defer server.Close()
ctx := context.Background()
result, err := fetchKagiKite(ctx, server.URL, 5*time.Second, "TestBot/1.0")
require.NoError(t, err)
assert.Equal(t, "News Story", result.Title)
assert.Equal(t, "This is the alt text description", result.Description)
assert.Contains(t, result.ThumbnailURL, "kagiproxy.com")
}
func TestFetchKagiKite_HTTPError(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}))
defer server.Close()
ctx := context.Background()
result, err := fetchKagiKite(ctx, server.URL, 5*time.Second, "TestBot/1.0")
assert.Error(t, err)
assert.Nil(t, result)
assert.Contains(t, err.Error(), "HTTP 404")
}
func TestFetchKagiKite_Timeout(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(2 * time.Second)
w.WriteHeader(http.StatusOK)
}))
defer server.Close()
ctx := context.Background()
result, err := fetchKagiKite(ctx, server.URL, 100*time.Millisecond, "TestBot/1.0")
assert.Error(t, err)
assert.Nil(t, result)
}
func TestFetchKagiKite_MultipleImages_PicksSecond(t *testing.T) {
mockHTML := `
Story with multiple images
`
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(mockHTML))
}))
defer server.Close()
ctx := context.Background()
result, err := fetchKagiKite(ctx, server.URL, 5*time.Second, "TestBot/1.0")
require.NoError(t, err)
// We skip the first image (often a header/logo) and use the second
assert.Contains(t, result.ThumbnailURL, "second456")
assert.Equal(t, "Second image", result.Description)
}
func TestFetchKagiKite_OnlyNonKagiImages_NoMatch(t *testing.T) {
mockHTML := `
Story with non-Kagi images
`
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(mockHTML))
}))
defer server.Close()
ctx := context.Background()
result, err := fetchKagiKite(ctx, server.URL, 5*time.Second, "TestBot/1.0")
assert.Error(t, err)
assert.Nil(t, result)
assert.Contains(t, err.Error(), "no image found")
}