410 lines
12 KiB
Go
410 lines
12 KiB
Go
//go:build integration
|
|
|
|
package admin_test
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/qianfree/team-api/tests/integration/admin/testinfra"
|
|
)
|
|
|
|
func TestHelpCategoryList(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
_, cleanup := createTestHelpCategory(t, client)
|
|
defer cleanup()
|
|
|
|
resp := client.Get("/api/admin/help-categories", map[string]string{
|
|
"page": "1",
|
|
"page_size": "10",
|
|
})
|
|
testinfra.AssertPaginatedList(t, resp, 1)
|
|
}
|
|
|
|
func TestHelpCategoryCRUD(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
suffix := randomSuffix()
|
|
originalName := fmt.Sprintf("CRUD分类 %s", suffix)
|
|
|
|
// --- Create ---
|
|
createResp := client.Post("/api/admin/help-categories", map[string]any{
|
|
"name": originalName,
|
|
"slug": fmt.Sprintf("test-category-%s", suffix),
|
|
"description": "集成测试帮助分类",
|
|
"sort_order": 100,
|
|
"is_visible": true,
|
|
})
|
|
createResp.AssertSuccess(t)
|
|
categoryID := createResp.GetID(t)
|
|
defer func() {
|
|
client.Delete(fmt.Sprintf("/api/admin/help-categories/%d", categoryID))
|
|
}()
|
|
|
|
// --- Verify creation via list ---
|
|
listResp := client.Get("/api/admin/help-categories", map[string]string{
|
|
"page": "1",
|
|
"page_size": "50",
|
|
})
|
|
testinfra.AssertPaginatedList(t, listResp, 1)
|
|
|
|
var listData struct {
|
|
List []struct {
|
|
Id int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Slug string `json:"slug"`
|
|
Description string `json:"description"`
|
|
SortOrder int `json:"sort_order"`
|
|
IsVisible bool `json:"is_visible"`
|
|
} `json:"list"`
|
|
}
|
|
listResp.DecodeData(t, &listData)
|
|
|
|
var created *struct {
|
|
Id int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Slug string `json:"slug"`
|
|
Description string `json:"description"`
|
|
SortOrder int `json:"sort_order"`
|
|
IsVisible bool `json:"is_visible"`
|
|
}
|
|
for i := range listData.List {
|
|
if listData.List[i].Id == categoryID {
|
|
created = &listData.List[i]
|
|
break
|
|
}
|
|
}
|
|
if created == nil {
|
|
t.Fatalf("category id=%d not found in list after creation", categoryID)
|
|
}
|
|
if created.Name != originalName {
|
|
t.Fatalf("expected name=%q, got %q", originalName, created.Name)
|
|
}
|
|
if created.SortOrder != 100 {
|
|
t.Fatalf("expected sort_order=100, got %d", created.SortOrder)
|
|
}
|
|
if !created.IsVisible {
|
|
t.Fatal("expected is_visible=true")
|
|
}
|
|
|
|
// --- Update ---
|
|
updatedName := fmt.Sprintf("更新分类 %s", suffix)
|
|
updateResp := client.Put(fmt.Sprintf("/api/admin/help-categories/%d", categoryID), map[string]any{
|
|
"name": updatedName,
|
|
"slug": fmt.Sprintf("updated-category-%s", suffix),
|
|
"description": "更新后的帮助分类描述",
|
|
"sort_order": 200,
|
|
"is_visible": false,
|
|
})
|
|
updateResp.AssertSuccess(t)
|
|
|
|
// --- Verify update via list ---
|
|
verifyResp := client.Get("/api/admin/help-categories", map[string]string{
|
|
"page": "1",
|
|
"page_size": "50",
|
|
})
|
|
verifyResp.AssertSuccess(t)
|
|
|
|
var verifyData struct {
|
|
List []struct {
|
|
Id int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
SortOrder int `json:"sort_order"`
|
|
IsVisible bool `json:"is_visible"`
|
|
} `json:"list"`
|
|
}
|
|
verifyResp.DecodeData(t, &verifyData)
|
|
|
|
var updated *struct {
|
|
Id int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
SortOrder int `json:"sort_order"`
|
|
IsVisible bool `json:"is_visible"`
|
|
}
|
|
for i := range verifyData.List {
|
|
if verifyData.List[i].Id == categoryID {
|
|
updated = &verifyData.List[i]
|
|
break
|
|
}
|
|
}
|
|
if updated == nil {
|
|
t.Fatalf("category id=%d not found after update", categoryID)
|
|
}
|
|
if updated.Name != updatedName {
|
|
t.Fatalf("expected updated name=%q, got %q", updatedName, updated.Name)
|
|
}
|
|
if updated.SortOrder != 200 {
|
|
t.Fatalf("expected sort_order=200 after update, got %d", updated.SortOrder)
|
|
}
|
|
if updated.IsVisible {
|
|
t.Fatal("expected is_visible=false after update")
|
|
}
|
|
|
|
// --- Delete ---
|
|
deleteResp := client.Delete(fmt.Sprintf("/api/admin/help-categories/%d", categoryID))
|
|
deleteResp.AssertSuccess(t)
|
|
|
|
// --- Verify deletion ---
|
|
afterDeleteResp := client.Get("/api/admin/help-categories", map[string]string{
|
|
"page": "1",
|
|
"page_size": "50",
|
|
})
|
|
afterDeleteResp.AssertSuccess(t)
|
|
|
|
var afterDeleteData struct {
|
|
List []struct {
|
|
Id int64 `json:"id"`
|
|
} `json:"list"`
|
|
}
|
|
afterDeleteResp.DecodeData(t, &afterDeleteData)
|
|
|
|
for _, item := range afterDeleteData.List {
|
|
if item.Id == categoryID {
|
|
t.Fatal("deleted category should not appear in list")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHelpArticleList(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
_, catCleanup := createTestHelpCategory(t, client)
|
|
defer catCleanup()
|
|
|
|
// List articles (may be empty if no articles exist)
|
|
resp := client.Get("/api/admin/help-articles", map[string]string{
|
|
"page": "1",
|
|
"page_size": "10",
|
|
})
|
|
testinfra.AssertPaginatedList(t, resp, 0)
|
|
}
|
|
|
|
func TestHelpArticleCRUD(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
suffix := randomSuffix()
|
|
|
|
// Create a category first
|
|
catResp := client.Post("/api/admin/help-categories", map[string]any{
|
|
"name": fmt.Sprintf("文章分类 %s", suffix),
|
|
"slug": fmt.Sprintf("article-cat-%s", suffix),
|
|
"sort_order": 50,
|
|
"is_visible": true,
|
|
})
|
|
catResp.AssertSuccess(t)
|
|
categoryID := catResp.GetID(t)
|
|
defer func() {
|
|
client.Delete(fmt.Sprintf("/api/admin/help-categories/%d", categoryID))
|
|
}()
|
|
|
|
// --- Create article ---
|
|
originalTitle := fmt.Sprintf("CRUD测试文章 %s", suffix)
|
|
createResp := client.Post("/api/admin/help-articles", map[string]any{
|
|
"category_id": categoryID,
|
|
"title": originalTitle,
|
|
"slug": fmt.Sprintf("test-article-%s", suffix),
|
|
"content": "这是集成测试帮助文章的正文内容",
|
|
"summary": "测试文章摘要",
|
|
"status": "draft",
|
|
"sort_order": 10,
|
|
"keywords": []string{"测试", "帮助"},
|
|
})
|
|
createResp.AssertSuccess(t)
|
|
articleID := createResp.GetID(t)
|
|
defer func() {
|
|
client.Delete(fmt.Sprintf("/api/admin/help-articles/%d", articleID))
|
|
}()
|
|
|
|
// --- Verify creation via article detail ---
|
|
detailResp := client.Get(fmt.Sprintf("/api/admin/help-articles/%d", articleID), nil)
|
|
detailResp.AssertSuccess(t)
|
|
|
|
var detail struct {
|
|
Id int64 `json:"id"`
|
|
CategoryId int64 `json:"category_id"`
|
|
Title string `json:"title"`
|
|
Slug string `json:"slug"`
|
|
Content string `json:"content"`
|
|
Summary string `json:"summary"`
|
|
Status string `json:"status"`
|
|
SortOrder int `json:"sort_order"`
|
|
Keywords []string `json:"keywords"`
|
|
}
|
|
detailResp.DecodeData(t, &detail)
|
|
|
|
if detail.Id != articleID {
|
|
t.Fatalf("expected id=%d, got %d", articleID, detail.Id)
|
|
}
|
|
if detail.CategoryId != categoryID {
|
|
t.Fatalf("expected category_id=%d, got %d", categoryID, detail.CategoryId)
|
|
}
|
|
if detail.Title != originalTitle {
|
|
t.Fatalf("expected title=%q, got %q", originalTitle, detail.Title)
|
|
}
|
|
if detail.Status != "draft" {
|
|
t.Fatalf("new article should be draft, got %q", detail.Status)
|
|
}
|
|
if detail.SortOrder != 10 {
|
|
t.Fatalf("expected sort_order=10, got %d", detail.SortOrder)
|
|
}
|
|
if len(detail.Keywords) != 2 {
|
|
t.Fatalf("expected 2 keywords, got %d", len(detail.Keywords))
|
|
}
|
|
|
|
// --- Verify creation via list filter ---
|
|
listResp := client.Get("/api/admin/help-articles", map[string]string{
|
|
"category_id": fmt.Sprintf("%d", categoryID),
|
|
"page": "1",
|
|
"page_size": "50",
|
|
})
|
|
testinfra.AssertPaginatedList(t, listResp, 1)
|
|
|
|
var listData struct {
|
|
List []struct {
|
|
Id int64 `json:"id"`
|
|
Title string `json:"title"`
|
|
Status string `json:"status"`
|
|
} `json:"list"`
|
|
}
|
|
listResp.DecodeData(t, &listData)
|
|
|
|
found := false
|
|
for _, item := range listData.List {
|
|
if item.Id == articleID {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatal("created article not found in filtered list")
|
|
}
|
|
|
|
// --- Update article ---
|
|
updatedTitle := fmt.Sprintf("更新文章 %s", suffix)
|
|
updateResp := client.Put(fmt.Sprintf("/api/admin/help-articles/%d", articleID), map[string]any{
|
|
"category_id": categoryID,
|
|
"title": updatedTitle,
|
|
"slug": fmt.Sprintf("updated-article-%s", suffix),
|
|
"content": "更新后的文章正文",
|
|
"summary": "更新后的摘要",
|
|
"status": "published",
|
|
"sort_order": 20,
|
|
"keywords": []string{"更新", "测试"},
|
|
})
|
|
updateResp.AssertSuccess(t)
|
|
|
|
// --- Verify update via detail ---
|
|
verifyResp := client.Get(fmt.Sprintf("/api/admin/help-articles/%d", articleID), nil)
|
|
verifyResp.AssertSuccess(t)
|
|
|
|
var verifyDetail struct {
|
|
Title string `json:"title"`
|
|
Content string `json:"content"`
|
|
Summary string `json:"summary"`
|
|
Status string `json:"status"`
|
|
SortOrder int `json:"sort_order"`
|
|
Keywords []string `json:"keywords"`
|
|
}
|
|
verifyResp.DecodeData(t, &verifyDetail)
|
|
|
|
if verifyDetail.Title != updatedTitle {
|
|
t.Fatalf("expected updated title=%q, got %q", updatedTitle, verifyDetail.Title)
|
|
}
|
|
if verifyDetail.Status != "published" {
|
|
t.Fatalf("expected status=published after update, got %q", verifyDetail.Status)
|
|
}
|
|
if verifyDetail.SortOrder != 20 {
|
|
t.Fatalf("expected sort_order=20 after update, got %d", verifyDetail.SortOrder)
|
|
}
|
|
if len(verifyDetail.Keywords) != 2 {
|
|
t.Fatalf("expected 2 keywords after update, got %d", len(verifyDetail.Keywords))
|
|
}
|
|
|
|
// --- Verify status filter works ---
|
|
publishedResp := client.Get("/api/admin/help-articles", map[string]string{
|
|
"category_id": fmt.Sprintf("%d", categoryID),
|
|
"status": "published",
|
|
"page": "1",
|
|
"page_size": "50",
|
|
})
|
|
publishedResp.AssertSuccess(t)
|
|
|
|
// --- Delete ---
|
|
deleteResp := client.Delete(fmt.Sprintf("/api/admin/help-articles/%d", articleID))
|
|
deleteResp.AssertSuccess(t)
|
|
|
|
// --- Verify deletion via list ---
|
|
afterDeleteResp := client.Get("/api/admin/help-articles", map[string]string{
|
|
"category_id": fmt.Sprintf("%d", categoryID),
|
|
"page": "1",
|
|
"page_size": "50",
|
|
})
|
|
afterDeleteResp.AssertSuccess(t)
|
|
|
|
var afterDeleteData struct {
|
|
List []struct {
|
|
Id int64 `json:"id"`
|
|
} `json:"list"`
|
|
}
|
|
afterDeleteResp.DecodeData(t, &afterDeleteData)
|
|
|
|
for _, item := range afterDeleteData.List {
|
|
if item.Id == articleID {
|
|
t.Fatal("deleted article should not appear in list")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHelpCenterNegative(t *testing.T) {
|
|
client := testinfra.GetAuthedClient(t)
|
|
|
|
// Create category with missing required fields
|
|
missingCatResp := client.Post("/api/admin/help-categories", map[string]any{})
|
|
if missingCatResp.Code == 0 {
|
|
t.Fatal("expected error for missing category fields, got success")
|
|
}
|
|
|
|
// Create article with non-existent category
|
|
invalidArticleResp := client.Post("/api/admin/help-articles", map[string]any{
|
|
"category_id": 999999999,
|
|
"title": "Invalid Article",
|
|
"slug": "invalid-article",
|
|
"content": "test",
|
|
})
|
|
if invalidArticleResp.Code == 0 {
|
|
t.Fatal("expected error for non-existent category_id, got success")
|
|
}
|
|
|
|
// Get non-existent article detail
|
|
getNonExistResp := client.Get("/api/admin/help-articles/999999999", nil)
|
|
if getNonExistResp.Code == 0 {
|
|
t.Fatal("expected error for non-existent article, got success")
|
|
}
|
|
|
|
// Delete non-existent category
|
|
deleteNonExistResp := client.Delete("/api/admin/help-categories/999999999")
|
|
if deleteNonExistResp.Code == 0 {
|
|
t.Fatal("expected error for deleting non-existent category, got success")
|
|
}
|
|
}
|
|
|
|
// createTestHelpCategory is a test helper that creates a help category and returns its ID and cleanup.
|
|
func createTestHelpCategory(t *testing.T, client *testinfra.APIClient) (int64, func()) {
|
|
t.Helper()
|
|
suffix := randomSuffix()
|
|
resp := client.Post("/api/admin/help-categories", map[string]any{
|
|
"name": fmt.Sprintf("测试分类 %s", suffix),
|
|
"slug": fmt.Sprintf("test-cat-%s", suffix),
|
|
"sort_order": 100,
|
|
"is_visible": true,
|
|
})
|
|
resp.AssertSuccess(t)
|
|
id := resp.GetID(t)
|
|
return id, func() {
|
|
client.Delete(fmt.Sprintf("/api/admin/help-categories/%d", id))
|
|
}
|
|
}
|