241 lines
6.0 KiB
Go
241 lines
6.0 KiB
Go
//go:build integration
|
|
|
|
package admin_test
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/qianfree/team-api/tests/integration/admin/testinfra"
|
|
)
|
|
|
|
func TestSettingsCategories(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
resp := client.Get("/api/admin/settings/categories", nil)
|
|
resp.AssertSuccess(t)
|
|
|
|
var data struct {
|
|
List []struct {
|
|
Key string `json:"key"`
|
|
Label string `json:"label"`
|
|
Icon string `json:"icon"`
|
|
Order int `json:"order"`
|
|
} `json:"list"`
|
|
}
|
|
resp.DecodeData(t, &data)
|
|
|
|
if len(data.List) == 0 {
|
|
t.Fatal("expected at least one settings category")
|
|
}
|
|
|
|
for _, cat := range data.List {
|
|
if cat.Key == "" {
|
|
t.Fatal("settings category key should not be empty")
|
|
}
|
|
if cat.Label == "" {
|
|
t.Fatalf("category %s has empty label", cat.Key)
|
|
}
|
|
}
|
|
|
|
t.Logf("Settings categories returned %d entries", len(data.List))
|
|
}
|
|
|
|
func TestSettingsGet(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
category := getFirstSettingsCategory(t, client)
|
|
if category == "" {
|
|
return
|
|
}
|
|
|
|
resp := client.Get(fmt.Sprintf("/api/admin/settings/%s", category), nil)
|
|
resp.AssertSuccess(t)
|
|
|
|
var data struct {
|
|
List []struct {
|
|
Key string `json:"key"`
|
|
Value any `json:"value"`
|
|
Type string `json:"type"`
|
|
Label string `json:"label"`
|
|
Description string `json:"description"`
|
|
Sensitive bool `json:"sensitive"`
|
|
Validation string `json:"validation"`
|
|
Default any `json:"default"`
|
|
} `json:"list"`
|
|
}
|
|
resp.DecodeData(t, &data)
|
|
|
|
if len(data.List) == 0 {
|
|
t.Fatalf("settings category %q returned empty list", category)
|
|
}
|
|
|
|
for _, item := range data.List {
|
|
if item.Key == "" {
|
|
t.Fatal("setting key should not be empty")
|
|
}
|
|
if item.Type == "" {
|
|
t.Fatalf("setting %s has empty type", item.Key)
|
|
}
|
|
if item.Label == "" {
|
|
t.Fatalf("setting %s has empty label", item.Key)
|
|
}
|
|
}
|
|
|
|
t.Logf("Settings for category %q returned %d entries", category, len(data.List))
|
|
}
|
|
|
|
func TestSettingsUpdateAndVerify(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
category := getFirstSettingsCategory(t, client)
|
|
if category == "" {
|
|
return
|
|
}
|
|
|
|
// Get current settings
|
|
getResp := client.Get(fmt.Sprintf("/api/admin/settings/%s", category), nil)
|
|
getResp.AssertSuccess(t)
|
|
|
|
var getData struct {
|
|
List []struct {
|
|
Key string `json:"key"`
|
|
Value any `json:"value"`
|
|
Type string `json:"type"`
|
|
Sensitive bool `json:"sensitive"`
|
|
} `json:"list"`
|
|
}
|
|
getResp.DecodeData(t, &getData)
|
|
|
|
if len(getData.List) == 0 {
|
|
t.Skipf("No settings found in category %q", category)
|
|
}
|
|
|
|
// Find a non-sensitive string setting to test with
|
|
var targetKey string
|
|
var originalValue any
|
|
for _, item := range getData.List {
|
|
if !item.Sensitive && (item.Type == "string" || item.Type == "text") {
|
|
targetKey = item.Key
|
|
originalValue = item.Value
|
|
break
|
|
}
|
|
}
|
|
|
|
if targetKey == "" {
|
|
t.Skipf("No non-sensitive string setting found in category %q, skipping update verification", category)
|
|
}
|
|
|
|
// Update with a new value
|
|
newValue := "integration-test-value"
|
|
settings := make(map[string]any)
|
|
for _, item := range getData.List {
|
|
settings[item.Key] = item.Value
|
|
}
|
|
settings[targetKey] = newValue
|
|
|
|
updateResp := client.Put(fmt.Sprintf("/api/admin/settings/%s", category), map[string]any{
|
|
"settings": settings,
|
|
})
|
|
updateResp.AssertSuccess(t)
|
|
|
|
// Verify the value was persisted by reading it back
|
|
verifyResp := client.Get(fmt.Sprintf("/api/admin/settings/%s", category), nil)
|
|
verifyResp.AssertSuccess(t)
|
|
|
|
var verifyData struct {
|
|
List []struct {
|
|
Key string `json:"key"`
|
|
Value any `json:"value"`
|
|
} `json:"list"`
|
|
}
|
|
verifyResp.DecodeData(t, &verifyData)
|
|
|
|
for _, item := range verifyData.List {
|
|
if item.Key == targetKey {
|
|
if item.Value != newValue {
|
|
t.Fatalf("expected setting %q=%q after update, got %v", targetKey, newValue, item.Value)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
|
|
// Restore original value
|
|
settings[targetKey] = originalValue
|
|
restoreResp := client.Put(fmt.Sprintf("/api/admin/settings/%s", category), map[string]any{
|
|
"settings": settings,
|
|
})
|
|
restoreResp.AssertSuccess(t)
|
|
|
|
t.Logf("Settings update verified: %q changed from %v to %q and restored", targetKey, originalValue, newValue)
|
|
}
|
|
|
|
func TestSettingsSensitiveFieldMasking(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
// Check all categories for sensitive fields
|
|
catResp := client.Get("/api/admin/settings/categories", nil)
|
|
catResp.AssertSuccess(t)
|
|
|
|
var catData struct {
|
|
List []struct {
|
|
Key string `json:"key"`
|
|
} `json:"list"`
|
|
}
|
|
catResp.DecodeData(t, &catData)
|
|
|
|
for _, cat := range catData.List {
|
|
resp := client.Get(fmt.Sprintf("/api/admin/settings/%s", cat.Key), nil)
|
|
resp.AssertSuccess(t)
|
|
|
|
var data struct {
|
|
List []struct {
|
|
Key string `json:"key"`
|
|
Sensitive bool `json:"sensitive"`
|
|
Value any `json:"value"`
|
|
} `json:"list"`
|
|
}
|
|
resp.DecodeData(t, &data)
|
|
|
|
for _, item := range data.List {
|
|
if item.Sensitive {
|
|
// Sensitive fields should not expose raw values
|
|
if strVal, ok := item.Value.(string); ok && len(strVal) > 4 {
|
|
// Value might be masked (e.g., "****1234" or similar)
|
|
t.Logf("Sensitive field %q in category %q: value present (length=%d)", item.Key, cat.Key, len(strVal))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSettingsNonExistentCategory(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
resp := client.Get("/api/admin/settings/nonexistent_category_xyz", nil)
|
|
if resp.Code == 0 {
|
|
t.Fatal("expected error for non-existent settings category, got success")
|
|
}
|
|
|
|
t.Logf("Non-existent category correctly rejected: code=%d, message=%s", resp.Code, resp.Message)
|
|
}
|
|
|
|
// getFirstSettingsCategory returns the key of the first settings category, or empty string if none.
|
|
func getFirstSettingsCategory(t *testing.T, client *testinfra.APIClient) string {
|
|
t.Helper()
|
|
catResp := client.Get("/api/admin/settings/categories", nil)
|
|
catResp.AssertSuccess(t)
|
|
|
|
var catData struct {
|
|
List []struct {
|
|
Key string `json:"key"`
|
|
} `json:"list"`
|
|
}
|
|
catResp.DecodeData(t, &catData)
|
|
|
|
if len(catData.List) == 0 {
|
|
t.Skip("No settings categories found")
|
|
}
|
|
return catData.List[0].Key
|
|
}
|