package system import ( "context" "testing" "kra/app/system/biz" ) func TestDictionaryListPreservesPreloadCollectionShapes(t *testing.T) { data := newTransactionTestData(t) ctx := context.Background() repo := &dictionaryRepo{data: data} if err := repo.CreateDictionary(ctx, &biz.Dictionary{Name: "status", Type: "status"}); err != nil { t.Fatal(err) } if err := repo.CreateDictionary(ctx, &biz.Dictionary{Name: "kind", Type: "kind"}); err != nil { t.Fatal(err) } plain, _, err := repo.ListDictionaries(ctx, 1, 1, "", "", false) if err != nil { t.Fatal(err) } if len(plain) != 2 || plain[0].Children == nil || len(plain[0].Children) != 0 { t.Fatalf("ordinary dictionary list children = %#v, want an empty preloaded slice", plain) } if plain[0].Details != nil { t.Fatalf("ordinary dictionary list details = %#v, want nil", plain[0].Details) } withDetails, _, err := repo.ListDictionaries(ctx, 1, 1, "", "", true) if err != nil { t.Fatal(err) } if len(withDetails) != 2 || withDetails[0].Details == nil || len(withDetails[0].Details) != 0 { t.Fatalf("dictionary details preload = %#v, want an empty preloaded slice", withDetails) } if withDetails[0].Children != nil { t.Fatalf("details-only dictionary list children = %#v, want nil", withDetails[0].Children) } } func TestImportDictionaryRejectsDuplicateType(t *testing.T) { data := newTransactionTestData(t) ctx := context.Background() repo := &dictionaryRepo{data: data} if err := repo.CreateDictionary(ctx, &biz.Dictionary{Name: "first", Type: "duplicate"}); err != nil { t.Fatal(err) } if err := repo.ImportDictionary(ctx, &biz.Dictionary{Name: "second", Type: "duplicate"}, nil); err == nil || err.Error() != "存在相同的type,不允许导入" { t.Fatalf("duplicate import error = %v", err) } var count int64 if err := data.gormDB.WithContext(ctx).Model(&dictionaryPO{}).Where("type = ?", "duplicate").Count(&count).Error; err != nil { t.Fatal(err) } if count != 1 { t.Fatalf("duplicate dictionary count = %d, want 1", count) } } func TestDictionaryTreeAndParentQueriesPreserveLoadedChildrenShape(t *testing.T) { data := newTransactionTestData(t) ctx := context.Background() repo := &dictionaryRepo{data: data} dictionary := &biz.Dictionary{Name: "tree", Type: "tree"} if err := repo.CreateDictionary(ctx, dictionary); err != nil { t.Fatal(err) } parent := &biz.DictionaryDetail{Label: "parent", Value: "parent", DictionaryID: dictionary.ID, Sort: 2} if err := repo.CreateDictionaryDetail(ctx, parent); err != nil { t.Fatal(err) } parentID := parent.ID child := &biz.DictionaryDetail{Label: "child", Value: "child", DictionaryID: dictionary.ID, ParentID: &parentID, Sort: 1} if err := repo.CreateDictionaryDetail(ctx, child); err != nil { t.Fatal(err) } tree, err := repo.DictionaryDetailTree(ctx, dictionary.ID, "") if err != nil { t.Fatal(err) } if len(tree) != 1 || len(tree[0].Children) != 1 || tree[0].Children[0].Children == nil { t.Fatalf("dictionary tree = %#v, want recursively loaded child slices", tree) } flat, err := repo.DictionaryDetailsByParent(ctx, dictionary.ID, &parentID, false) if err != nil { t.Fatal(err) } if len(flat) != 1 || flat[0].Children != nil { t.Fatalf("flat parent query = %#v, want nil children", flat) } loaded, err := repo.DictionaryDetailsByParent(ctx, dictionary.ID, &parentID, true) if err != nil { t.Fatal(err) } if len(loaded) != 1 || loaded[0].Children == nil || len(loaded[0].Children) != 0 { t.Fatalf("recursive parent query = %#v, want an empty loaded child slice", loaded) } } func TestDictionaryDetailListAppliesZeroLimit(t *testing.T) { data := newTransactionTestData(t) ctx := context.Background() repo := &dictionaryRepo{data: data} dictionary := &biz.Dictionary{Name: "limited", Type: "limited"} if err := repo.CreateDictionary(ctx, dictionary); err != nil { t.Fatal(err) } if err := repo.CreateDictionaryDetail(ctx, &biz.DictionaryDetail{Label: "one", Value: "one", DictionaryID: dictionary.ID}); err != nil { t.Fatal(err) } items, total, err := repo.ListDictionaryDetails(ctx, 0, 0, biz.DictionaryDetailFilter{DictionaryID: dictionary.ID}) if err != nil { t.Fatal(err) } if total != 1 || len(items) != 0 { t.Fatalf("zero-limit detail list: total=%d items=%#v", total, items) } } func TestUserListAppliesZeroLimitForNegativePageSize(t *testing.T) { data := newTransactionTestData(t) ctx := context.Background() if err := data.gormDB.WithContext(ctx).Create(&userPO{Username: "limited", Password: "hash", AuthorityID: 888, Enable: 1}).Error; err != nil { t.Fatal(err) } items, total, err := (&userRepo{data: data}).ListUsers(ctx, 1, -1, &biz.UserListFilter{}) if err != nil { t.Fatal(err) } if total != 1 || len(items) != 0 { t.Fatalf("negative-size user list: total=%d items=%#v", total, items) } } func TestDepartmentTreeAndFlatResultsPreserveChildrenShape(t *testing.T) { data := newTransactionTestData(t) ctx := context.Background() repo := &departmentRepo{data: data} root := &biz.Department{Name: "root"} if err := repo.CreateDepartment(ctx, root); err != nil { t.Fatal(err) } var rootPO departmentPO if err := data.gormDB.WithContext(ctx).Where("name = ?", "root").First(&rootPO).Error; err != nil { t.Fatal(err) } if err := repo.CreateDepartment(ctx, &biz.Department{Name: "child", ParentID: rootPO.ID}); err != nil { t.Fatal(err) } tree, err := repo.ListDepartments(ctx, "") if err != nil { t.Fatal(err) } if len(tree) != 1 || len(tree[0].Children) != 1 || tree[0].Children[0].Children == nil || len(tree[0].Children[0].Children) != 0 { t.Fatalf("department tree children = %#v, want every loaded node to expose a slice", tree) } flat, err := repo.ListDepartments(ctx, "child") if err != nil { t.Fatal(err) } if len(flat) != 1 || flat[0].Children != nil { t.Fatalf("flat department search children = %#v, want nil", flat) } found, err := repo.FindDepartment(ctx, rootPO.ID) if err != nil { t.Fatal(err) } if found.Children != nil { t.Fatalf("single department children = %#v, want nil", found.Children) } }