summaryrefslogtreecommitdiff
path: root/internal/api/research_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/api/research_test.go')
-rw-r--r--internal/api/research_test.go241
1 files changed, 0 insertions, 241 deletions
diff --git a/internal/api/research_test.go b/internal/api/research_test.go
deleted file mode 100644
index f2519e2..0000000
--- a/internal/api/research_test.go
+++ /dev/null
@@ -1,241 +0,0 @@
-package api
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "os"
- "testing"
- "time"
-)
-
-// Research tests for API optimization
-// Run with: go test -v -run TestResearch ./internal/api/
-// Requires TODOIST_API_KEY and TRELLO_API_KEY/TRELLO_TOKEN environment variables
-
-func TestTodoistSyncResearch(t *testing.T) {
- apiKey := os.Getenv("TODOIST_API_KEY")
- if apiKey == "" {
- t.Skip("TODOIST_API_KEY not set, skipping research test")
- }
-
- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
- defer cancel()
-
- // Todoist Sync API endpoint
- syncURL := "https://api.todoist.com/sync/v9/sync"
-
- // First sync with "*" to get all data
- params := url.Values{}
- params.Set("sync_token", "*")
- params.Set("resource_types", `["items"]`) // "items" = tasks in Sync API
-
- req, err := http.NewRequestWithContext(ctx, "POST", syncURL, nil)
- if err != nil {
- t.Fatalf("Failed to create request: %v", err)
- }
- req.URL.RawQuery = params.Encode()
- req.Header.Set("Authorization", "Bearer "+apiKey)
-
- client := &http.Client{Timeout: 30 * time.Second}
- resp, err := client.Do(req)
- if err != nil {
- t.Fatalf("Failed to call Sync API: %v", err)
- }
- defer func() { _ = resp.Body.Close() }()
-
- body, err := io.ReadAll(resp.Body)
- if err != nil {
- t.Fatalf("Failed to read response: %v", err)
- }
-
- if resp.StatusCode != http.StatusOK {
- t.Fatalf("Sync API error (status %d): %s", resp.StatusCode, string(body))
- }
-
- // Parse response
- var syncResp map[string]interface{}
- if err := json.Unmarshal(body, &syncResp); err != nil {
- t.Fatalf("Failed to parse response: %v", err)
- }
-
- // Log findings
- t.Logf("=== TODOIST SYNC API RESEARCH ===")
- t.Logf("Response size: %d bytes", len(body))
-
- if syncToken, ok := syncResp["sync_token"].(string); ok {
- t.Logf("sync_token: %s... (length: %d)", syncToken[:min(20, len(syncToken))], len(syncToken))
- }
-
- if items, ok := syncResp["items"].([]interface{}); ok {
- t.Logf("Number of items (tasks): %d", len(items))
- if len(items) > 0 {
- // Show structure of first item
- firstItem, _ := json.MarshalIndent(items[0], "", " ")
- t.Logf("First item structure:\n%s", string(firstItem))
- }
- }
-
- // List top-level keys
- t.Logf("Top-level response keys:")
- for key := range syncResp {
- t.Logf(" - %s", key)
- }
-
- // Save sync_token for incremental sync test
- syncToken := syncResp["sync_token"].(string)
-
- // Test incremental sync (should return minimal data if nothing changed)
- t.Logf("\n=== INCREMENTAL SYNC TEST ===")
- params2 := url.Values{}
- params2.Set("sync_token", syncToken)
- params2.Set("resource_types", `["items"]`)
-
- req2, _ := http.NewRequestWithContext(ctx, "POST", syncURL, nil)
- req2.URL.RawQuery = params2.Encode()
- req2.Header.Set("Authorization", "Bearer "+apiKey)
-
- resp2, err := client.Do(req2)
- if err != nil {
- t.Fatalf("Incremental sync failed: %v", err)
- }
- defer func() { _ = resp2.Body.Close() }()
-
- body2, _ := io.ReadAll(resp2.Body)
- t.Logf("Incremental response size: %d bytes (vs full: %d bytes)", len(body2), len(body))
-
- var syncResp2 map[string]interface{}
- _ = json.Unmarshal(body2, &syncResp2)
- if items2, ok := syncResp2["items"].([]interface{}); ok {
- t.Logf("Incremental items count: %d", len(items2))
- }
-}
-
-func TestTrelloOptimizationResearch(t *testing.T) {
- apiKey := os.Getenv("TRELLO_API_KEY")
- token := os.Getenv("TRELLO_TOKEN")
- if apiKey == "" || token == "" {
- t.Skip("TRELLO_API_KEY or TRELLO_TOKEN not set, skipping research test")
- }
-
- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
- defer cancel()
-
- client := &http.Client{Timeout: 30 * time.Second}
- baseURL := "https://api.trello.com/1"
-
- // Test 1: Full response (current implementation)
- t.Logf("=== TRELLO OPTIMIZATION RESEARCH ===")
-
- params := url.Values{}
- params.Set("key", apiKey)
- params.Set("token", token)
- params.Set("filter", "open")
-
- start := time.Now()
- req, _ := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/members/me/boards?%s", baseURL, params.Encode()), nil)
- resp, err := client.Do(req)
- if err != nil {
- t.Fatalf("Failed to fetch boards: %v", err)
- }
- body, _ := io.ReadAll(resp.Body)
- _ = resp.Body.Close()
- fullDuration := time.Since(start)
-
- t.Logf("Test 1 - Full boards response:")
- t.Logf(" Size: %d bytes", len(body))
- t.Logf(" Duration: %v", fullDuration)
-
- var boards []map[string]interface{}
- _ = json.Unmarshal(body, &boards)
- t.Logf(" Board count: %d", len(boards))
- if len(boards) > 0 {
- t.Logf(" Fields in first board: %v", getKeys(boards[0]))
- }
-
- // Test 2: Limited fields
- params2 := url.Values{}
- params2.Set("key", apiKey)
- params2.Set("token", token)
- params2.Set("filter", "open")
- params2.Set("fields", "id,name") // Only essential fields
-
- start = time.Now()
- req2, _ := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/members/me/boards?%s", baseURL, params2.Encode()), nil)
- resp2, err := client.Do(req2)
- if err != nil {
- t.Fatalf("Failed to fetch limited boards: %v", err)
- }
- body2, _ := io.ReadAll(resp2.Body)
- _ = resp2.Body.Close()
- limitedDuration := time.Since(start)
-
- t.Logf("\nTest 2 - Limited fields (id,name):")
- t.Logf(" Size: %d bytes (%.1f%% of full)", len(body2), float64(len(body2))/float64(len(body))*100)
- t.Logf(" Duration: %v", limitedDuration)
-
- // Test 3: Batch request with cards included
- if len(boards) > 0 {
- boardID := boards[0]["id"].(string)
-
- params3 := url.Values{}
- params3.Set("key", apiKey)
- params3.Set("token", token)
- params3.Set("cards", "visible")
- params3.Set("card_fields", "id,name,idList,due,url")
- params3.Set("lists", "open")
- params3.Set("list_fields", "id,name")
-
- start = time.Now()
- req3, _ := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/boards/%s?%s", baseURL, boardID, params3.Encode()), nil)
- resp3, err := client.Do(req3)
- if err != nil {
- t.Fatalf("Failed to fetch board with cards: %v", err)
- }
- body3, _ := io.ReadAll(resp3.Body)
- _ = resp3.Body.Close()
- batchDuration := time.Since(start)
-
- t.Logf("\nTest 3 - Single board with cards/lists embedded:")
- t.Logf(" Size: %d bytes", len(body3))
- t.Logf(" Duration: %v", batchDuration)
-
- var boardWithCards map[string]interface{}
- _ = json.Unmarshal(body3, &boardWithCards)
- if cards, ok := boardWithCards["cards"].([]interface{}); ok {
- t.Logf(" Cards count: %d", len(cards))
- }
- if lists, ok := boardWithCards["lists"].([]interface{}); ok {
- t.Logf(" Lists count: %d", len(lists))
- }
- }
-
- // Test 4: Check for webhooks/since parameter
- t.Logf("\nTest 4 - Checking for 'since' parameter support:")
- params4 := url.Values{}
- params4.Set("key", apiKey)
- params4.Set("token", token)
- params4.Set("filter", "open")
- params4.Set("since", time.Now().Add(-24*time.Hour).Format(time.RFC3339))
-
- req4, _ := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/members/me/boards?%s", baseURL, params4.Encode()), nil)
- resp4, err := client.Do(req4)
- if err != nil {
- t.Logf(" 'since' parameter: Error - %v", err)
- } else {
- body4, _ := io.ReadAll(resp4.Body)
- _ = resp4.Body.Close()
- t.Logf(" 'since' parameter: Status %d, Size %d bytes", resp4.StatusCode, len(body4))
- }
-}
-
-func getKeys(m map[string]interface{}) []string {
- keys := make([]string, 0, len(m))
- for k := range m {
- keys = append(keys, k)
- }
- return keys
-}