Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "OneLauncher"
version = "2.0.2"
description = "The OneLauncher to rule them all"
authors = [{ name = "June Stepp", email = "contact@junestepp.me" }]
requires-python = ">=3.11,<3.12"
requires-python = ">=3.11"
readme = "README.md"
license = "GPL-3.0-or-later"
keywords = ["LOTRO", "DDO", "launcher", "addon-manager", "custom-launcher"]
Expand Down
78 changes: 39 additions & 39 deletions src/onelauncher/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,45 @@ async def start_game(self, game_launcher_config: GameLauncherConfig) -> None:
subscription = game_subscriptions[0]
account_number = subscription.name

selected_world: World = self.ui.cboWorld.currentData()

try:
selected_world_status = await selected_world.get_status()
except httpx.HTTPError:
logger.exception("Network error while fetching world status")
return
except WorldUnavailableError:
logger.exception(
"Error fetching world status. You may want to check "
"the news feed for a scheduled down time.",
)
return
except XMLSchemaValidationError:
logger.exception(
"World status info has incompatible format. Please report "
"this issue if using a supported game server",
)
return

if selected_world_status.queue_url != "":
await self.world_queue(
queueURL=selected_world_status.queue_url,
account_number=account_number,
login_response=login_response,
game_launcher_config=game_launcher_config,
)
game = StartGame(
game_id=self.game_id,
config_manager=self.config_manager,
game_launcher_local_config=self.game_launcher_local_config,
game_launcher_config=game_launcher_config,
world=selected_world,
login_server=selected_world_status.login_server,
account_number=account_number,
ticket=login_response.session_ticket,
)
await game.start_game()

if self.ui.chkSaveAccount.isChecked():
if len(game_subscriptions) > 1:
self.config_manager.save_game_account_last_used_subscription_name(
Expand Down Expand Up @@ -626,45 +665,6 @@ async def start_game(self, game_launcher_config: GameLauncherConfig) -> None:
self.config_manager.update_game_accounts_config_file(self.game_id, ())
self.loadAllSavedAccounts()

selected_world: World = self.ui.cboWorld.currentData()

try:
selected_world_status = await selected_world.get_status()
except httpx.HTTPError:
logger.exception("Network error while fetching world status")
return
except WorldUnavailableError:
logger.exception(
"Error fetching world status. You may want to check "
"the news feed for a scheduled down time.",
)
return
except XMLSchemaValidationError:
logger.exception(
"World status info has incompatible format. Please report "
"this issue if using a supported game server",
)
return

if selected_world_status.queue_url != "":
await self.world_queue(
queueURL=selected_world_status.queue_url,
account_number=account_number,
login_response=login_response,
game_launcher_config=game_launcher_config,
)
game = StartGame(
game_id=self.game_id,
config_manager=self.config_manager,
game_launcher_local_config=self.game_launcher_local_config,
game_launcher_config=game_launcher_config,
world=selected_world,
login_server=selected_world_status.login_server,
account_number=account_number,
ticket=login_response.session_ticket,
)
await game.start_game()

async def world_queue(
self,
queueURL: str,
Expand Down
4 changes: 2 additions & 2 deletions src/onelauncher/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ class CaseInsensitiveAbsolutePath(Path):
"""

_flavour = (
pathlib._windows_flavour # type: ignore[attr-defined]
pathlib.PureWindowsPath._flavour # type: ignore[attr-defined]
if os.name == "nt"
else pathlib._posix_flavour # type: ignore[attr-defined]
else pathlib.PurePosixPath._flavour # type: ignore[attr-defined]
)

def __new__(cls, *pathsegments: StrPath) -> Self:
Expand Down
55 changes: 55 additions & 0 deletions tests/onelauncher/test_main_window.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from __future__ import annotations

from unittest.mock import MagicMock, patch

import pytest
from PySide6 import QtWidgets

from onelauncher.game_account_config import GameAccountConfig
from onelauncher.main_window import MainWindow


@pytest.fixture
def mock_config_manager():
manager = MagicMock()
manager.get_game_accounts.return_value = [
GameAccountConfig(username="testuser", last_used_world_name="World1")
]
manager.get_game_config.return_value.name = "Test Game"
manager.get_program_config.return_value.games_sorting_mode = "alphabetical"
manager.get_games_sorted.return_value = ["test_game"]
manager.get_game_config_ids.return_value = ["test_game"]
return manager


def test_world_not_saved_on_failed_login(mock_config_manager):
app = QtWidgets.QApplication.instance() or QtWidgets.QApplication([])

with patch("onelauncher.main_window.StartGame") as mock_start_game, \
patch("onelauncher.main_window.MainWindow.authenticate_account", new_callable=MagicMock) as mock_authenticate:
# Simulate a failed game launch
mock_start_game.return_value.start_game.side_effect = Exception(
"Game launch failed"
)
mock_authenticate.return_value = MagicMock()

main_window = MainWindow(
config_manager=mock_config_manager, starting_game_id="test_game"
)
main_window.setup_ui()
main_window.game_launcher_config = MagicMock()
main_window.game_launcher_local_config = MagicMock()
main_window.ui.cboAccount.setCurrentText("testuser")
main_window.ui.cboWorld.addItem("World2")
main_window.ui.cboWorld.setCurrentText("World2")

def mock_start_soon(target, *args, **kwargs):
target(*args, **kwargs)

with patch('trio.open_nursery', new_callable=MagicMock) as mock_nursery:
mock_nursery.start_soon = mock_start_soon
with pytest.raises(Exception, match="Game launch failed"):
main_window.btnLoginClicked()

# Assert that the last used world was NOT updated
mock_config_manager.update_game_accounts_config_file.assert_not_called()
Loading