266 lines
6.8 KiB
Go
266 lines
6.8 KiB
Go
//go:build integration
|
|
|
|
package admin_test
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/qianfree/team-api/tests/integration/admin/testinfra"
|
|
)
|
|
|
|
func TestUsageLogList(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
resp := client.Get("/api/admin/usage-logs", map[string]string{
|
|
"page": "1",
|
|
"page_size": "10",
|
|
})
|
|
testinfra.AssertPaginatedList(t, resp, 0)
|
|
|
|
t.Logf("Usage log list: total=%d", resp.GetTotal(t))
|
|
}
|
|
|
|
func TestUsageLogListWithFilters(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
// Date range filter
|
|
resp := client.Get("/api/admin/usage-logs", map[string]string{
|
|
"page": "1",
|
|
"page_size": "10",
|
|
"start_date": "2025-01-01",
|
|
"end_date": "2030-12-31",
|
|
})
|
|
testinfra.AssertPaginatedList(t, resp, 0)
|
|
|
|
// Status filter
|
|
resp2 := client.Get("/api/admin/usage-logs", map[string]string{
|
|
"page": "1",
|
|
"page_size": "10",
|
|
"status": "success",
|
|
})
|
|
testinfra.AssertPaginatedList(t, resp2, 0)
|
|
|
|
// Verify status filter correctness
|
|
if resp2.GetTotal(t) > 0 {
|
|
var data struct {
|
|
List []struct {
|
|
Id int64 `json:"id"`
|
|
Status string `json:"status"`
|
|
} `json:"list"`
|
|
}
|
|
resp2.DecodeData(t, &data)
|
|
|
|
for _, item := range data.List {
|
|
if item.Status != "success" {
|
|
t.Fatalf("filter status=success returned item with status=%q (id=%d)", item.Status, item.Id)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Narrow date range (should have fewer results)
|
|
narrowResp := client.Get("/api/admin/usage-logs", map[string]string{
|
|
"page": "1",
|
|
"page_size": "10",
|
|
"start_date": "2026-05-01",
|
|
"end_date": "2026-05-27",
|
|
})
|
|
narrowResp.AssertSuccess(t)
|
|
|
|
// Tenant filter
|
|
tenantID, cleanup := testinfra.CreateTestTenant(t, client)
|
|
defer cleanup()
|
|
|
|
tenantResp := client.Get("/api/admin/usage-logs", map[string]string{
|
|
"page": "1",
|
|
"page_size": "10",
|
|
"tenant_id": fmt.Sprintf("%d", tenantID),
|
|
})
|
|
tenantResp.AssertSuccess(t)
|
|
|
|
// New tenant should have no usage
|
|
var tenantData struct {
|
|
Total int `json:"total"`
|
|
}
|
|
tenantResp.DecodeData(t, &tenantData)
|
|
if tenantData.Total != 0 {
|
|
t.Fatalf("new tenant should have 0 usage logs, got %d", tenantData.Total)
|
|
}
|
|
}
|
|
|
|
func TestUsageLogCleanupCreate(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
// Create a cleanup task with dry_run=true (non-destructive)
|
|
createResp := client.Post("/api/admin/usage-logs/cleanup", map[string]any{
|
|
"start_time": "2025-01-01T00:00:00Z",
|
|
"end_time": "2025-12-31T23:59:59Z",
|
|
"batch_size": 5000,
|
|
"dry_run": true,
|
|
})
|
|
createResp.AssertSuccess(t)
|
|
|
|
var createData struct {
|
|
TaskID int64 `json:"task_id"`
|
|
}
|
|
createResp.DecodeData(t, &createData)
|
|
|
|
if createData.TaskID <= 0 {
|
|
t.Fatalf("expected valid task_id, got %d", createData.TaskID)
|
|
}
|
|
|
|
t.Logf("Cleanup task created: task_id=%d", createData.TaskID)
|
|
}
|
|
|
|
func TestUsageLogCleanupList(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
// Create a cleanup task first
|
|
createResp := client.Post("/api/admin/usage-logs/cleanup", map[string]any{
|
|
"start_time": "2025-01-01T00:00:00Z",
|
|
"end_time": "2025-12-31T23:59:59Z",
|
|
"batch_size": 5000,
|
|
"dry_run": true,
|
|
})
|
|
createResp.AssertSuccess(t)
|
|
|
|
// List cleanup tasks
|
|
listResp := client.Get("/api/admin/usage-logs/cleanup/tasks", map[string]string{
|
|
"page": "1",
|
|
"page_size": "10",
|
|
})
|
|
testinfra.AssertPaginatedList(t, listResp, 1)
|
|
|
|
var listData struct {
|
|
List []struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Status string `json:"status"`
|
|
} `json:"list"`
|
|
}
|
|
listResp.DecodeData(t, &listData)
|
|
|
|
if len(listData.List) > 0 {
|
|
task := listData.List[0]
|
|
if task.ID <= 0 {
|
|
t.Fatalf("expected valid task ID, got %d", task.ID)
|
|
}
|
|
if task.Status == "" {
|
|
t.Fatal("task should have non-empty status")
|
|
}
|
|
t.Logf("Cleanup task: id=%d, name=%q, status=%q", task.ID, task.Name, task.Status)
|
|
}
|
|
}
|
|
|
|
func TestUsageLogCleanupCancel(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
// Create a cleanup task
|
|
createResp := client.Post("/api/admin/usage-logs/cleanup", map[string]any{
|
|
"start_time": "2025-01-01T00:00:00Z",
|
|
"end_time": "2025-12-31T23:59:59Z",
|
|
"batch_size": 5000,
|
|
"dry_run": true,
|
|
})
|
|
createResp.AssertSuccess(t)
|
|
|
|
var createData struct {
|
|
TaskID int64 `json:"task_id"`
|
|
}
|
|
createResp.DecodeData(t, &createData)
|
|
|
|
if createData.TaskID <= 0 {
|
|
t.Skip("Failed to create cleanup task for cancel test")
|
|
}
|
|
|
|
// Cancel the cleanup task
|
|
cancelResp := client.Post(fmt.Sprintf("/api/admin/usage-logs/cleanup/tasks/%d/cancel", createData.TaskID), nil)
|
|
cancelResp.AssertSuccess(t)
|
|
|
|
// Verify the task is cancelled via list
|
|
listResp := client.Get("/api/admin/usage-logs/cleanup/tasks", map[string]string{
|
|
"page": "1",
|
|
"page_size": "50",
|
|
})
|
|
listResp.AssertSuccess(t)
|
|
|
|
var listData struct {
|
|
List []struct {
|
|
ID int64 `json:"id"`
|
|
Status string `json:"status"`
|
|
} `json:"list"`
|
|
}
|
|
listResp.DecodeData(t, &listData)
|
|
|
|
for _, task := range listData.List {
|
|
if task.ID == createData.TaskID {
|
|
if task.Status != "cancelled" {
|
|
t.Fatalf("expected status=cancelled after cancel, got %q", task.Status)
|
|
}
|
|
return
|
|
}
|
|
}
|
|
|
|
t.Logf("Cleanup task %d cancelled", createData.TaskID)
|
|
}
|
|
|
|
func TestUsageLogExport(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
// CSV export
|
|
csvResp := client.Get("/api/admin/usage-logs/export", map[string]string{
|
|
"format": "csv",
|
|
})
|
|
csvResp.AssertSuccess(t)
|
|
|
|
// XLSX export
|
|
xlsxResp := client.Get("/api/admin/usage-logs/export", map[string]string{
|
|
"format": "xlsx",
|
|
})
|
|
xlsxResp.AssertSuccess(t)
|
|
|
|
// Export with filters
|
|
filteredResp := client.Get("/api/admin/usage-logs/export", map[string]string{
|
|
"format": "csv",
|
|
"status": "success",
|
|
"start_date": "2025-01-01",
|
|
"end_date": "2030-12-31",
|
|
})
|
|
filteredResp.AssertSuccess(t)
|
|
}
|
|
|
|
func TestUsageLogNegative(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
// Cleanup with missing required fields
|
|
missingResp := client.Post("/api/admin/usage-logs/cleanup", map[string]any{})
|
|
if missingResp.Code == 0 {
|
|
t.Fatal("expected error for missing cleanup fields, got success")
|
|
}
|
|
|
|
// Cleanup with invalid batch_size (too small)
|
|
invalidBatchResp := client.Post("/api/admin/usage-logs/cleanup", map[string]any{
|
|
"start_time": "2025-01-01T00:00:00Z",
|
|
"end_time": "2025-12-31T23:59:59Z",
|
|
"batch_size": 10,
|
|
})
|
|
if invalidBatchResp.Code == 0 {
|
|
t.Fatal("expected error for batch_size < 100, got success")
|
|
}
|
|
|
|
// Cancel non-existent cleanup task
|
|
cancelNonExistResp := client.Post("/api/admin/usage-logs/cleanup/tasks/999999999/cancel", nil)
|
|
if cancelNonExistResp.Code == 0 {
|
|
t.Fatal("expected error when cancelling non-existent cleanup task, got success")
|
|
}
|
|
|
|
// start_time > end_time should fail
|
|
invalidTimeResp := client.Post("/api/admin/usage-logs/cleanup", map[string]any{
|
|
"start_time": "2025-12-31T23:59:59Z",
|
|
"end_time": "2025-01-01T00:00:00Z",
|
|
})
|
|
if invalidTimeResp.Code == 0 {
|
|
t.Fatal("expected error for start_time > end_time, got success")
|
|
}
|
|
}
|