447 lines
18 KiB
Python
447 lines
18 KiB
Python
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
import os
|
|
import unittest
|
|
|
|
from ..bootstrap import Bootstrap
|
|
from ..display.display import Display
|
|
from ..display.display_manager import DisplayManager
|
|
from ..entities.friendly import Sunflower
|
|
from ..entities.items import Bomb
|
|
from ..entities.player import Player
|
|
from ..enums import DisplayActions
|
|
from ..game import Game, KeyValues, GameMode
|
|
from ..menus import MainMenuValues
|
|
from ..resources import ResourceManager
|
|
from ..settings import Settings
|
|
from ..translations import gettext as _, Translator
|
|
|
|
|
|
class TestGame(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
"""
|
|
Setup game.
|
|
"""
|
|
self.game = Game()
|
|
self.game.new_game()
|
|
self.game.logs.add_message("Hello World !")
|
|
display = DisplayManager(None, self.game)
|
|
self.game.display_actions = display.handle_display_action
|
|
|
|
def test_load_game(self) -> None:
|
|
"""
|
|
Save a game and reload it.
|
|
"""
|
|
bomb = Bomb()
|
|
self.game.map.add_entity(bomb)
|
|
bomb.hold(self.game.player)
|
|
old_state = self.game.save_state()
|
|
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.assertEqual(self.game.main_menu.validate(), MainMenuValues.SAVE)
|
|
self.game.handle_key_pressed(KeyValues.ENTER) # Save game
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.assertEqual(self.game.main_menu.validate(), MainMenuValues.LOAD)
|
|
self.game.handle_key_pressed(KeyValues.ENTER) # Load game
|
|
|
|
new_state = self.game.save_state()
|
|
self.assertEqual(old_state, new_state)
|
|
|
|
# Ensure that the bomb is loaded
|
|
self.assertTrue(self.game.player.inventory)
|
|
|
|
# Error on loading save
|
|
with open(ResourceManager.get_config_path("save.json"), "w") as f:
|
|
f.write("I am not a JSON file")
|
|
self.assertIsNone(self.game.message)
|
|
self.game.load_game()
|
|
self.assertIsNotNone(self.game.message)
|
|
self.game.message = None
|
|
|
|
with open(ResourceManager.get_config_path("save.json"), "w") as f:
|
|
f.write("{}")
|
|
self.assertIsNone(self.game.message)
|
|
self.game.load_game()
|
|
self.assertIsNotNone(self.game.message)
|
|
self.game.message = None
|
|
|
|
# Load game with a dead player
|
|
self.game.map.remove_entity(self.game.player)
|
|
self.game.save_game()
|
|
self.game.load_game()
|
|
self.assertIsNotNone(self.game.message)
|
|
|
|
def test_bootstrap_fail(self) -> None:
|
|
"""
|
|
Ensure that the test can't play the game,
|
|
because there is no associated shell.
|
|
Yeah, that's only for coverage.
|
|
"""
|
|
self.assertRaises(Exception, Bootstrap.run_game)
|
|
self.assertEqual(os.getenv("TERM", "unknown"), "unknown")
|
|
|
|
def test_key_translation(self) -> None:
|
|
"""
|
|
Test key bindings.
|
|
"""
|
|
self.game.settings = Settings()
|
|
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_UP_PRIMARY, self.game.settings),
|
|
KeyValues.UP)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_UP_SECONDARY, self.game.settings),
|
|
KeyValues.UP)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_DOWN_PRIMARY, self.game.settings),
|
|
KeyValues.DOWN)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_DOWN_SECONDARY, self.game.settings),
|
|
KeyValues.DOWN)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_LEFT_PRIMARY, self.game.settings),
|
|
KeyValues.LEFT)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_LEFT_SECONDARY, self.game.settings),
|
|
KeyValues.LEFT)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_RIGHT_PRIMARY, self.game.settings),
|
|
KeyValues.RIGHT)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_RIGHT_SECONDARY, self.game.settings),
|
|
KeyValues.RIGHT)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_ENTER, self.game.settings),
|
|
KeyValues.ENTER)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_INVENTORY, self.game.settings),
|
|
KeyValues.INVENTORY)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_USE, self.game.settings),
|
|
KeyValues.USE)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_EQUIP, self.game.settings),
|
|
KeyValues.EQUIP)
|
|
self.assertEqual(KeyValues.translate_key(
|
|
self.game.settings.KEY_DROP, self.game.settings),
|
|
KeyValues.DROP)
|
|
self.assertEqual(KeyValues.translate_key(' ', self.game.settings),
|
|
KeyValues.SPACE)
|
|
self.assertEqual(KeyValues.translate_key('plop', self.game.settings),
|
|
None)
|
|
|
|
def test_key_press(self) -> None:
|
|
"""
|
|
Press a key and see what is done.
|
|
"""
|
|
self.assertEqual(self.game.state, GameMode.MAINMENU)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.START)
|
|
self.game.handle_key_pressed(KeyValues.UP)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.START)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.RESUME)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.SAVE)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.LOAD)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.SETTINGS)
|
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
|
self.assertEqual(self.game.state, GameMode.SETTINGS)
|
|
|
|
self.game.handle_key_pressed(KeyValues.SPACE)
|
|
self.assertEqual(self.game.state, GameMode.MAINMENU)
|
|
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.EXIT)
|
|
self.assertRaises(SystemExit, self.game.handle_key_pressed,
|
|
KeyValues.ENTER)
|
|
|
|
self.game.handle_key_pressed(KeyValues.UP)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.SETTINGS)
|
|
self.game.handle_key_pressed(KeyValues.UP)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.LOAD)
|
|
self.game.handle_key_pressed(KeyValues.UP)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.SAVE)
|
|
self.game.handle_key_pressed(KeyValues.UP)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.RESUME)
|
|
self.game.handle_key_pressed(KeyValues.UP)
|
|
self.assertEqual(self.game.main_menu.validate(),
|
|
MainMenuValues.START)
|
|
|
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
|
self.assertEqual(self.game.state, GameMode.PLAY)
|
|
|
|
# Kill entities
|
|
for entity in self.game.map.entities.copy():
|
|
if not isinstance(entity, Player):
|
|
self.game.map.remove_entity(entity)
|
|
|
|
y, x = self.game.player.y, self.game.player.x
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
new_y, new_x = self.game.player.y, self.game.player.x
|
|
self.assertEqual(new_y, y + 1)
|
|
self.assertEqual(new_x, x)
|
|
|
|
y, x = new_y, new_x
|
|
self.game.handle_key_pressed(KeyValues.RIGHT)
|
|
new_y, new_x = self.game.player.y, self.game.player.x
|
|
self.assertEqual(new_y, y)
|
|
self.assertEqual(new_x, x + 1)
|
|
|
|
y, x = self.game.player.y, self.game.player.x
|
|
self.game.handle_key_pressed(KeyValues.UP)
|
|
new_y, new_x = self.game.player.y, self.game.player.x
|
|
self.assertEqual(new_y, y - 1)
|
|
self.assertEqual(new_x, x)
|
|
|
|
y, x = self.game.player.y, self.game.player.x
|
|
self.game.handle_key_pressed(KeyValues.LEFT)
|
|
new_y, new_x = self.game.player.y, self.game.player.x
|
|
self.assertEqual(new_y, y)
|
|
self.assertEqual(new_x, x - 1)
|
|
|
|
self.game.handle_key_pressed(KeyValues.SPACE)
|
|
self.assertEqual(self.game.state, GameMode.MAINMENU)
|
|
|
|
def test_new_game(self) -> None:
|
|
"""
|
|
Ensure that the start button starts a new game.
|
|
"""
|
|
old_map = self.game.map
|
|
old_player = self.game.player
|
|
self.game.handle_key_pressed(KeyValues.ENTER) # Start new game
|
|
new_map = self.game.map
|
|
new_player = self.game.player
|
|
# Ensure that
|
|
self.assertNotEqual(old_map, new_map)
|
|
self.assertNotEqual(old_player, new_player)
|
|
|
|
self.game.handle_key_pressed(KeyValues.SPACE)
|
|
old_map = new_map
|
|
old_player = new_player
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.ENTER) # Resume game
|
|
new_map = self.game.map
|
|
new_player = self.game.player
|
|
self.assertEqual(old_map, new_map)
|
|
self.assertEqual(old_player, new_player)
|
|
|
|
def test_settings_menu(self) -> None:
|
|
"""
|
|
Ensure that the settings menu is working properly.
|
|
"""
|
|
self.game.settings = Settings()
|
|
|
|
# Open settings menu
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
|
self.assertEqual(self.game.state, GameMode.SETTINGS)
|
|
|
|
# Define the "move up" key to 'w'
|
|
self.assertFalse(self.game.settings_menu.waiting_for_key)
|
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
|
self.assertTrue(self.game.settings_menu.waiting_for_key)
|
|
self.game.handle_key_pressed(None, 'w')
|
|
self.assertFalse(self.game.settings_menu.waiting_for_key)
|
|
self.assertEqual(self.game.settings.KEY_UP_PRIMARY, 'w')
|
|
|
|
# Navigate to "move left"
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.UP)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
|
|
# Define the "move up" key to 'a'
|
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
|
self.assertTrue(self.game.settings_menu.waiting_for_key)
|
|
# Can't used a mapped key
|
|
self.game.handle_key_pressed(None, 's')
|
|
self.assertTrue(self.game.settings_menu.waiting_for_key)
|
|
self.game.handle_key_pressed(None, 'a')
|
|
self.assertFalse(self.game.settings_menu.waiting_for_key)
|
|
self.assertEqual(self.game.settings.KEY_LEFT_PRIMARY, 'a')
|
|
|
|
# Navigate to "texture pack"
|
|
for ignored in range(9):
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
|
|
# Change texture pack
|
|
self.assertEqual(self.game.settings.TEXTURE_PACK, "ascii")
|
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
|
self.assertEqual(self.game.settings.TEXTURE_PACK, "squirrel")
|
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
|
self.assertEqual(self.game.settings.TEXTURE_PACK, "ascii")
|
|
|
|
# Change language
|
|
Translator.compilemessages()
|
|
Translator.refresh_translations()
|
|
self.game.settings.LOCALE = "en"
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
|
self.assertEqual(self.game.settings.LOCALE, "fr")
|
|
self.assertEqual(_("New game"), "Nouvelle partie")
|
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
|
self.assertEqual(self.game.settings.LOCALE, "de")
|
|
self.assertEqual(_("New game"), "Neu Spiel")
|
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
|
self.assertEqual(self.game.settings.LOCALE, "en")
|
|
self.assertEqual(_("New game"), "New game")
|
|
|
|
# Navigate to "back" button
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
|
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
|
self.assertEqual(self.game.state, GameMode.MAINMENU)
|
|
|
|
def test_logs(self) -> None:
|
|
"""
|
|
Tests the use of logs
|
|
"""
|
|
self.assertEqual(self.game.logs.messages, ["Hello World !"])
|
|
self.game.logs.add_messages(["Hello", "World"])
|
|
self.assertEqual(self.game.logs.messages, ["Hello World !",
|
|
"Hello", "World"])
|
|
self.game.logs.clear()
|
|
self.assertEqual(self.game.logs.messages, [])
|
|
|
|
def test_dead_screen(self) -> None:
|
|
"""
|
|
Kill player and render dead screen.
|
|
"""
|
|
self.game.state = GameMode.PLAY
|
|
# Kill player
|
|
self.game.player.take_damage(self.game.player,
|
|
self.game.player.health + 2)
|
|
y, x = self.game.player.y, self.game.player.x
|
|
for key in [KeyValues.UP, KeyValues.DOWN,
|
|
KeyValues.LEFT, KeyValues.RIGHT]:
|
|
self.game.handle_key_pressed(key)
|
|
new_y, new_x = self.game.player.y, self.game.player.x
|
|
self.assertEqual(new_y, y)
|
|
self.assertEqual(new_x, x)
|
|
|
|
def test_not_implemented(self) -> None:
|
|
"""
|
|
Check that some functions are not implemented, only for coverage.
|
|
"""
|
|
self.assertRaises(NotImplementedError, Display.display, None)
|
|
|
|
def test_messages(self) -> None:
|
|
"""
|
|
Display error messages.
|
|
"""
|
|
self.game.message = "I am an error"
|
|
self.game.display_actions(DisplayActions.UPDATE)
|
|
self.game.display_actions(DisplayActions.REFRESH)
|
|
self.game.handle_key_pressed(None, "random key")
|
|
self.assertIsNone(self.game.message)
|
|
|
|
def test_inventory_menu(self) -> None:
|
|
"""
|
|
Open the inventory menu and interact with items.
|
|
"""
|
|
self.game.state = GameMode.PLAY
|
|
# Open and close the inventory
|
|
self.game.handle_key_pressed(KeyValues.INVENTORY)
|
|
self.assertEqual(self.game.state, GameMode.INVENTORY)
|
|
self.game.handle_key_pressed(KeyValues.SPACE)
|
|
self.assertEqual(self.game.state, GameMode.PLAY)
|
|
|
|
# Add five bombs in the inventory
|
|
for ignored in range(5):
|
|
bomb = Bomb()
|
|
bomb.map = self.game.map
|
|
bomb.map.add_entity(bomb)
|
|
bomb.hold(self.game.player)
|
|
|
|
self.game.handle_key_pressed(KeyValues.INVENTORY)
|
|
self.assertEqual(self.game.state, GameMode.INVENTORY)
|
|
|
|
# Navigate in the menu
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.assertEqual(self.game.inventory_menu.position, 3)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.game.handle_key_pressed(KeyValues.UP)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.assertEqual(self.game.inventory_menu.position, 4)
|
|
|
|
# Equip key does nothing
|
|
self.game.handle_key_pressed(KeyValues.EQUIP)
|
|
|
|
# Drop an item
|
|
bomb = self.game.player.inventory[-1]
|
|
self.assertEqual(self.game.inventory_menu.validate(), bomb)
|
|
self.assertTrue(bomb.held)
|
|
self.assertEqual(bomb.held_by, self.game.player)
|
|
self.game.handle_key_pressed(KeyValues.DROP)
|
|
self.assertFalse(bomb.held)
|
|
self.assertIsNone(bomb.held_by)
|
|
self.assertIsNone(bomb.owner)
|
|
self.assertFalse(bomb.exploding)
|
|
self.assertEqual(bomb.y, self.game.player.y)
|
|
self.assertEqual(bomb.x, self.game.player.x)
|
|
|
|
# Use the bomb
|
|
bomb = self.game.player.inventory[-1]
|
|
self.assertEqual(self.game.inventory_menu.validate(), bomb)
|
|
self.assertTrue(bomb.held)
|
|
self.assertEqual(bomb.held_by, self.game.player)
|
|
self.game.handle_key_pressed(KeyValues.USE)
|
|
self.assertFalse(bomb.held)
|
|
self.assertIsNone(bomb.held_by)
|
|
self.assertEqual(bomb.owner, self.game.player)
|
|
self.assertTrue(bomb.exploding)
|
|
self.assertEqual(bomb.y, self.game.player.y)
|
|
self.assertEqual(bomb.x, self.game.player.x)
|
|
|
|
def test_talk_to_sunflowers(self) -> None:
|
|
"""
|
|
Interact with sunflowers
|
|
"""
|
|
self.game.state = GameMode.PLAY
|
|
|
|
sunflower = Sunflower()
|
|
sunflower.move(2, 6)
|
|
self.game.map.add_entity(sunflower)
|
|
|
|
# Talk to sunflower... or not
|
|
self.game.handle_key_pressed(KeyValues.T)
|
|
self.assertTrue(self.game.waiting_for_friendly_key)
|
|
self.game.handle_key_pressed(KeyValues.UP)
|
|
self.assertFalse(self.game.waiting_for_friendly_key)
|
|
self.assertEqual(self.game.state, GameMode.PLAY)
|
|
self.assertFalse(len(self.game.logs.messages) > 1)
|
|
|
|
# Talk to sunflower
|
|
self.game.handle_key_pressed(KeyValues.T)
|
|
self.assertTrue(self.game.waiting_for_friendly_key)
|
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
self.assertFalse(self.game.waiting_for_friendly_key)
|
|
self.assertEqual(self.game.state, GameMode.PLAY)
|
|
self.assertTrue(self.game.logs.messages)
|
|
# Ensure that the message is a good message
|
|
self.assertIn(self.game.logs.messages[1][21:],
|
|
Sunflower.dialogue_option)
|