package server import ( "bytes" "encoding/json" "mime/multipart" "net/http" "net/http/httptest" "strings" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.kenn.io/agentsview/internal/importer" ) func TestHandleImportClaudeAI(t *testing.T) { srv := testServer(t, 5*time.Second) conversations := `[ { "uuid": "api-test-001", "name": "API Test", "summary": "", "created_at": "2026-03-01T10:00:00.000000Z", "updated_at": "2026-03-01T10:05:00.000000Z", "account": {"uuid": "acct-1"}, "chat_messages": [ { "uuid": "m1", "text": "Test message", "content": [{"type":"text","text":"Test message"}], "sender": "human", "created_at": "2026-03-01T10:00:00.000000Z", "updated_at": "2026-03-01T10:00:00.000000Z", "attachments": [], "files": [] } ] } ]` var body bytes.Buffer writer := multipart.NewWriter(&body) part, err := writer.CreateFormFile("file", "conversations.json") require.NoError(t, err) _, _ = part.Write([]byte(conversations)) writer.Close() req := httptest.NewRequest( http.MethodPost, "/api/v1/import/claude-ai", &body, ) req.Header.Set("Content-Type", writer.FormDataContentType()) rec := httptest.NewRecorder() srv.mux.ServeHTTP(rec, req) require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var stats importer.ImportStats require.NoError(t, json.NewDecoder(rec.Body).Decode(&stats)) assert.Equal(t, 1, stats.Imported) assert.Zero(t, stats.Updated) } func TestHandleImportChatGPT_RequiresZip(t *testing.T) { srv := testServer(t, 5*time.Second) var body bytes.Buffer writer := multipart.NewWriter(&body) part, err := writer.CreateFormFile("file", "data.json") require.NoError(t, err) _, _ = part.Write([]byte("[]")) writer.Close() req := httptest.NewRequest( http.MethodPost, "/api/v1/import/chatgpt", &body, ) req.Header.Set( "Content-Type", writer.FormDataContentType(), ) rec := httptest.NewRecorder() srv.mux.ServeHTTP(rec, req) require.Equal(t, http.StatusBadRequest, rec.Code, "body: %s", rec.Body.String()) } func TestHandleImportClaudeAI_SSE(t *testing.T) { srv := testServer(t, 5*time.Second) conversations := `[{ "uuid": "sse-test-001", "name": "SSE Test", "created_at": "2026-03-01T10:00:00.000000Z", "updated_at": "2026-03-01T10:05:00.000000Z", "chat_messages": [{ "uuid": "m1", "text": "hello", "sender": "human", "content": [{"type":"text","text":"hello"}], "created_at": "2026-03-01T10:00:00.000000Z" }] }]` var body bytes.Buffer writer := multipart.NewWriter(&body) part, err := writer.CreateFormFile( "file", "conversations.json", ) require.NoError(t, err) _, _ = part.Write([]byte(conversations)) writer.Close() req := httptest.NewRequest( http.MethodPost, "/api/v1/import/claude-ai", &body, ) req.Header.Set( "Content-Type", writer.FormDataContentType(), ) req.Header.Set("Accept", "text/event-stream") rec := httptest.NewRecorder() srv.mux.ServeHTTP(rec, req) require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) require.Contains(t, rec.Header().Get("Content-Type"), "text/event-stream") // Parse the done event from the SSE body. var stats importer.ImportStats lines := strings.Split(rec.Body.String(), "\n") for i, line := range lines { if line == "event: done" && i+1 < len(lines) { data := strings.TrimPrefix( lines[i+1], "data: ", ) require.NoError(t, json.Unmarshal([]byte(data), &stats)) } } assert.Equal(t, 1, stats.Imported) } func TestHandleImportClaudeAI_NoFile(t *testing.T) { srv := testServer(t, 5*time.Second) var body bytes.Buffer writer := multipart.NewWriter(&body) writer.Close() req := httptest.NewRequest( http.MethodPost, "/api/v1/import/claude-ai", &body, ) req.Header.Set("Content-Type", writer.FormDataContentType()) rec := httptest.NewRecorder() srv.mux.ServeHTTP(rec, req) require.Equal(t, http.StatusBadRequest, rec.Code, "body: %s", rec.Body.String()) }