diff options
Diffstat (limited to 'internal/api/research_test.go')
| -rw-r--r-- | internal/api/research_test.go | 241 |
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 -} |
