Stash bunch of broken generated test with shitty broken mocking
This commit is contained in:
		
							
								
								
									
										18
									
								
								game/chat.go
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								game/chat.go
									
									
									
									
									
								
							| @ -25,12 +25,14 @@ type Chat struct { | |||||||
| 	cursorPos    int | 	cursorPos    int | ||||||
| 	scrollOffset int | 	scrollOffset int | ||||||
| 	userData     interface{} | 	userData     interface{} | ||||||
|  | 	input        InputHandler | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewChat() *Chat { | func NewChat() *Chat { | ||||||
| 	return &Chat{ | 	return &Chat{ | ||||||
| 		messages:    make([]types.ChatMessage, 0, maxMessages), | 		messages:    make([]types.ChatMessage, 0, maxMessages), | ||||||
| 		inputBuffer: make([]rune, 0, runeLimit), | 		inputBuffer: make([]rune, 0, runeLimit), | ||||||
|  | 		input:       &RaylibInput{}, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -153,23 +155,23 @@ func (c *Chat) Update() (string, bool) { | |||||||
| 			c.scrollOffset = clamp(c.scrollOffset-int(wheelMove), 0, maxScroll) | 			c.scrollOffset = clamp(c.scrollOffset-int(wheelMove), 0, maxScroll) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if rl.IsKeyPressed(rl.KeyT) { | 		if c.input.IsKeyPressed(rl.KeyT) { | ||||||
| 			c.isTyping = true | 			c.isTyping = true | ||||||
| 			return "", false | 			return "", false | ||||||
| 		} | 		} | ||||||
| 		return "", false | 		return "", false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	key := rl.GetCharPressed() | 	key := c.input.GetCharPressed() | ||||||
| 	for key > 0 { | 	for key > 0 { | ||||||
| 		if len(c.inputBuffer) < runeLimit { | 		if len(c.inputBuffer) < runeLimit { | ||||||
| 			c.inputBuffer = append(c.inputBuffer[:c.cursorPos], append([]rune{key}, c.inputBuffer[c.cursorPos:]...)...) | 			c.inputBuffer = append(c.inputBuffer[:c.cursorPos], append([]rune{key}, c.inputBuffer[c.cursorPos:]...)...) | ||||||
| 			c.cursorPos++ | 			c.cursorPos++ | ||||||
| 		} | 		} | ||||||
| 		key = rl.GetCharPressed() | 		key = c.input.GetCharPressed() | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if rl.IsKeyPressed(rl.KeyEnter) || rl.IsKeyPressed(rl.KeyKpEnter) { | 	if c.input.IsKeyPressed(rl.KeyEnter) || c.input.IsKeyPressed(rl.KeyKpEnter) { | ||||||
| 		if len(c.inputBuffer) > 0 { | 		if len(c.inputBuffer) > 0 { | ||||||
| 			message := string(c.inputBuffer) | 			message := string(c.inputBuffer) | ||||||
| 			c.inputBuffer = c.inputBuffer[:0] | 			c.inputBuffer = c.inputBuffer[:0] | ||||||
| @ -180,21 +182,21 @@ func (c *Chat) Update() (string, bool) { | |||||||
| 		c.isTyping = false | 		c.isTyping = false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if rl.IsKeyPressed(rl.KeyEscape) && c.isTyping { | 	if c.input.IsKeyPressed(rl.KeyEscape) && c.isTyping { | ||||||
| 		c.inputBuffer = c.inputBuffer[:0] | 		c.inputBuffer = c.inputBuffer[:0] | ||||||
| 		c.cursorPos = 0 | 		c.cursorPos = 0 | ||||||
| 		c.isTyping = false | 		c.isTyping = false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if rl.IsKeyPressed(rl.KeyBackspace) && c.cursorPos > 0 { | 	if c.input.IsKeyPressed(rl.KeyBackspace) && c.cursorPos > 0 { | ||||||
| 		c.inputBuffer = append(c.inputBuffer[:c.cursorPos-1], c.inputBuffer[c.cursorPos:]...) | 		c.inputBuffer = append(c.inputBuffer[:c.cursorPos-1], c.inputBuffer[c.cursorPos:]...) | ||||||
| 		c.cursorPos-- | 		c.cursorPos-- | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if rl.IsKeyPressed(rl.KeyLeft) && c.cursorPos > 0 { | 	if c.input.IsKeyPressed(rl.KeyLeft) && c.cursorPos > 0 { | ||||||
| 		c.cursorPos-- | 		c.cursorPos-- | ||||||
| 	} | 	} | ||||||
| 	if rl.IsKeyPressed(rl.KeyRight) && c.cursorPos < len(c.inputBuffer) { | 	if c.input.IsKeyPressed(rl.KeyRight) && c.cursorPos < len(c.inputBuffer) { | ||||||
| 		c.cursorPos++ | 		c.cursorPos++ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										106
									
								
								game/chat_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								game/chat_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | |||||||
|  | package game | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/game/testutils" | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/types" | ||||||
|  | 	pb "gitea.boner.be/bdnugget/goonserver/actions" | ||||||
|  | 	rl "github.com/gen2brain/raylib-go/raylib" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestChat_AddMessage(t *testing.T) { | ||||||
|  | 	chat := NewChat() | ||||||
|  |  | ||||||
|  | 	// Test adding single message | ||||||
|  | 	chat.AddMessage(1, "Hello") | ||||||
|  | 	assert.Equal(t, 1, len(chat.messages)) | ||||||
|  | 	assert.Equal(t, int32(1), chat.messages[0].PlayerID) | ||||||
|  | 	assert.Equal(t, "Hello", chat.messages[0].Content) | ||||||
|  |  | ||||||
|  | 	// Test message limit | ||||||
|  | 	for i := 0; i < maxMessages+10; i++ { | ||||||
|  | 		chat.AddMessage(1, "spam") | ||||||
|  | 	} | ||||||
|  | 	assert.Equal(t, maxMessages, len(chat.messages)) | ||||||
|  | 	assert.Equal(t, "spam", chat.messages[len(chat.messages)-1].Content) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestChat_HandleServerMessages(t *testing.T) { | ||||||
|  | 	chat := NewChat() | ||||||
|  | 	mockGame := &Game{ | ||||||
|  | 		Player: &types.Player{ID: 1}, | ||||||
|  | 		OtherPlayers: map[int32]*types.Player{ | ||||||
|  | 			2: {ID: 2}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	chat.userData = mockGame | ||||||
|  |  | ||||||
|  | 	messages := []*pb.ChatMessage{ | ||||||
|  | 		{ | ||||||
|  | 			PlayerId:  1, | ||||||
|  | 			Username:  "player1", | ||||||
|  | 			Content:   "test1", | ||||||
|  | 			Timestamp: time.Now().UnixNano(), | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			PlayerId:  2, | ||||||
|  | 			Username:  "player2", | ||||||
|  | 			Content:   "test2", | ||||||
|  | 			Timestamp: time.Now().UnixNano(), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	chat.HandleServerMessages(messages) | ||||||
|  | 	assert.Equal(t, 2, len(chat.messages)) | ||||||
|  | 	assert.Equal(t, "test1", chat.messages[0].Content) | ||||||
|  | 	assert.Equal(t, "test2", chat.messages[1].Content) | ||||||
|  |  | ||||||
|  | 	// Test duplicate message prevention | ||||||
|  | 	chat.HandleServerMessages(messages) | ||||||
|  | 	assert.Equal(t, 2, len(chat.messages)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestChat_Update(t *testing.T) { | ||||||
|  | 	t.Parallel() | ||||||
|  | 	done := make(chan bool) | ||||||
|  | 	go func() { | ||||||
|  | 		game, cleanup := setupTestEnvironment(t) | ||||||
|  | 		defer cleanup() | ||||||
|  |  | ||||||
|  | 		chat := game.Chat | ||||||
|  |  | ||||||
|  | 		// Test starting chat | ||||||
|  | 		testutils.SimulateKeyPress(rl.KeyT) | ||||||
|  | 		msg, sent := chat.Update() | ||||||
|  | 		assert.True(t, chat.isTyping) | ||||||
|  | 		assert.False(t, sent) | ||||||
|  | 		assert.Empty(t, msg) | ||||||
|  |  | ||||||
|  | 		// Test typing message | ||||||
|  | 		testutils.SimulateCharInput('h') | ||||||
|  | 		msg, sent = chat.Update() | ||||||
|  | 		testutils.SimulateCharInput('i') | ||||||
|  | 		msg, sent = chat.Update() | ||||||
|  | 		assert.Equal(t, 2, len(chat.inputBuffer)) | ||||||
|  | 		assert.False(t, sent) | ||||||
|  | 		assert.Empty(t, msg) | ||||||
|  |  | ||||||
|  | 		// Test sending message | ||||||
|  | 		testutils.SimulateKeyPress(rl.KeyEnter) | ||||||
|  | 		msg, sent = chat.Update() | ||||||
|  | 		assert.True(t, sent) | ||||||
|  | 		assert.Equal(t, "hi", msg) | ||||||
|  | 		assert.False(t, chat.isTyping) | ||||||
|  | 		done <- true | ||||||
|  | 	}() | ||||||
|  |  | ||||||
|  | 	select { | ||||||
|  | 	case <-done: | ||||||
|  | 		// Test completed successfully | ||||||
|  | 	case <-time.After(5 * time.Second): | ||||||
|  | 		t.Fatal("Test timed out") | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -22,6 +22,7 @@ type Game struct { | |||||||
| 	QuitChan     chan struct{} // Channel to signal shutdown | 	QuitChan     chan struct{} // Channel to signal shutdown | ||||||
| 	loginScreen  *LoginScreen | 	loginScreen  *LoginScreen | ||||||
| 	isLoggedIn   bool | 	isLoggedIn   bool | ||||||
|  | 	input        InputHandler | ||||||
| } | } | ||||||
|  |  | ||||||
| func New() *Game { | func New() *Game { | ||||||
| @ -38,6 +39,7 @@ func New() *Game { | |||||||
| 		Chat:        NewChat(), | 		Chat:        NewChat(), | ||||||
| 		QuitChan:    make(chan struct{}), | 		QuitChan:    make(chan struct{}), | ||||||
| 		loginScreen: NewLoginScreen(), | 		loginScreen: NewLoginScreen(), | ||||||
|  | 		input:       &RaylibInput{}, | ||||||
| 	} | 	} | ||||||
| 	game.Chat.userData = game | 	game.Chat.userData = game | ||||||
| 	return game | 	return game | ||||||
| @ -86,7 +88,7 @@ func (g *Game) Update(deltaTime float32) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Handle ESC for menu | 	// Handle ESC for menu | ||||||
| 	if rl.IsKeyPressed(rl.KeyEscape) { | 	if g.input.IsKeyPressed(rl.KeyEscape) { | ||||||
| 		g.MenuOpen = !g.MenuOpen | 		g.MenuOpen = !g.MenuOpen | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| @ -325,13 +327,13 @@ func (g *Game) DrawMenu() { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Check mouse hover | 		// Check mouse hover | ||||||
| 		mousePoint := rl.GetMousePosition() | 		mousePoint := g.input.GetMousePosition() | ||||||
| 		mouseHover := rl.CheckCollisionPointRec(mousePoint, buttonRect) | 		mouseHover := rl.CheckCollisionPointRec(mousePoint, buttonRect) | ||||||
|  |  | ||||||
| 		// Draw button | 		// Draw button | ||||||
| 		if mouseHover { | 		if mouseHover { | ||||||
| 			rl.DrawRectangleRec(buttonRect, rl.ColorAlpha(rl.White, 0.3)) | 			rl.DrawRectangleRec(buttonRect, rl.ColorAlpha(rl.White, 0.3)) | ||||||
| 			if rl.IsMouseButtonPressed(rl.MouseLeftButton) { | 			if g.input.IsMouseButtonPressed(toInt32(rl.MouseLeftButton)) { | ||||||
| 				switch item { | 				switch item { | ||||||
| 				case "Resume": | 				case "Resume": | ||||||
| 					g.MenuOpen = false | 					g.MenuOpen = false | ||||||
|  | |||||||
							
								
								
									
										106
									
								
								game/game_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								game/game_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | |||||||
|  | package game | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/game/testutils" | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/types" | ||||||
|  | 	pb "gitea.boner.be/bdnugget/goonserver/actions" | ||||||
|  | 	rl "github.com/gen2brain/raylib-go/raylib" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestGame_HandleInput(t *testing.T) { | ||||||
|  | 	game := New() | ||||||
|  | 	game.Player = &types.Player{ | ||||||
|  | 		ID:    1, | ||||||
|  | 		Speed: 50.0, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Test valid click | ||||||
|  | 	simulateMouseRay(rl.Ray{ | ||||||
|  | 		Position:  rl.Vector3{X: 0, Y: 10, Z: 0}, | ||||||
|  | 		Direction: rl.Vector3{X: 0, Y: -1, Z: 0}, | ||||||
|  | 	}) | ||||||
|  | 	simulateMouseButton(toInt32(rl.MouseLeftButton), true) | ||||||
|  | 	game.HandleInput() | ||||||
|  | 	assert.NotEmpty(t, game.Player.TargetPath) | ||||||
|  |  | ||||||
|  | 	// Test invalid click (outside map) | ||||||
|  | 	simulateMouseRay(rl.Ray{ | ||||||
|  | 		Position:  rl.Vector3{X: 1000, Y: 10, Z: 1000}, | ||||||
|  | 		Direction: rl.Vector3{X: 0, Y: -1, Z: 0}, | ||||||
|  | 	}) | ||||||
|  | 	simulateMouseButton(toInt32(rl.MouseLeftButton), true) | ||||||
|  | 	game.HandleInput() | ||||||
|  | 	assert.Empty(t, game.Player.TargetPath) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestGame_UpdateCamera(t *testing.T) { | ||||||
|  | 	game := New() | ||||||
|  |  | ||||||
|  | 	// Test zoom limits | ||||||
|  | 	testutils.SimulateMouseWheel(1.0) // Zoom in | ||||||
|  | 	testutils.SimulateMouseWheel(1.0) | ||||||
|  | 	assert.GreaterOrEqual(t, cameraDistance, float32(10.0)) | ||||||
|  |  | ||||||
|  | 	testutils.SimulateMouseWheel(-1.0) // Zoom out | ||||||
|  | 	testutils.SimulateMouseWheel(-1.0) | ||||||
|  | 	assert.LessOrEqual(t, cameraDistance, float32(250.0)) | ||||||
|  |  | ||||||
|  | 	// Test camera rotation | ||||||
|  | 	originalYaw := cameraYaw | ||||||
|  | 	testutils.SimulateKeyDown(rl.KeyRight, true) | ||||||
|  | 	game.Update(0.1) | ||||||
|  | 	assert.Greater(t, cameraYaw, originalYaw) | ||||||
|  |  | ||||||
|  | 	// Test pitch limits | ||||||
|  | 	simulateKeyDown(rl.KeyUp, true) | ||||||
|  | 	for i := 0; i < 100; i++ { | ||||||
|  | 		game.Update(0.1) | ||||||
|  | 	} | ||||||
|  | 	assert.GreaterOrEqual(t, cameraPitch, float32(20.0)) | ||||||
|  | 	assert.LessOrEqual(t, cameraPitch, float32(85.0)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestGame_ChatIntegration(t *testing.T) { | ||||||
|  | 	game := New() | ||||||
|  | 	game.Player = &types.Player{ID: 1} | ||||||
|  |  | ||||||
|  | 	// Test chat message to action queue | ||||||
|  | 	testutils.SimulateKeyPress(rl.KeyT) | ||||||
|  | 	game.Update(0.1) | ||||||
|  | 	assert.True(t, game.Chat.isTyping) | ||||||
|  |  | ||||||
|  | 	testutils.SimulateCharInput('h') | ||||||
|  | 	testutils.SimulateCharInput('i') | ||||||
|  | 	testutils.SimulateKeyPress(rl.KeyEnter) | ||||||
|  | 	game.Update(0.1) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, 1, len(game.Player.ActionQueue)) | ||||||
|  | 	assert.Equal(t, pb.Action_CHAT, game.Player.ActionQueue[0].Type) | ||||||
|  | 	assert.Equal(t, "hi", game.Player.ActionQueue[0].ChatMessage) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestGame_MenuHandling(t *testing.T) { | ||||||
|  | 	game := New() | ||||||
|  |  | ||||||
|  | 	// Test menu toggle | ||||||
|  | 	assert.False(t, game.MenuOpen) | ||||||
|  | 	testutils.SimulateKeyPress(rl.KeyEscape) | ||||||
|  | 	game.Update(0.1) | ||||||
|  | 	assert.True(t, game.MenuOpen) | ||||||
|  |  | ||||||
|  | 	// Test input blocking when menu is open | ||||||
|  | 	game.Player = &types.Player{ID: 1} | ||||||
|  | 	testutils.SimulateMouseButton(testutils.ToInt32(rl.MouseLeftButton), true) | ||||||
|  | 	game.Update(0.1) | ||||||
|  | 	assert.Empty(t, game.Player.TargetPath) | ||||||
|  |  | ||||||
|  | 	// Test menu close | ||||||
|  | 	testutils.SimulateKeyPress(rl.KeyEscape) | ||||||
|  | 	game.Update(0.1) | ||||||
|  | 	assert.False(t, game.MenuOpen) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Add more test helpers as needed... | ||||||
| @ -3,16 +3,95 @@ package game | |||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  |  | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/game/mock" | ||||||
| 	"gitea.boner.be/bdnugget/goonscape/types" | 	"gitea.boner.be/bdnugget/goonscape/types" | ||||||
| 	rl "github.com/gen2brain/raylib-go/raylib" | 	rl "github.com/gen2brain/raylib-go/raylib" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // InputHandler abstracts raylib input functions for testing | ||||||
|  | type InputHandler interface { | ||||||
|  | 	IsKeyPressed(key int32) bool | ||||||
|  | 	IsKeyDown(key int32) bool | ||||||
|  | 	IsMouseButtonPressed(button int32) bool | ||||||
|  | 	GetMousePosition() rl.Vector2 | ||||||
|  | 	GetMouseRay(mousePos rl.Vector2, camera rl.Camera3D) rl.Ray | ||||||
|  | 	GetMouseWheelMove() float32 | ||||||
|  | 	GetCharPressed() rune | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // RaylibInput implements InputHandler using actual raylib functions | ||||||
|  | type RaylibInput struct{} | ||||||
|  |  | ||||||
|  | func (r *RaylibInput) IsKeyPressed(key int32) bool { return rl.IsKeyPressed(key) } | ||||||
|  | func (r *RaylibInput) IsKeyDown(key int32) bool    { return rl.IsKeyDown(key) } | ||||||
|  | func (r *RaylibInput) IsMouseButtonPressed(button int32) bool { | ||||||
|  | 	return rl.IsMouseButtonPressed(rl.MouseButton(button)) | ||||||
|  | } | ||||||
|  | func (r *RaylibInput) GetMousePosition() rl.Vector2 { return rl.GetMousePosition() } | ||||||
|  | func (r *RaylibInput) GetMouseRay(mousePos rl.Vector2, camera rl.Camera3D) rl.Ray { | ||||||
|  | 	return rl.GetMouseRay(mousePos, camera) | ||||||
|  | } | ||||||
|  | func (r *RaylibInput) GetMouseWheelMove() float32 { return rl.GetMouseWheelMove() } | ||||||
|  | func (r *RaylibInput) GetCharPressed() rune       { return rl.GetCharPressed() } | ||||||
|  |  | ||||||
|  | // MockInput implements InputHandler using our mock functions | ||||||
|  | type MockInput struct{} | ||||||
|  |  | ||||||
|  | func (m *MockInput) IsKeyPressed(key int32) bool { | ||||||
|  | 	if mock.IsKeyPressed == nil { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	return mock.IsKeyPressed(key) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *MockInput) IsKeyDown(key int32) bool { | ||||||
|  | 	if mock.IsKeyDown == nil { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	return mock.IsKeyDown(key) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *MockInput) IsMouseButtonPressed(button int32) bool { | ||||||
|  | 	if mock.IsMouseButtonPressed == nil { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	return mock.IsMouseButtonPressed(button) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *MockInput) GetMousePosition() rl.Vector2 { | ||||||
|  | 	if mock.GetMousePosition == nil { | ||||||
|  | 		return rl.Vector2{} | ||||||
|  | 	} | ||||||
|  | 	return mock.GetMousePosition() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *MockInput) GetMouseRay(mousePos rl.Vector2, camera rl.Camera3D) rl.Ray { | ||||||
|  | 	if mock.GetMouseRay == nil { | ||||||
|  | 		return rl.Ray{} | ||||||
|  | 	} | ||||||
|  | 	return mock.GetMouseRay(mousePos, camera) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *MockInput) GetMouseWheelMove() float32 { | ||||||
|  | 	if mock.GetMouseWheelMove == nil { | ||||||
|  | 		return 0 | ||||||
|  | 	} | ||||||
|  | 	return mock.GetMouseWheelMove() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *MockInput) GetCharPressed() rune { | ||||||
|  | 	if mock.GetCharPressed == nil { | ||||||
|  | 		return 0 | ||||||
|  | 	} | ||||||
|  | 	return mock.GetCharPressed() | ||||||
|  | } | ||||||
|  |  | ||||||
| func (g *Game) GetTileAtMouse() (types.Tile, bool) { | func (g *Game) GetTileAtMouse() (types.Tile, bool) { | ||||||
| 	if !rl.IsMouseButtonPressed(rl.MouseLeftButton) { | 	if !g.input.IsMouseButtonPressed(toInt32(rl.MouseLeftButton)) { | ||||||
| 		return types.Tile{}, false | 		return types.Tile{}, false | ||||||
| 	} | 	} | ||||||
| 	mouse := rl.GetMousePosition() | 	mouse := g.input.GetMousePosition() | ||||||
| 	ray := rl.GetMouseRay(mouse, g.Camera) | 	ray := g.input.GetMouseRay(mouse, g.Camera) | ||||||
|  |  | ||||||
| 	for x := 0; x < types.MapWidth; x++ { | 	for x := 0; x < types.MapWidth; x++ { | ||||||
| 		for y := 0; y < types.MapHeight; y++ { | 		for y := 0; y < types.MapHeight; y++ { | ||||||
|  | |||||||
							
								
								
									
										187
									
								
								game/input_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								game/input_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,187 @@ | |||||||
|  | package game | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/game/testutils" | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/types" | ||||||
|  | 	rl "github.com/gen2brain/raylib-go/raylib" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestMouseInput_EdgeCases(t *testing.T) { | ||||||
|  | 	game, cleanup := setupTestEnvironment(t) | ||||||
|  | 	defer cleanup() | ||||||
|  |  | ||||||
|  | 	game.Player = &types.Player{ID: 1} | ||||||
|  |  | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name     string | ||||||
|  | 		ray      rl.Ray | ||||||
|  | 		expected bool | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name: "Click outside map bounds", | ||||||
|  | 			ray: rl.Ray{ | ||||||
|  | 				Position:  rl.Vector3{X: 1000, Y: 10, Z: 1000}, | ||||||
|  | 				Direction: rl.Vector3{X: 0, Y: -1, Z: 0}, | ||||||
|  | 			}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "Click at map edge", | ||||||
|  | 			ray: rl.Ray{ | ||||||
|  | 				Position:  rl.Vector3{X: float32(types.MapWidth * types.TileSize), Y: 10, Z: 0}, | ||||||
|  | 				Direction: rl.Vector3{X: 0, Y: -1, Z: 0}, | ||||||
|  | 			}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "Click on valid tile", | ||||||
|  | 			ray: rl.Ray{ | ||||||
|  | 				Position:  rl.Vector3{X: 32, Y: 10, Z: 32}, | ||||||
|  | 				Direction: rl.Vector3{X: 0, Y: -1, Z: 0}, | ||||||
|  | 			}, | ||||||
|  | 			expected: true, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			testutils.ResetMockInput() | ||||||
|  | 			testutils.SimulateMouseRay(tt.ray) | ||||||
|  | 			testutils.SimulateMouseButton(testutils.ToInt32(rl.MouseLeftButton), true) | ||||||
|  | 			tile, clicked := game.GetTileAtMouse() | ||||||
|  | 			assert.Equal(t, tt.expected, clicked) | ||||||
|  | 			if tt.expected { | ||||||
|  | 				assert.NotEmpty(t, tile) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestChat_InputValidation(t *testing.T) { | ||||||
|  | 	game, cleanup := setupTestEnvironment(t) | ||||||
|  | 	defer cleanup() | ||||||
|  |  | ||||||
|  | 	game.Player = &types.Player{ID: 1} | ||||||
|  |  | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name     string | ||||||
|  | 		input    []rune | ||||||
|  | 		expected string | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name:     "Empty message", | ||||||
|  | 			input:    []rune{}, | ||||||
|  | 			expected: "", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:     "Message with only spaces", | ||||||
|  | 			input:    []rune("   "), | ||||||
|  | 			expected: "", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:     "Very long message", | ||||||
|  | 			input:    []rune(string(make([]rune, runeLimit))), | ||||||
|  | 			expected: string(make([]rune, runeLimit)), | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:     "Unicode characters", | ||||||
|  | 			input:    []rune("Hello 世界"), | ||||||
|  | 			expected: "Hello 世界", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			testutils.ResetMockInput() | ||||||
|  | 			testutils.SimulateKeyPress(rl.KeyT) | ||||||
|  | 			game.Update(0.1) | ||||||
|  |  | ||||||
|  | 			for _, r := range tt.input { | ||||||
|  | 				testutils.SimulateCharInput(r) | ||||||
|  | 				game.Update(0.1) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			testutils.SimulateKeyPress(rl.KeyEnter) | ||||||
|  | 			game.Update(0.1) | ||||||
|  |  | ||||||
|  | 			if tt.expected != "" { | ||||||
|  | 				assert.Equal(t, 1, len(game.Player.ActionQueue)) | ||||||
|  | 				assert.Equal(t, tt.expected, game.Player.ActionQueue[0].ChatMessage) | ||||||
|  | 			} else { | ||||||
|  | 				assert.Empty(t, game.Player.ActionQueue) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestLogin_InputValidation(t *testing.T) { | ||||||
|  | 	_, cleanup := setupTestEnvironment(t) | ||||||
|  | 	defer cleanup() | ||||||
|  |  | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name          string | ||||||
|  | 		username      string | ||||||
|  | 		password      string | ||||||
|  | 		expectSuccess bool | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name:          "Valid credentials", | ||||||
|  | 			username:      "validuser", | ||||||
|  | 			password:      "validpass", | ||||||
|  | 			expectSuccess: true, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:          "Empty username", | ||||||
|  | 			username:      "", | ||||||
|  | 			password:      "password", | ||||||
|  | 			expectSuccess: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:          "Empty password", | ||||||
|  | 			username:      "username", | ||||||
|  | 			password:      "", | ||||||
|  | 			expectSuccess: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:          "Username too long", | ||||||
|  | 			username:      "verylongusername123", | ||||||
|  | 			password:      "password", | ||||||
|  | 			expectSuccess: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:          "Special characters in username", | ||||||
|  | 			username:      "user@name", | ||||||
|  | 			password:      "password", | ||||||
|  | 			expectSuccess: false, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			login := NewLoginScreen() | ||||||
|  | 			testutils.ResetMockInput() | ||||||
|  |  | ||||||
|  | 			// Simulate typing username | ||||||
|  | 			login.focusedField = 0 | ||||||
|  | 			for _, r := range tt.username { | ||||||
|  | 				testutils.SimulateCharInput(r) | ||||||
|  | 				login.Update() | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Simulate typing password | ||||||
|  | 			login.focusedField = 1 | ||||||
|  | 			for _, r := range tt.password { | ||||||
|  | 				testutils.SimulateCharInput(r) | ||||||
|  | 				login.Update() | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Simulate clicking login button | ||||||
|  | 			testutils.SimulateMouseClick(400, 365) | ||||||
|  | 			_, _, _, submitted := login.Update() | ||||||
|  | 			assert.Equal(t, tt.expectSuccess, submitted) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										80
									
								
								game/login_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								game/login_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | |||||||
|  | package game | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/game/testutils" | ||||||
|  | 	rl "github.com/gen2brain/raylib-go/raylib" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestLoginScreen_Update(t *testing.T) { | ||||||
|  | 	login := NewLoginScreen() | ||||||
|  |  | ||||||
|  | 	// Test field focus switching | ||||||
|  | 	simulateMouseClick(400, 215) // Click username field | ||||||
|  | 	assert.Equal(t, 0, login.focusedField) | ||||||
|  |  | ||||||
|  | 	simulateMouseClick(400, 265) // Click password field | ||||||
|  | 	assert.Equal(t, 1, login.focusedField) | ||||||
|  |  | ||||||
|  | 	// Test input length limits | ||||||
|  | 	login.focusedField = 0 | ||||||
|  | 	for i := 0; i < 20; i++ { | ||||||
|  | 		simulateCharInput('x') | ||||||
|  | 	} | ||||||
|  | 	assert.LessOrEqual(t, len(login.username), 12) | ||||||
|  |  | ||||||
|  | 	login.focusedField = 1 | ||||||
|  | 	for i := 0; i < 30; i++ { | ||||||
|  | 		simulateCharInput('x') | ||||||
|  | 	} | ||||||
|  | 	assert.LessOrEqual(t, len(login.password), 20) | ||||||
|  |  | ||||||
|  | 	// Test mode switching | ||||||
|  | 	simulateMouseClick(600, 365) // Click switch mode button | ||||||
|  | 	assert.True(t, login.isRegistering) | ||||||
|  | 	simulateMouseClick(600, 365) // Click again | ||||||
|  | 	assert.False(t, login.isRegistering) | ||||||
|  |  | ||||||
|  | 	// Test submission | ||||||
|  | 	login.username = "test" | ||||||
|  | 	login.password = "password" | ||||||
|  | 	testutils.SimulateMousePosition(400, 365) | ||||||
|  | 	testutils.SimulateMouseButton(testutils.ToInt32(rl.MouseLeftButton), true) | ||||||
|  | 	username, password, isRegistering, submitted := login.Update() | ||||||
|  | 	assert.True(t, submitted) | ||||||
|  | 	assert.Equal(t, "test", username) | ||||||
|  | 	assert.Equal(t, "password", password) | ||||||
|  | 	assert.False(t, isRegistering) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestLoginScreen_ErrorHandling(t *testing.T) { | ||||||
|  | 	login := NewLoginScreen() | ||||||
|  |  | ||||||
|  | 	// Test empty fields | ||||||
|  | 	login.username = "" | ||||||
|  | 	login.password = "test" | ||||||
|  | 	testutils.SimulateMousePosition(400, 365) | ||||||
|  | 	testutils.SimulateMouseButton(testutils.ToInt32(rl.MouseLeftButton), true) | ||||||
|  | 	_, _, _, submitted := login.Update() | ||||||
|  | 	assert.False(t, submitted) | ||||||
|  | 	assert.Contains(t, login.errorMessage, "username") | ||||||
|  |  | ||||||
|  | 	// Test special characters | ||||||
|  | 	login.username = "test!@#" | ||||||
|  | 	login.password = "password" | ||||||
|  | 	testutils.SimulateMousePosition(400, 365) | ||||||
|  | 	testutils.SimulateMouseButton(testutils.ToInt32(rl.MouseLeftButton), true) | ||||||
|  | 	_, _, _, submitted = login.Update() | ||||||
|  | 	assert.False(t, submitted) | ||||||
|  | 	assert.Contains(t, login.errorMessage, "invalid characters") | ||||||
|  |  | ||||||
|  | 	// Test error message display | ||||||
|  | 	login.SetError("Test error") | ||||||
|  | 	assert.Equal(t, "Test error", login.errorMessage) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func simulateMouseClick(x, y float32) { | ||||||
|  | 	// Implementation would depend on how raylib is mocked | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								game/mock/raylib.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								game/mock/raylib.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | package mock | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	rl "github.com/gen2brain/raylib-go/raylib" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	IsKeyPressed         func(key int32) bool | ||||||
|  | 	IsKeyDown            func(key int32) bool | ||||||
|  | 	IsMouseButtonPressed func(button int32) bool | ||||||
|  | 	GetMousePosition     func() rl.Vector2 | ||||||
|  | 	GetMouseRay          func(mousePos rl.Vector2, camera rl.Camera3D) rl.Ray | ||||||
|  | 	GetMouseWheelMove    func() float32 | ||||||
|  | 	GetCharPressed       func() rune | ||||||
|  | ) | ||||||
							
								
								
									
										141
									
								
								game/test_helpers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								game/test_helpers.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,141 @@ | |||||||
|  | package game | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"sync" | ||||||
|  |  | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/game/mock" | ||||||
|  | 	rl "github.com/gen2brain/raylib-go/raylib" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	mockInput struct { | ||||||
|  | 		sync.Mutex | ||||||
|  | 		keyPressed    map[int32]bool | ||||||
|  | 		keyDown       map[int32]bool | ||||||
|  | 		mousePressed  map[int32]bool | ||||||
|  | 		mousePosition rl.Vector2 | ||||||
|  | 		mouseRay      rl.Ray | ||||||
|  | 		mouseWheel    float32 | ||||||
|  | 		charPressed   rune | ||||||
|  | 	} | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	resetMockInput() | ||||||
|  | 	setupMockFunctions() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func setupMockFunctions() { | ||||||
|  | 	mock.IsKeyPressed = mockIsKeyPressed | ||||||
|  | 	mock.IsKeyDown = mockIsKeyDown | ||||||
|  | 	mock.IsMouseButtonPressed = mockIsMouseButtonPressed | ||||||
|  | 	mock.GetMousePosition = mockGetMousePosition | ||||||
|  | 	mock.GetMouseRay = mockGetMouseRay | ||||||
|  | 	mock.GetMouseWheelMove = mockGetMouseWheelMove | ||||||
|  | 	mock.GetCharPressed = mockGetCharPressed | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func resetMockInput() { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	mockInput.keyPressed = make(map[int32]bool) | ||||||
|  | 	mockInput.keyDown = make(map[int32]bool) | ||||||
|  | 	mockInput.mousePressed = make(map[int32]bool) | ||||||
|  | 	mockInput.mousePosition = rl.Vector2{} | ||||||
|  | 	mockInput.mouseRay = rl.Ray{} | ||||||
|  | 	mockInput.mouseWheel = 0 | ||||||
|  | 	mockInput.charPressed = 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Mock input simulation functions | ||||||
|  | func simulateKeyPress(key int32) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.keyPressed[key] = true | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func simulateKeyDown(key int32, isDown bool) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.keyDown[key] = isDown | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func simulateMouseButton(button int32, isPressed bool) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.mousePressed[button] = isPressed | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func simulateMousePosition(x, y float32) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.mousePosition = rl.Vector2{X: x, Y: y} | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func simulateMouseRay(ray rl.Ray) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.mouseRay = ray | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func simulateMouseWheel(move float32) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.mouseWheel = move | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func simulateCharInput(char rune) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.charPressed = char | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Mock raylib functions | ||||||
|  | func mockIsKeyPressed(key int32) bool { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.keyPressed[key] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func mockIsKeyDown(key int32) bool { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.keyDown[key] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func mockIsMouseButtonPressed(button int32) bool { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.mousePressed[button] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func mockGetMousePosition() rl.Vector2 { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.mousePosition | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func mockGetMouseRay(mousePos rl.Vector2, camera rl.Camera3D) rl.Ray { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.mouseRay | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func mockGetMouseWheelMove() float32 { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.mouseWheel | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func mockGetCharPressed() rune { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.charPressed | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Add more mock implementations... | ||||||
|  |  | ||||||
|  | // Add this helper function | ||||||
|  | func toInt32(button rl.MouseButton) int32 { | ||||||
|  | 	return int32(button) | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								game/test_setup.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								game/test_setup.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | package game | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/game/mock" | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/game/testutils" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func setupTestEnvironment(t *testing.T) (*Game, func()) { | ||||||
|  | 	testutils.ResetMockInput() | ||||||
|  | 	testutils.SetupMockFunctions() | ||||||
|  |  | ||||||
|  | 	game := New() | ||||||
|  | 	game.input = &MockInput{} | ||||||
|  | 	game.Chat.input = &MockInput{} // Also inject mock input into chat | ||||||
|  |  | ||||||
|  | 	// Verify mock setup | ||||||
|  | 	if mock.IsKeyPressed == nil || mock.GetCharPressed == nil { | ||||||
|  | 		t.Fatal("Mock functions not properly initialized") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return game, func() { | ||||||
|  | 		testutils.ResetMockInput() | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										153
									
								
								game/testutils/helpers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								game/testutils/helpers.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,153 @@ | |||||||
|  | package testutils | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"sync" | ||||||
|  |  | ||||||
|  | 	"gitea.boner.be/bdnugget/goonscape/game/mock" | ||||||
|  | 	rl "github.com/gen2brain/raylib-go/raylib" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	mockInput struct { | ||||||
|  | 		sync.Mutex | ||||||
|  | 		keyPressed    map[int32]bool | ||||||
|  | 		keyDown       map[int32]bool | ||||||
|  | 		mousePressed  map[int32]bool | ||||||
|  | 		mousePosition rl.Vector2 | ||||||
|  | 		mouseRay      rl.Ray | ||||||
|  | 		mouseWheel    float32 | ||||||
|  | 		charPressed   rune | ||||||
|  | 	} | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	ResetMockInput() | ||||||
|  | 	SetupMockFunctions() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SetupMockFunctions initializes mock functions | ||||||
|  | func SetupMockFunctions() { | ||||||
|  | 	mock.IsKeyPressed = MockIsKeyPressed | ||||||
|  | 	mock.IsKeyDown = MockIsKeyDown | ||||||
|  | 	mock.IsMouseButtonPressed = MockIsMouseButtonPressed | ||||||
|  | 	mock.GetMousePosition = MockGetMousePosition | ||||||
|  | 	mock.GetMouseRay = MockGetMouseRay | ||||||
|  | 	mock.GetMouseWheelMove = MockGetMouseWheelMove | ||||||
|  | 	mock.GetCharPressed = MockGetCharPressed | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ResetMockInput resets all mock input states | ||||||
|  | func ResetMockInput() { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	mockInput.keyPressed = make(map[int32]bool) | ||||||
|  | 	mockInput.keyDown = make(map[int32]bool) | ||||||
|  | 	mockInput.mousePressed = make(map[int32]bool) | ||||||
|  | 	mockInput.mousePosition = rl.Vector2{} | ||||||
|  | 	mockInput.mouseRay = rl.Ray{} | ||||||
|  | 	mockInput.mouseWheel = 0 | ||||||
|  | 	mockInput.charPressed = 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SimulateKeyPress simulates a key press | ||||||
|  | func SimulateKeyPress(key int32) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.keyPressed[key] = true | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SimulateKeyDown simulates holding a key down | ||||||
|  | func SimulateKeyDown(key int32, isDown bool) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.keyDown[key] = isDown | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SimulateMouseButton simulates a mouse button press | ||||||
|  | func SimulateMouseButton(button int32, isPressed bool) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.mousePressed[button] = isPressed | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SimulateMousePosition simulates mouse movement | ||||||
|  | func SimulateMousePosition(x, y float32) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.mousePosition = rl.Vector2{X: x, Y: y} | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SimulateMouseClick simulates a mouse click at the given position | ||||||
|  | func SimulateMouseClick(x, y float32) { | ||||||
|  | 	SimulateMousePosition(x, y) | ||||||
|  | 	SimulateMouseButton(ToInt32(rl.MouseLeftButton), true) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SimulateMouseRay simulates a mouse ray | ||||||
|  | func SimulateMouseRay(ray rl.Ray) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.mouseRay = ray | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SimulateMouseWheel simulates mouse wheel movement | ||||||
|  | func SimulateMouseWheel(move float32) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.mouseWheel = move | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SimulateCharInput simulates character input | ||||||
|  | func SimulateCharInput(char rune) { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	mockInput.charPressed = char | ||||||
|  | 	mockInput.Unlock() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Mock raylib functions | ||||||
|  | func MockIsKeyPressed(key int32) bool { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.keyPressed[key] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func MockIsKeyDown(key int32) bool { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.keyDown[key] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func MockIsMouseButtonPressed(button int32) bool { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.mousePressed[button] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func MockGetMousePosition() rl.Vector2 { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.mousePosition | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func MockGetMouseRay(mousePos rl.Vector2, camera rl.Camera3D) rl.Ray { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.mouseRay | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func MockGetMouseWheelMove() float32 { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.mouseWheel | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func MockGetCharPressed() rune { | ||||||
|  | 	mockInput.Lock() | ||||||
|  | 	defer mockInput.Unlock() | ||||||
|  | 	return mockInput.charPressed | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ToInt32 converts MouseButton to int32 | ||||||
|  | func ToInt32(button rl.MouseButton) int32 { | ||||||
|  | 	return int32(button) | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								go.mod
									
									
									
									
									
								
							| @ -8,8 +8,15 @@ require ( | |||||||
| 	google.golang.org/protobuf v1.36.3 | 	google.golang.org/protobuf v1.36.3 | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | require ( | ||||||
|  | 	github.com/davecgh/go-spew v1.1.1 // indirect | ||||||
|  | 	github.com/pmezard/go-difflib v1.0.0 // indirect | ||||||
|  | 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||||
|  | ) | ||||||
|  |  | ||||||
| require ( | require ( | ||||||
| 	github.com/ebitengine/purego v0.8.2 // indirect | 	github.com/ebitengine/purego v0.8.2 // indirect | ||||||
|  | 	github.com/stretchr/testify v1.10.0 | ||||||
| 	golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect | 	golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect | ||||||
| 	golang.org/x/sys v0.29.0 // indirect | 	golang.org/x/sys v0.29.0 // indirect | ||||||
| ) | ) | ||||||
|  | |||||||
							
								
								
									
										9
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								go.sum
									
									
									
									
									
								
							| @ -1,12 +1,21 @@ | |||||||
|  | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||||
|  | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||||
| github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= | github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= | ||||||
| github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= | github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= | ||||||
| github.com/gen2brain/raylib-go/raylib v0.0.0-20250109172833-6dbba4f81a9b h1:JJfspevP3YOXcSKVABizYOv++yMpTJIdPUtoDzF/RWw= | github.com/gen2brain/raylib-go/raylib v0.0.0-20250109172833-6dbba4f81a9b h1:JJfspevP3YOXcSKVABizYOv++yMpTJIdPUtoDzF/RWw= | ||||||
| github.com/gen2brain/raylib-go/raylib v0.0.0-20250109172833-6dbba4f81a9b/go.mod h1:BaY76bZk7nw1/kVOSQObPY1v1iwVE1KHAGMfvI6oK1Q= | github.com/gen2brain/raylib-go/raylib v0.0.0-20250109172833-6dbba4f81a9b/go.mod h1:BaY76bZk7nw1/kVOSQObPY1v1iwVE1KHAGMfvI6oK1Q= | ||||||
| github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= | ||||||
| github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||||||
|  | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||||
|  | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||||
|  | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= | ||||||
|  | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||||||
| golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA= | golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA= | ||||||
| golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= | golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= | ||||||
| golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= | golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= | ||||||
| golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||||
| google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= | google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= | ||||||
| google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= | google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= | ||||||
|  | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
|  | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||||
|  | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user