Add GdUnit4 testing framework with comprehensive test coverage
- Add GdUnit4 v6.2.1 framework in addons/gdUnit4/ - Create test directory structure (tests/unit/, tests/integration/, tests/mocks/) - Add unit tests for MusicPlayer.gd (8 tests) - Add unit tests for MainWindow.gd (15+ tests) - Add unit tests for Settings.gd (5 tests) - Add unit tests for Playlist.gd (11 tests) - Add integration tests for full flow (10+ tests) - Add MockHTTPRequest for HTTP request mocking - Add TestHelpers with utility functions - Add Gitea Actions CI workflow (.gitea/workflows/test.yml) - Add .runsettings for GdUnit4 CLI configuration - Add run_tests.sh for convenient test execution - Add TESTING.md with comprehensive documentation - Add TESTING_PLAN.md with implementation details - Update .gitignore for test artifacts - Enable GdUnit4 plugin in project.godot Features: - Test button functionality (play, pause, search, sync, etc.) - Mock REST API requests to server - Test complete application flows - Run tests in CI (headless mode) - Run tests in GUI for visual feedback - JUnit XML and HTML test reports Generated by OpenCode AI assistant.
This commit is contained in:
1 parent
8da6fc442f
commit
4a275e6a88
15 files changed
+2146
-1
No files matched your search
@@ -0,0 +1,357 @@
|
||||
class_name MainWindowTest
|
||||
extends GdUnitTestSuite
|
||||
|
||||
|
||||
func test_next_button_pressed_connects_to_play_next_song():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_next_button = mock(Button)
|
||||
|
||||
main_window.next_button = mock_next_button
|
||||
|
||||
# Connect the signal
|
||||
main_window._ready()
|
||||
|
||||
# Simulate button press
|
||||
mock_next_button.emit_signal("pressed")
|
||||
|
||||
# Verify the connection was made (play_next_song should be callable)
|
||||
assert_true(main_window.is_connected("next_button", "pressed", main_window, "play_next_song"))
|
||||
|
||||
|
||||
func test_show_answer_button_pressed_connects_to_handler():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_show_answer_button = mock(Button)
|
||||
|
||||
main_window.show_answer_button = mock_show_answer_button
|
||||
main_window._ready()
|
||||
|
||||
assert_true(main_window.is_connected("show_answer_button", "pressed", main_window, "show_answer_pressed"))
|
||||
|
||||
|
||||
func test_search_button_pressed_connects_to_show_search():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_search_button = mock(Button)
|
||||
|
||||
main_window.search_button = mock_search_button
|
||||
main_window._ready()
|
||||
|
||||
assert_true(main_window.is_connected("search_button", "pressed", main_window, "show_search"))
|
||||
|
||||
|
||||
func test_sync_button_pressed_connects_to_sync_soundtracks():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_sync_button = mock(Button)
|
||||
|
||||
main_window.sync_button = mock_sync_button
|
||||
main_window._ready()
|
||||
|
||||
assert_true(main_window.is_connected("sync_button", "pressed", main_window, "sync_soundtracks"))
|
||||
|
||||
|
||||
func test_sound_test_button_pressed_connects_to_get_sound_test_song():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_sound_test_button = mock(Button)
|
||||
var mock_music_player = mock(MusicPlayer)
|
||||
|
||||
main_window.sound_test_button = mock_sound_test_button
|
||||
main_window.music_player_container = mock_music_player
|
||||
main_window._ready()
|
||||
|
||||
assert_true(main_window.is_connected("sound_test_button", "pressed", mock_music_player, "get_sound_test_song"))
|
||||
|
||||
|
||||
func test_settings_button_pressed_connects_to_show_settings():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_settings_button = mock(Button)
|
||||
|
||||
main_window.settings_button = mock_settings_button
|
||||
main_window._ready()
|
||||
|
||||
assert_true(main_window.is_connected("settings_button", "pressed", main_window, "show_settings"))
|
||||
|
||||
|
||||
func test_reset_playlist_button_pressed_connects_to_reset_playlist():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_reset_button = mock(Button)
|
||||
|
||||
main_window.reset_playlist_button = mock_reset_button
|
||||
main_window._ready()
|
||||
|
||||
assert_true(main_window.is_connected("reset_playlist_button", "pressed", main_window, "reset_playlist"))
|
||||
|
||||
|
||||
func test_reset_points_button_pressed_connects_to_reset_points():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_reset_points_button = mock(Button)
|
||||
|
||||
main_window.reset_points_button = mock_reset_points_button
|
||||
main_window._ready()
|
||||
|
||||
assert_true(main_window.is_connected("reset_points_button", "pressed", main_window, "reset_points"))
|
||||
|
||||
|
||||
func test_add_players_button_toggles_visibility():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_add_players_button = mock(TextureButton)
|
||||
var mock_container = mock(HBoxContainer)
|
||||
|
||||
main_window.add_players_button = mock_add_players_button
|
||||
main_window.add_player_container = mock_container
|
||||
|
||||
Settings.edit_players = false
|
||||
mock_container.visible = false
|
||||
|
||||
main_window.add_players()
|
||||
|
||||
assert_true(Settings.edit_players)
|
||||
assert_true(mock_container.visible)
|
||||
|
||||
main_window.add_players()
|
||||
|
||||
assert_false(Settings.edit_players)
|
||||
assert_false(mock_container.visible)
|
||||
|
||||
|
||||
func test_add_player_adds_to_array():
|
||||
var main_window = MainWindow.new()
|
||||
|
||||
Settings.player_array.clear()
|
||||
Settings.edit_players = true
|
||||
|
||||
var initial_count = Settings.player_array.size()
|
||||
|
||||
main_window.new_player_name_field = mock(TextEdit)
|
||||
main_window.new_player_name_field.text = "Test Player"
|
||||
|
||||
main_window.add_player()
|
||||
|
||||
assert_eq(Settings.player_array.size(), initial_count + 1)
|
||||
assert_eq(Settings.player_array[-1].player_name, "Test Player")
|
||||
|
||||
|
||||
func test_add_player_does_not_add_empty_name():
|
||||
var main_window = MainWindow.new()
|
||||
|
||||
Settings.player_array.clear()
|
||||
Settings.edit_players = true
|
||||
|
||||
main_window.new_player_name_field = mock(TextEdit)
|
||||
main_window.new_player_name_field.text = ""
|
||||
|
||||
var initial_count = Settings.player_array.size()
|
||||
|
||||
main_window.add_player()
|
||||
|
||||
assert_eq(Settings.player_array.size(), initial_count)
|
||||
|
||||
|
||||
func test_add_player_does_not_exceed_max():
|
||||
var main_window = MainWindow.new()
|
||||
|
||||
Settings.player_array.clear()
|
||||
Settings.edit_players = true
|
||||
|
||||
# Fill up to max
|
||||
for i in range(Settings.MAX_NUMBER_OF_PLAYERS):
|
||||
var player_obj = PlayerObject.new("Player %d" % i, i)
|
||||
Settings.player_array.append(player_obj)
|
||||
|
||||
main_window.new_player_name_field = mock(TextEdit)
|
||||
main_window.new_player_name_field.text = "Extra Player"
|
||||
|
||||
var initial_count = Settings.player_array.size()
|
||||
|
||||
main_window.add_player()
|
||||
|
||||
assert_eq(Settings.player_array.size(), initial_count)
|
||||
|
||||
|
||||
func test_show_search_toggles_visibility():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_search_view = mock(Control)
|
||||
|
||||
main_window.search_view = mock_search_view
|
||||
mock_search_view.visible = false
|
||||
|
||||
main_window.show_search()
|
||||
|
||||
assert_true(mock_search_view.visible)
|
||||
|
||||
main_window.show_search()
|
||||
|
||||
assert_false(mock_search_view.visible)
|
||||
|
||||
|
||||
func test_show_settings_makes_window_visible():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_settings_window = mock(Control)
|
||||
|
||||
main_window.settings_window = mock_settings_window
|
||||
mock_settings_window.visible = false
|
||||
|
||||
main_window.show_settings()
|
||||
|
||||
assert_true(mock_settings_window.visible)
|
||||
|
||||
|
||||
func test_show_qr_calls_show_window():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_qr_window = mock(Control)
|
||||
|
||||
main_window.qr_window = mock_qr_window
|
||||
|
||||
main_window.show_qr()
|
||||
|
||||
# Verify show_window was called (mock should track this)
|
||||
assert_true(mock_qr_window.show_window.was_called())
|
||||
|
||||
|
||||
func test_show_about_makes_window_visible():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_about_window = mock(Control)
|
||||
|
||||
main_window.about_window = mock_about_window
|
||||
mock_about_window.visible = false
|
||||
|
||||
main_window.show_about()
|
||||
|
||||
assert_true(mock_about_window.visible)
|
||||
|
||||
|
||||
func test_get_statistics_shows_popup():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_popup = mock(PopupPanel)
|
||||
var mock_label = mock(Label)
|
||||
|
||||
main_window.statistic_popup = mock_popup
|
||||
main_window.statistic_label = mock_label
|
||||
|
||||
main_window.get_statistics()
|
||||
|
||||
assert_true(mock_popup.visible)
|
||||
|
||||
|
||||
func test_sync_soundtracks_starts_sync():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_sync_window = mock(Control)
|
||||
|
||||
main_window.sync_window = mock_sync_window
|
||||
|
||||
main_window.sync_soundtracks()
|
||||
|
||||
assert_true(mock_sync_window.start_sync.was_called())
|
||||
|
||||
|
||||
func test_reset_playlist_clears_and_refetches():
|
||||
var main_window = MainWindow.new()
|
||||
|
||||
# Mock Settings.make_request2
|
||||
var original_make_request = Settings.make_request2
|
||||
var reset_called = false
|
||||
|
||||
Settings.make_request2 = func(address: String, func_name: Callable, expect_data: bool) -> void:
|
||||
if address == "/music/reset":
|
||||
reset_called = true
|
||||
func_name.call()
|
||||
elif address == "/music/list":
|
||||
func_name.call([])
|
||||
elif address == "/music/rand":
|
||||
func_name.call(PackedByteArray())
|
||||
|
||||
Playlist.clear_song_list()
|
||||
Playlist.add_to_playlist(TestHelpers.create_test_song_object(1))
|
||||
|
||||
main_window.reset_playlist()
|
||||
|
||||
assert_true(reset_called)
|
||||
|
||||
Settings.make_request2 = original_make_request
|
||||
|
||||
|
||||
func test_reset_points_resets_all_players():
|
||||
var main_window = MainWindow.new()
|
||||
|
||||
Settings.player_array.clear()
|
||||
|
||||
var player1 = PlayerObject.new("Player 1", 0)
|
||||
var player2 = PlayerObject.new("Player 2", 1)
|
||||
|
||||
player1.player_score = 5
|
||||
player2.player_score = 10
|
||||
|
||||
Settings.player_array.append(player1)
|
||||
Settings.player_array.append(player2)
|
||||
|
||||
main_window.reset_points()
|
||||
|
||||
assert_eq(player1.player_score, 0)
|
||||
assert_eq(player2.player_score, 0)
|
||||
|
||||
|
||||
func test_play_next_song_increments_and_plays():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_music_player = mock(MusicPlayer)
|
||||
|
||||
main_window.music_player_container = mock_music_player
|
||||
|
||||
Playlist.clear_song_list()
|
||||
Playlist.add_to_playlist(TestHelpers.create_test_song_object(1))
|
||||
Playlist.add_to_playlist(TestHelpers.create_test_song_object(2))
|
||||
Playlist.latest_played_song = 0
|
||||
Playlist.first_song_played = true
|
||||
|
||||
main_window.play_next_song()
|
||||
|
||||
assert_eq(Playlist.latest_played_song, 1)
|
||||
assert_true(mock_music_player.play_song_object.was_called_with([1]))
|
||||
|
||||
|
||||
func test_song_object_clicked_handles_left_click():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_music_player = mock(MusicPlayer)
|
||||
|
||||
main_window.music_player_container = mock_music_player
|
||||
|
||||
Playlist.clear_song_list()
|
||||
var song = TestHelpers.create_test_song_object(1)
|
||||
Playlist.add_to_playlist(song)
|
||||
|
||||
var mock_event = mock(InputEventMouseButton)
|
||||
mock_event.pressed = true
|
||||
mock_event.button_index = MOUSE_BUTTON_LEFT
|
||||
|
||||
main_window.song_object_clicked(mock_event, 0)
|
||||
|
||||
assert_true(mock_music_player.play_song_object.was_called_with([0]))
|
||||
|
||||
|
||||
func test_song_object_clicked_downloads_if_not_available():
|
||||
var main_window = MainWindow.new()
|
||||
var mock_music_player = mock(MusicPlayer)
|
||||
|
||||
main_window.music_player_container = mock_music_player
|
||||
|
||||
Playlist.clear_song_list()
|
||||
var song = TestHelpers.create_test_song_object(1)
|
||||
song.song = null # No song loaded
|
||||
Playlist.add_to_playlist(song)
|
||||
|
||||
var mock_event = mock(InputEventMouseButton)
|
||||
mock_event.pressed = true
|
||||
mock_event.button_index = MOUSE_BUTTON_LEFT
|
||||
|
||||
# Mock Settings.make_request2 for download
|
||||
var original_make_request = Settings.make_request2
|
||||
var download_called = false
|
||||
|
||||
Settings.make_request2 = func(address: String, func_name: Callable, expect_data: bool) -> void:
|
||||
if address.begins_with("/music?song="):
|
||||
download_called = true
|
||||
var test_stream = TestHelpers.create_mock_audio_stream()
|
||||
func_name.call(test_stream.get_data())
|
||||
|
||||
main_window.song_object_clicked(mock_event, 0)
|
||||
|
||||
assert_true(download_called)
|
||||
|
||||
Settings.make_request2 = original_make_request
|
||||
Reference in new issue
Block a user