1package hub_test23import (4 "testing"56 "gno.land/p/gnoland/boards/exts/hub/v0"7 "gno.land/p/gnoland/boards/exts/permissions/v0"8 "gno.land/p/gnoland/boards/v0"9 "gno.land/p/nt/urequire/v0"10)1112func TestNewSafeBoard(t *testing.T) {13 tests := []struct {14 name string15 setup func() *boards.Board16 threadCount, memberCount int17 createdAt int6418 }{19 {20 name: "new board",21 setup: func() *boards.Board { return boards.New(1) },22 createdAt: testTime,23 },24 {25 name: "with threads",26 setup: func() *boards.Board {27 b := boards.New(1)28 b.Threads.Add(boards.MustNewThread(b, alice, "Title 1", "Body 1"))29 b.Threads.Add(boards.MustNewThread(b, bob, "Title 2", "Body 2"))30 return b31 },32 threadCount: 2,33 createdAt: testTime,34 },35 {36 name: "with members",37 setup: func() *boards.Board {38 b := boards.New(1)39 perms := permissions.New()40 perms.SetUserRoles(alice)41 perms.SetUserRoles(bob)42 b.Permissions = perms43 return b44 },45 memberCount: 2,46 createdAt: testTime,47 },48 {49 // A board with no storages assigned must not panic: the counts50 // are skipped and the zero creation time maps to a zero Unix time.51 name: "bare board without storages",52 setup: func() *boards.Board { return &boards.Board{ID: 1} },53 },54 }5556 for _, tt := range tests {57 t.Run(tt.name, func(t *testing.T) {58 ref := tt.setup()59 ref.Name = "test123"60 ref.Creator = alice6162 board := hub.NewSafeBoard(ref)6364 urequire.Equal(t, uint64(1), board.ID(), "expect ID to match")65 urequire.Equal(t, "test123", board.Name(), "expect name to match")66 urequire.Equal(t, alice, board.Creator(), "expect creator to match")67 urequire.False(t, board.Readonly(), "expect board not to be readonly")68 urequire.Equal(t, tt.threadCount, board.ThreadCount(), "expect thread count to match")69 urequire.Equal(t, tt.memberCount, board.MemberCount(), "expect member count to match")70 urequire.Equal(t, tt.createdAt, board.CreatedAt(), "expect creation time to match")71 urequire.Equal(t, int64(0), board.UpdatedAt(), "expect zero update time to map to zero")72 })73 }74}7576// TestNewSafeBoardSnapshotsAliases asserts the invariant this package exists77// for: a safe type is a snapshot, so later writes to the source board must not78// be observable through a value already handed to a caller.79func TestNewSafeBoardSnapshotsAliases(t *testing.T) {80 ref := boards.New(1)81 ref.Name = "current"82 ref.Aliases = []string{"previous"}8384 board := hub.NewSafeBoard(ref)8586 ref.Aliases[0] = "mutated"87 ref.Aliases = append(ref.Aliases, "added")88 ref.Name = "renamed"89 ref.Readonly = true9091 aliases := board.Aliases()92 urequire.Equal(t, 1, len(aliases), "expect alias count to be unaffected")93 urequire.Equal(t, "previous", aliases[0], "expect alias to be unaffected")94 urequire.Equal(t, "current", board.Name(), "expect name to be unaffected")95 urequire.False(t, board.Readonly(), "expect readonly to be unaffected")96}9798func TestNewSafeBoardNilRef(cur realm, t *testing.T) {99 urequire.PanicsWithMessage(t, cur, "board reference is nil", func() {100 hub.NewSafeBoard(nil)101 }, "expect a nil board reference to be rejected")102}103Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.