Skip to content

Commit 76d73ec

Browse files
committed
Add more test coverage
1 parent 9e55149 commit 76d73ec

File tree

2 files changed

+261
-2
lines changed

2 files changed

+261
-2
lines changed

game/game_test.go

Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ func createTestLevel() *Level {
3535
level.Player = &Player{
3636
Character: Character{
3737
Entity: Entity{
38-
Pos: Pos{X: 7, Y: 7}, // Center of 15x15 grid
38+
Pos: Pos{X: 7, Y: 7},
3939
Name: "You",
4040
Rune: '@',
4141
},
4242
Hitpoints: 100,
43-
SightRange: 3, // Reduced to match test map size
43+
SightRange: 3,
44+
Speed: 1.0,
45+
PatternRNG: mrand.New(mrand.NewSource(0)),
4446
},
4547
}
4648
level.Monsters = make(map[Pos]*Monster)
@@ -1385,3 +1387,134 @@ func TestMoveWithPortal(t *testing.T) {
13851387
t.Error("Move should set player to target position")
13861388
}
13871389
}
1390+
1391+
func TestHandleInputMovement(t *testing.T) {
1392+
game := createTestGame()
1393+
initialPos := game.CurrentLevel.Player.Pos
1394+
input := &Input{Typ: Up}
1395+
game.handleInput(input)
1396+
newPos := game.CurrentLevel.Player.Pos
1397+
expectedPos := Pos{initialPos.X, initialPos.Y - 1}
1398+
if newPos != expectedPos {
1399+
t.Errorf("Expected player position %v, got %v", expectedPos, newPos)
1400+
}
1401+
}
1402+
1403+
func TestHandleInputTakeItem(t *testing.T) {
1404+
game := createTestGame()
1405+
level := game.CurrentLevel
1406+
pos := level.Player.Pos
1407+
item := NewSword(pos)
1408+
level.Items[pos] = append(level.Items[pos], item)
1409+
1410+
input := &Input{Typ: TakeItem, Item: item}
1411+
game.handleInput(input)
1412+
1413+
if len(level.Player.Items) != 1 || level.Player.Items[0] != item {
1414+
t.Error("Item not added to player's inventory")
1415+
}
1416+
if len(level.Items[pos]) != 0 {
1417+
t.Error("Item not removed from level")
1418+
}
1419+
}
1420+
1421+
func TestHandleInputDropItem(t *testing.T) {
1422+
game := createTestGame()
1423+
level := game.CurrentLevel
1424+
player := level.Player
1425+
item := NewSword(player.Pos)
1426+
player.Items = append(player.Items, item)
1427+
1428+
input := &Input{Typ: DropItem, Item: item}
1429+
game.handleInput(input)
1430+
1431+
if len(player.Items) != 0 {
1432+
t.Error("Item not removed from inventory")
1433+
}
1434+
if len(level.Items[player.Pos]) != 1 || level.Items[player.Pos][0] != item {
1435+
t.Error("Item not added to level")
1436+
}
1437+
}
1438+
1439+
func TestHandleInputCombatBurst(t *testing.T) {
1440+
game := createTestGame()
1441+
level := game.CurrentLevel
1442+
player := level.Player
1443+
monsterPos := Pos{7, 6}
1444+
monster := NewRat(monsterPos)
1445+
level.Monsters[monsterPos] = monster
1446+
level.Attack(&player.Character, &monster.Character)
1447+
player.Burst = &Burst{Notes: []int{2}, MaxCombo: 1, Combo: 0} // Assuming 2 corresponds to Up
1448+
player.Stamina = 1
1449+
1450+
input := &Input{Typ: Up}
1451+
game.handleInput(input)
1452+
1453+
if len(player.Burst.Notes) != 0 {
1454+
t.Error("Burst note not consumed")
1455+
}
1456+
if player.Stamina != 0 {
1457+
t.Error("Stamina not decremented")
1458+
}
1459+
}
1460+
1461+
func TestHandleInputCloseWindow(t *testing.T) {
1462+
game := createTestGame()
1463+
initialChannels := len(game.LevelChans)
1464+
testChan := game.LevelChans[0]
1465+
input := &Input{Typ: CloseWindow, LevelChannel: testChan}
1466+
game.handleInput(input)
1467+
1468+
if len(game.LevelChans) != initialChannels-1 {
1469+
t.Error("Level channel not removed")
1470+
}
1471+
}
1472+
1473+
func TestRunProcessesInput(t *testing.T) {
1474+
game := createTestGame()
1475+
levelChan := make(chan *Level, 1)
1476+
game.LevelChans = []chan *Level{levelChan}
1477+
1478+
go game.Run()
1479+
defer close(game.InputChan)
1480+
1481+
initialPos := game.CurrentLevel.Player.Pos
1482+
game.InputChan <- &Input{Typ: Up}
1483+
1484+
updatedLevel := <-levelChan
1485+
newPos := updatedLevel.Player.Pos
1486+
expectedPos := Pos{initialPos.X, initialPos.Y - 1}
1487+
if newPos != expectedPos {
1488+
t.Errorf("Expected player position %v after Run, got %v", expectedPos, newPos)
1489+
}
1490+
}
1491+
1492+
func TestRunUpdatesMonsters(t *testing.T) {
1493+
game := createTestGame()
1494+
level := game.CurrentLevel
1495+
monsterPos := Pos{7, 6}
1496+
monster := NewRat(monsterPos)
1497+
monster.ActionPoints = 0.0
1498+
level.Monsters[monsterPos] = monster
1499+
1500+
levelChan := make(chan *Level, 1)
1501+
game.LevelChans = []chan *Level{levelChan}
1502+
1503+
go game.Run()
1504+
defer close(game.InputChan)
1505+
1506+
<-levelChan // Discard initial state sent on Run start
1507+
1508+
// Send dummy input to trigger game loop processing
1509+
game.InputChan <- &Input{Typ: None}
1510+
1511+
updatedLevel := <-levelChan // Get state after update
1512+
updatedMonster, exists := updatedLevel.Monsters[monsterPos]
1513+
if !exists {
1514+
t.Fatal("Monster not found in level")
1515+
}
1516+
// Correct the expected value from 1.5 to 0.5
1517+
if updatedMonster.ActionPoints != 0.5 {
1518+
t.Errorf("Expected monster ActionPoints 0.5, got %f", updatedMonster.ActionPoints)
1519+
}
1520+
}

ui2d/ui2d_test.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,3 +502,129 @@ func TestInventoryUIEdgeCases(t *testing.T) {
502502
t.Error("Should handle dropping item in full inventory")
503503
}
504504
}
505+
506+
func TestCheckEquippedItem(t *testing.T) {
507+
ui := &ui{
508+
winWidth: 800,
509+
winHeight: 600,
510+
draggedItem: &game.Item{
511+
Typ: game.Weapon,
512+
},
513+
}
514+
515+
// Position mouse over weapon slot
516+
weaponRect := ui.getWeaponSlotRect()
517+
ui.currentMouseState = &mouseState{
518+
pos: game.Pos{X: int(weaponRect.X) + 5, Y: int(weaponRect.Y) + 5},
519+
}
520+
521+
// Test weapon equip
522+
result := ui.CheckEquippedItem()
523+
if result != ui.draggedItem {
524+
t.Error("Should return weapon when dragged over weapon slot")
525+
}
526+
527+
// Test wrong item type
528+
ui.draggedItem.Typ = game.Helmet
529+
result = ui.CheckEquippedItem()
530+
if result != nil {
531+
t.Error("Should not equip helmet in weapon slot")
532+
}
533+
534+
// Test helmet equip
535+
ui.draggedItem.Typ = game.Helmet
536+
helmetRect := ui.getHelmetSlotRect()
537+
ui.currentMouseState.pos = game.Pos{X: int(helmetRect.X) + 5, Y: int(helmetRect.Y) + 5}
538+
result = ui.CheckEquippedItem()
539+
if result != ui.draggedItem {
540+
t.Error("Should return helmet when dragged over helmet slot")
541+
}
542+
}
543+
544+
func TestCheckInventoryItems(t *testing.T) {
545+
item := &game.Item{}
546+
level := &game.Level{
547+
Player: &game.Player{
548+
Character: game.Character{
549+
Items: []*game.Item{item},
550+
},
551+
},
552+
}
553+
554+
ui := &ui{
555+
winWidth: 800,
556+
winHeight: 600,
557+
currentMouseState: &mouseState{
558+
leftButton: true,
559+
},
560+
}
561+
562+
// Position mouse over first inventory slot
563+
itemRect := ui.getInventoryItemRect(0)
564+
ui.currentMouseState.pos = game.Pos{X: int(itemRect.X) + 5, Y: int(itemRect.Y) + 5}
565+
566+
// Test item pickup
567+
result := ui.CheckInventoryItems(level)
568+
if result != item {
569+
t.Error("Should detect inventory item when clicked")
570+
}
571+
572+
// Test no item found
573+
ui.currentMouseState.pos = game.Pos{X: 0, Y: 0}
574+
result = ui.CheckInventoryItems(level)
575+
if result != nil {
576+
t.Error("Should return nil when clicking empty area")
577+
}
578+
}
579+
580+
func TestGetSliceFromInt(t *testing.T) {
581+
ui := &ui{}
582+
tests := []struct {
583+
input int
584+
expected []int
585+
}{
586+
{0, []int{0}},
587+
{5, []int{5}},
588+
{45, []int{5, 4}},
589+
{123, []int{3, 2, 1}},
590+
{6789, []int{9, 8, 7, 6}},
591+
}
592+
593+
for _, tc := range tests {
594+
actual := ui.getSliceFromInt(tc.input)
595+
if !slicesEqual(actual, tc.expected) {
596+
t.Errorf("For %d expected %v, got %v", tc.input, tc.expected, actual)
597+
}
598+
}
599+
}
600+
601+
func slicesEqual(a, b []int) bool {
602+
if len(a) != len(b) {
603+
return false
604+
}
605+
for i := range a {
606+
if a[i] != b[i] {
607+
return false
608+
}
609+
}
610+
return true
611+
}
612+
613+
func TestGetRuneFromNoteskinIndex(t *testing.T) {
614+
tests := []struct {
615+
input int
616+
expected rune
617+
}{
618+
{0, game.Receptor},
619+
{1, game.Red},
620+
{2, game.Blue},
621+
{4, game.Yellow},
622+
}
623+
624+
for _, tc := range tests {
625+
actual := getRuneFromNoteskinIndex(tc.input)
626+
if actual != tc.expected {
627+
t.Errorf("For %d expected %c, got %c", tc.input, tc.expected, actual)
628+
}
629+
}
630+
}

0 commit comments

Comments
 (0)