You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
6.3 KiB
269 lines
6.3 KiB
package model
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"gorm.io/driver/mysql"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// setupMenuTestDB 创建菜单测试数据库(使用MySQL)
|
|
func setupMenuTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
|
|
dsn := "root:dev123456@tcp(219.159.132.177:17173)/base?charset=utf8mb4&parseTime=true&loc=Local"
|
|
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
|
require.NoError(t, err)
|
|
|
|
err = db.AutoMigrate(&Menu{})
|
|
require.NoError(t, err)
|
|
|
|
// 清理所有数据确保测试隔离(运行后需重启后端以恢复种子数据)
|
|
db.Exec("SET FOREIGN_KEY_CHECKS = 0")
|
|
db.Exec("TRUNCATE TABLE menu")
|
|
db.Exec("SET FOREIGN_KEY_CHECKS = 1")
|
|
|
|
return db
|
|
}
|
|
|
|
// createTestMenu 创建测试菜单
|
|
func createTestMenu(t *testing.T, db *gorm.DB) *Menu {
|
|
t.Helper()
|
|
|
|
now := time.Now()
|
|
menu := &Menu{
|
|
Name: "测试菜单",
|
|
Path: "/test",
|
|
Icon: "Star",
|
|
Type: "config",
|
|
SortOrder: 1,
|
|
Visible: true,
|
|
Status: 1,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
|
|
err := db.Create(menu).Error
|
|
require.NoError(t, err)
|
|
|
|
return menu
|
|
}
|
|
|
|
// TestMenuInsert 测试插入菜单
|
|
func TestMenuInsert(t *testing.T) {
|
|
db := setupMenuTestDB(t)
|
|
|
|
ctx := context.Background()
|
|
menu := &Menu{
|
|
Name: "新菜单",
|
|
Path: "/new",
|
|
Icon: "Plus",
|
|
Type: "config",
|
|
SortOrder: 5,
|
|
Visible: true,
|
|
Status: 1,
|
|
}
|
|
|
|
id, err := MenuInsert(ctx, db, menu)
|
|
|
|
require.NoError(t, err)
|
|
assert.Greater(t, id, int64(0))
|
|
assert.Equal(t, id, menu.Id)
|
|
|
|
// 验证数据已保存
|
|
saved, err := MenuFindOne(ctx, db, id)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "新菜单", saved.Name)
|
|
assert.Equal(t, "/new", saved.Path)
|
|
assert.Equal(t, "Plus", saved.Icon)
|
|
assert.Equal(t, 5, saved.SortOrder)
|
|
}
|
|
|
|
// TestMenuFindOne 测试根据ID查询菜单
|
|
func TestMenuFindOne(t *testing.T) {
|
|
db := setupMenuTestDB(t)
|
|
|
|
menu := createTestMenu(t, db)
|
|
ctx := context.Background()
|
|
|
|
found, err := MenuFindOne(ctx, db, menu.Id)
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, found)
|
|
assert.Equal(t, menu.Id, found.Id)
|
|
assert.Equal(t, "测试菜单", found.Name)
|
|
assert.Equal(t, "/test", found.Path)
|
|
assert.Equal(t, "Star", found.Icon)
|
|
}
|
|
|
|
// TestMenuFindOne_NotFound 测试查询不存在的菜单
|
|
func TestMenuFindOne_NotFound(t *testing.T) {
|
|
db := setupMenuTestDB(t)
|
|
|
|
ctx := context.Background()
|
|
|
|
found, err := MenuFindOne(ctx, db, 99999)
|
|
|
|
require.Error(t, err)
|
|
require.Nil(t, found)
|
|
assert.Equal(t, ErrNotFound, err)
|
|
}
|
|
|
|
// TestMenuFindAll 测试查询所有启用的菜单
|
|
func TestMenuFindAll(t *testing.T) {
|
|
db := setupMenuTestDB(t)
|
|
ctx := context.Background()
|
|
|
|
// 创建3个菜单:2个启用,1个禁用
|
|
now := time.Now()
|
|
menus := []Menu{
|
|
{Name: "菜单A", Path: "/a", SortOrder: 2, Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "菜单B", Path: "/b", SortOrder: 1, Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "菜单C", Path: "/c", SortOrder: 3, Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
}
|
|
|
|
for i := range menus {
|
|
err := db.Create(&menus[i]).Error
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// 将菜单C设为禁用(status=0是零值,GORM Create时会使用default:1,需要单独更新)
|
|
db.Model(&menus[2]).Update("status", 0)
|
|
|
|
// 查询所有启用的菜单
|
|
result, err := MenuFindAll(ctx, db)
|
|
|
|
require.NoError(t, err)
|
|
assert.Len(t, result, 2)
|
|
|
|
// 验证按 sort_order 排序
|
|
assert.Equal(t, "菜单B", result[0].Name) // sort_order=1
|
|
assert.Equal(t, "菜单A", result[1].Name) // sort_order=2
|
|
}
|
|
|
|
// TestMenuFindByIds 测试根据ID列表查询菜单
|
|
func TestMenuFindByIds(t *testing.T) {
|
|
db := setupMenuTestDB(t)
|
|
ctx := context.Background()
|
|
|
|
// 创建3个菜单
|
|
now := time.Now()
|
|
menus := []Menu{
|
|
{Name: "菜单1", Path: "/1", SortOrder: 1, Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "菜单2", Path: "/2", SortOrder: 2, Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "菜单3", Path: "/3", SortOrder: 3, Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
}
|
|
|
|
for i := range menus {
|
|
err := db.Create(&menus[i]).Error
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// 查询其中2个
|
|
ids := []int64{menus[0].Id, menus[2].Id}
|
|
result, err := MenuFindByIds(ctx, db, ids)
|
|
|
|
require.NoError(t, err)
|
|
assert.Len(t, result, 2)
|
|
assert.Equal(t, "菜单1", result[0].Name)
|
|
assert.Equal(t, "菜单3", result[1].Name)
|
|
}
|
|
|
|
// TestMenuUpdate 测试更新菜单
|
|
func TestMenuUpdate(t *testing.T) {
|
|
db := setupMenuTestDB(t)
|
|
|
|
menu := createTestMenu(t, db)
|
|
ctx := context.Background()
|
|
|
|
// 修改菜单数据
|
|
menu.Name = "更新后的菜单"
|
|
menu.Path = "/updated"
|
|
|
|
err := MenuUpdate(ctx, db, menu)
|
|
|
|
require.NoError(t, err)
|
|
|
|
// 验证更新结果
|
|
updated, err := MenuFindOne(ctx, db, menu.Id)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "更新后的菜单", updated.Name)
|
|
assert.Equal(t, "/updated", updated.Path)
|
|
}
|
|
|
|
// TestMenuDelete 测试删除菜单
|
|
func TestMenuDelete(t *testing.T) {
|
|
db := setupMenuTestDB(t)
|
|
|
|
menu := createTestMenu(t, db)
|
|
menuId := menu.Id
|
|
ctx := context.Background()
|
|
|
|
err := MenuDelete(ctx, db, menuId)
|
|
|
|
require.NoError(t, err)
|
|
|
|
// 验证菜单已被删除
|
|
_, err = MenuFindOne(ctx, db, menuId)
|
|
require.Error(t, err)
|
|
assert.Equal(t, ErrNotFound, err)
|
|
}
|
|
|
|
// TestMenuHasChildren 测试检查菜单是否有子菜单
|
|
func TestMenuHasChildren(t *testing.T) {
|
|
db := setupMenuTestDB(t)
|
|
ctx := context.Background()
|
|
|
|
now := time.Now()
|
|
|
|
// 创建父菜单
|
|
parent := &Menu{
|
|
Name: "父菜单",
|
|
Path: "/parent",
|
|
SortOrder: 1,
|
|
Status: 1,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
err := db.Create(parent).Error
|
|
require.NoError(t, err)
|
|
|
|
// 创建子菜单
|
|
child := &Menu{
|
|
ParentId: parent.Id,
|
|
Name: "子菜单",
|
|
Path: "/parent/child",
|
|
SortOrder: 1,
|
|
Status: 1,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
err = db.Create(child).Error
|
|
require.NoError(t, err)
|
|
|
|
// 创建无子菜单的孤立菜单
|
|
orphan := &Menu{
|
|
Name: "孤立菜单",
|
|
Path: "/orphan",
|
|
SortOrder: 1,
|
|
Status: 1,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
err = db.Create(orphan).Error
|
|
require.NoError(t, err)
|
|
|
|
// 验证父菜单有子菜单
|
|
hasChildren, err := MenuHasChildren(ctx, db, parent.Id)
|
|
require.NoError(t, err)
|
|
assert.True(t, hasChildren)
|
|
|
|
// 验证孤立菜单没有子菜单
|
|
hasChildren, err = MenuHasChildren(ctx, db, orphan.Id)
|
|
require.NoError(t, err)
|
|
assert.False(t, hasChildren)
|
|
}
|
|
|