diff --git a/CHANGELOG.md b/CHANGELOG.md index d2dfe16d..a5a1b631 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +**1.2.6** +- Show a loading screen on startup (thanks to orende) +- Hide Cyberpunk 2077 Digital Goodies and Xenonauts 2 Alpha demo (thanks to orende) + **1.2.5** - Fix filtering for installed games diff --git a/bin/minigalaxy b/bin/minigalaxy index 391f93fa..646faf3d 100755 --- a/bin/minigalaxy +++ b/bin/minigalaxy @@ -43,12 +43,13 @@ def main(): if cli_args.reset: conf_reset() # Import the gi module after parsing arguments - from minigalaxy.ui.gtk import Gtk - from minigalaxy.ui import Window + from minigalaxy.ui.gtk import Gtk, GLib + from minigalaxy.ui import Window, LoadingScreen from minigalaxy.config import Config from minigalaxy.api import Api from minigalaxy.download_manager import DownloadManager from minigalaxy.css import load_css + from minigalaxy.ui.library import Library # Start the application load_css() @@ -57,8 +58,11 @@ def main(): session.headers.update({'User-Agent': 'Minigalaxy/{} (Linux {})'.format(VERSION, platform.machine())}) api = Api(config, session) download_manager = DownloadManager(session) - window = Window(config, api, download_manager, APPLICATION_NAME) + library = Library(config, api, download_manager) + window = Window(config, api, library, APPLICATION_NAME) window.connect("destroy", Gtk.main_quit) + loading_screen = LoadingScreen() + library.initialize(loading_screen, window) Gtk.main() diff --git a/data/images/spiral_galaxy.jpg b/data/images/spiral_galaxy.jpg new file mode 100644 index 00000000..f7d285bd Binary files /dev/null and b/data/images/spiral_galaxy.jpg differ diff --git a/data/ui/loadingscreen.ui b/data/ui/loadingscreen.ui new file mode 100644 index 00000000..650d1d50 --- /dev/null +++ b/data/ui/loadingscreen.ui @@ -0,0 +1,42 @@ + + + + + diff --git a/minigalaxy/api.py b/minigalaxy/api.py index 7c0a0f39..e9019dc0 100644 --- a/minigalaxy/api.py +++ b/minigalaxy/api.py @@ -1,5 +1,4 @@ import http -import os import time from urllib.parse import urlencode import requests @@ -27,7 +26,6 @@ def __init__(self, config: Config, session: Session): self.redirect_uri = "https://embed.gog.com/on_login_success?origin=client" self.client_id = "46899977096215655" self.client_secret = "9d85c43b1482497dbbce61f6e4aa173a433796eeae2ca8c5f6129f2dc4de46d9" - self.debug = os.environ.get("MG_DEBUG") self.active_token = False self.active_token_expiration_time = time.time() self.conn_check_thpool = ThreadPoolExecutor(max_workers=2) @@ -284,8 +282,7 @@ def __request(self, url: str = None, params: dict = None) -> dict: result = {} try: response = self.session.get(url, headers=headers, params=params) - if self.debug: - logger.debug("Request %s, return code %s, response body %s", url, response.status_code, response.text) + logger.debug("Request %s, return code %s, response body %s", url, response.status_code, response.text) if response.status_code < 300: result = response.json() except requests.exceptions.RequestException: diff --git a/minigalaxy/constants.py b/minigalaxy/constants.py index d70290b3..8beda426 100644 --- a/minigalaxy/constants.py +++ b/minigalaxy/constants.py @@ -59,8 +59,10 @@ 1980301910, # The Witcher Goodies Collection 2005648906, # Spring Sale Goodies Collection #1 1486144755, # Cyberpunk 2077 Goodies Collection + 1548764757, # Cyberpunk 2077 Digital Goodies 1581684020, # A Plague Tale Digital Goodies Pack 1185685769, # CDPR Goodie Pack Content + 1497289938, # Xenonauts 2 alpha demo ] DOWNLOAD_CHUNK_SIZE = 1024 * 1024 # 1 MB diff --git a/minigalaxy/paths.py b/minigalaxy/paths.py index 470ef6ca..65d455c0 100644 --- a/minigalaxy/paths.py +++ b/minigalaxy/paths.py @@ -27,6 +27,10 @@ os.path.join(LAUNCH_DIR, "../share/icons/hicolor/192x192/apps/io.github.sharkwouter.Minigalaxy.png") ) +SPLASH_IMAGE_PATH = os.path.abspath(os.path.join(LAUNCH_DIR, "../data/images/spiral_galaxy.jpg")) +if not os.path.exists(SPLASH_IMAGE_PATH): + SPLASH_IMAGE_PATH = os.path.abspath(os.path.join(LAUNCH_DIR, "../share/minigalaxy/images/spiral_galaxy.jpg")) + ICON_WINE_PATH = os.path.abspath(os.path.join(LAUNCH_DIR, "../data/images/winehq_logo_glass.png")) if not os.path.exists(ICON_WINE_PATH): ICON_WINE_PATH = os.path.abspath(os.path.join(LAUNCH_DIR, "../share/minigalaxy/images/winehq_logo_glass.png")) diff --git a/minigalaxy/ui/__init__.py b/minigalaxy/ui/__init__.py index 34f2dcd5..bfce42a2 100644 --- a/minigalaxy/ui/__init__.py +++ b/minigalaxy/ui/__init__.py @@ -3,3 +3,4 @@ from minigalaxy.ui.window import Window # noqa: F401 from minigalaxy.ui.preferences import Preferences # noqa: F401 from minigalaxy.ui.gametile import GameTile # noqa: F401 +from minigalaxy.ui.loadingscreen import LoadingScreen # noqa: F401 diff --git a/minigalaxy/ui/gametile.py b/minigalaxy/ui/gametile.py index 0f378eaa..443043ec 100644 --- a/minigalaxy/ui/gametile.py +++ b/minigalaxy/ui/gametile.py @@ -19,8 +19,6 @@ from minigalaxy.paths import ICON_WINE_PATH from minigalaxy.api import NoDownloadLinkFound, Api from minigalaxy.ui.gtk import Gtk, GLib, Notify -from minigalaxy.ui.information import Information -from minigalaxy.ui.properties import Properties @Gtk.Template.from_file(os.path.join(UI_DIR, "gametile.ui")) @@ -41,7 +39,8 @@ class GameTile(Gtk.Box): menu_button_properties = Gtk.Template.Child() progress_bar = Gtk.Template.Child() - def __init__(self, parent, game: Game, config: Config, api: Api, download_manager: DownloadManager): + def __init__(self, parent, game: Game, config: Config, api: Api, download_manager: DownloadManager, + show_properties_callback, show_information_callback): self.config = config current_locale = self.config.locale default_locale = locale.getdefaultlocale()[0] @@ -63,6 +62,8 @@ def __init__(self, parent, game: Game, config: Config, api: Api, download_manage self.download_list = [] self.dlc_dict = {} self.current_state = State.DOWNLOADABLE + self.show_information_callback = show_information_callback + self.show_properties_callback = show_properties_callback self.image.set_tooltip_text(self.game.name) @@ -129,16 +130,12 @@ def on_button_click(self, widget) -> None: self.parent.parent.show_error(_("Failed to start {}:").format(self.game.name), err_msg) @Gtk.Template.Callback("on_menu_button_information_clicked") - def show_information(self, button): - information_window = Information(self, self.game, self.config, self.api, self.download_manager) - information_window.run() - information_window.destroy() + def on_menu_button_information(self, button): + self.show_information_callback(self.game, self.download_manager) @Gtk.Template.Callback("on_menu_button_properties_clicked") - def show_properties(self, button): - properties_window = Properties(self, self.game, self.api) - properties_window.run() - properties_window.destroy() + def on_menu_button_properties(self, button): + self.show_properties_callback(self.game) @Gtk.Template.Callback("on_button_cancel_clicked") def on_button_cancel(self, widget): diff --git a/minigalaxy/ui/gametilelist.py b/minigalaxy/ui/gametilelist.py index 542d4be9..22fb4dde 100644 --- a/minigalaxy/ui/gametilelist.py +++ b/minigalaxy/ui/gametilelist.py @@ -20,8 +20,6 @@ from minigalaxy.paths import ICON_WINE_PATH from minigalaxy.api import NoDownloadLinkFound, Api from minigalaxy.ui.gtk import Gtk, GLib, Notify -from minigalaxy.ui.information import Information -from minigalaxy.ui.properties import Properties @Gtk.Template.from_file(os.path.join(UI_DIR, "gametilelist.ui")) @@ -42,7 +40,8 @@ class GameTileList(Gtk.Box): menu_button_properties = Gtk.Template.Child() game_label = Gtk.Template.Child() - def __init__(self, parent, game: Game, config: Config, api: Api, download_manager: DownloadManager): + def __init__(self, parent, game: Game, config: Config, api: Api, download_manager: DownloadManager, + show_properties_callback, show_information_callback): self.config = config current_locale = self.config.locale default_locale = locale.getdefaultlocale()[0] @@ -67,6 +66,8 @@ def __init__(self, parent, game: Game, config: Config, api: Api, download_manage self.download_list = [] self.dlc_dict = {} self.current_state = State.DOWNLOADABLE + self.show_information_callback = show_information_callback + self.show_properties_callback = show_properties_callback self.image.set_tooltip_text(self.game.name) @@ -135,16 +136,12 @@ def on_button_click(self, widget) -> None: self.parent.parent.show_error(_("Failed to start {}:").format(self.game.name), err_msg) @Gtk.Template.Callback("on_menu_button_information_clicked") - def show_information(self, button): - information_window = Information(self, self.game, self.config, self.api, self.download_manager) - information_window.run() - information_window.destroy() + def on_menu_button_information(self, button): + self.show_information_callback(self.game, self.download_manager) @Gtk.Template.Callback("on_menu_button_properties_clicked") - def show_properties(self, button): - properties_window = Properties(self, self.game, self.api) - properties_window.run() - properties_window.destroy() + def on_menu_button_properties(self, button): + self.show_properties_callback(self.game) @Gtk.Template.Callback("on_button_cancel_clicked") def on_button_cancel(self, widget): diff --git a/minigalaxy/ui/information.py b/minigalaxy/ui/information.py index 58b8ce45..b75b677b 100644 --- a/minigalaxy/ui/information.py +++ b/minigalaxy/ui/information.py @@ -26,7 +26,7 @@ class Information(Gtk.Dialog): label_game_description = Gtk.Template.Child() def __init__(self, parent, game, config: Config, api: Api, download_manager: DownloadManager): - Gtk.Dialog.__init__(self, title=_("Information about {}").format(game.name), parent=parent.parent.parent, + Gtk.Dialog.__init__(self, title=_("Information about {}").format(game.name), parent=parent, modal=True) self.parent = parent self.game = game diff --git a/minigalaxy/ui/library.py b/minigalaxy/ui/library.py index 0db39502..d3e647e7 100644 --- a/minigalaxy/ui/library.py +++ b/minigalaxy/ui/library.py @@ -24,9 +24,8 @@ class Library(Gtk.Viewport): flowbox = Gtk.Template.Child() - def __init__(self, parent, config: Config, api: Api, download_manager: DownloadManager): + def __init__(self, config: Config, api: Api, download_manager: DownloadManager): Gtk.Viewport.__init__(self) - self.parent = parent self.config = config self.api = api self.download_manager = download_manager @@ -38,6 +37,28 @@ def __init__(self, parent, config: Config, api: Api, download_manager: DownloadM self._queue = [] self.category_filters = [] + def initialize(self, loading_screen, window): + worker_thread = threading.Thread(target=lambda: self._do_initialization(loading_screen, window)) + worker_thread.start() + + def _do_initialization(self, loading_screen, window): + logger.debug("Checking API connectivity...") + self.offline = not self.api.can_connect() + logger.debug("Done checking API connectivity, status: %s", "offline" if self.offline else "online") + if not self.offline: + try: + logger.debug("Authenticating...") + window.authenticate() + logger.debug("Authenticated as %s", self.api.get_user_info()) + window.set_subtitle(self.api.get_user_info()) + except Exception: + logger.warn("Starting in offline mode after receiving exception", exc_info=1) + self.offline = True + self.update_library(window.show_error, window.show_properties, window.show_information) + logger.debug("Worker thread done, closing loading screen, showing main window") + loading_screen.destroy() + window.show_all() + def _debounce(self, thunk): if thunk not in self._queue: self._queue.append(thunk) @@ -48,28 +69,32 @@ def _run_queue(self): for thunk in queue: GLib.idle_add(thunk) - def reset(self): + def reset(self, show_error_callback, show_properties_callback, show_information_callback): self.games = [] for child in self.flowbox.get_children(): self.flowbox.remove(child) self.flowbox.show_all() - self.update_library() + self.update_library(show_error_callback, show_properties_callback, show_information_callback) - def update_library(self) -> None: - library_update_thread = threading.Thread(target=self.__update_library) + def update_library(self, show_error_callback, show_properties_callback, show_information_callback) -> None: + library_update_thread = threading.Thread(target=self.__update_library, args=[show_error_callback, + show_properties_callback, + show_information_callback]) library_update_thread.daemon = True library_update_thread.start() - def __update_library(self): + def __update_library(self, show_error_callback, show_properties_callback, show_information_callback): GLib.idle_add(self.__load_tile_states) self.owned_products_ids = self.api.get_owned_products_ids() # Get already installed games first self.games = self.__get_installed_games() - GLib.idle_add(self.__create_gametiles) + GLib.idle_add(self.__create_gametiles, show_properties_callback, show_information_callback) # Get games from the API - self.__add_games_from_api() - GLib.idle_add(self.__create_gametiles) + is_offline, err_msg = self.__add_games_from_api() + if is_offline: + GLib.idle_add(show_error_callback, _("Failed to retrieve library"), _(err_msg)) + GLib.idle_add(self.__create_gametiles, show_properties_callback, show_information_callback) GLib.idle_add(self.filter_library) def __load_tile_states(self): @@ -113,7 +138,7 @@ def __sort_library_func(self, child1, child2): tile2 = child2.get_children()[0].game return tile2 < tile1 - def __create_gametiles(self) -> None: + def __create_gametiles(self, show_properties_callback, show_information_callback) -> None: games_with_tiles = [] for child in self.flowbox.get_children(): tile = child.get_children()[0] @@ -122,14 +147,16 @@ def __create_gametiles(self) -> None: for game in self.games: if game not in games_with_tiles: - self.__add_gametile(game) + self.__add_gametile(game, show_properties_callback, show_information_callback) - def __add_gametile(self, game): + def __add_gametile(self, game, show_properties_callback, show_information_callback): view = self.config.view if view == "grid": - self.flowbox.add(GameTile(self, game, self.config, self.api, self.download_manager)) + self.flowbox.add(GameTile(self, game, self.config, self.api, self.download_manager, + show_properties_callback, show_information_callback)) elif view == "list": - self.flowbox.add(GameTileList(self, game, self.config, self.api, self.download_manager)) + self.flowbox.add(GameTileList(self, game, self.config, self.api, self.download_manager, + show_properties_callback, show_information_callback)) self._debounce(self.sort_library) self._debounce(self.flowbox.show_all) @@ -172,7 +199,6 @@ def __add_games_from_api(self): else: self.offline = True logger.info("Client is offline, showing installed games only") - GLib.idle_add(self.parent.show_error, _("Failed to retrieve library"), _(err_msg)) game_category_dict = {} for game in retrieved_games: if game not in self.games: @@ -186,6 +212,7 @@ def __add_games_from_api(self): if len(game.category) > 0: # exclude games without set category game_category_dict[game.name] = game.category update_game_categories_file(game_category_dict, CATEGORIES_FILE_PATH) + return self.offline, err_msg def get_installed_windows_games(full_path, game_categories_dict=None): diff --git a/minigalaxy/ui/loadingscreen.py b/minigalaxy/ui/loadingscreen.py new file mode 100644 index 00000000..a1b317db --- /dev/null +++ b/minigalaxy/ui/loadingscreen.py @@ -0,0 +1,17 @@ +import os + +from minigalaxy.paths import UI_DIR, SPLASH_IMAGE_PATH +from minigalaxy.ui.gtk import Gtk + + +@Gtk.Template.from_file(os.path.join(UI_DIR, "loadingscreen.ui")) +class LoadingScreen(Gtk.Dialog): + __gtype_name__ = "LoadingScreen" + + splash_image = Gtk.Template.Child() + splash_label = Gtk.Template.Child() + + def __init__(self): + super().__init__(title="Loading - Minigalaxy", modal=True) + self.splash_image.set_from_file(SPLASH_IMAGE_PATH) + self.show_all() diff --git a/minigalaxy/ui/properties.py b/minigalaxy/ui/properties.py index ec8eacac..a478168f 100644 --- a/minigalaxy/ui/properties.py +++ b/minigalaxy/ui/properties.py @@ -31,7 +31,7 @@ class Properties(Gtk.Dialog): label_wine_custom = Gtk.Template.Child() def __init__(self, parent, game, api): - Gtk.Dialog.__init__(self, title=_("Properties of {}").format(game.name), parent=parent.parent.parent, + Gtk.Dialog.__init__(self, title=_("Properties of {}").format(game.name), parent=parent, modal=True) self.parent = parent self.game = game diff --git a/minigalaxy/ui/window.py b/minigalaxy/ui/window.py index 20fb2977..b07a533f 100644 --- a/minigalaxy/ui/window.py +++ b/minigalaxy/ui/window.py @@ -2,8 +2,10 @@ import locale from minigalaxy.download_manager import DownloadManager +from minigalaxy.game import Game from minigalaxy.logger import logger from minigalaxy.ui.categoryfilters import CategoryFilters +from minigalaxy.ui.information import Information from minigalaxy.ui.login import Login from minigalaxy.ui.preferences import Preferences from minigalaxy.ui.about import About @@ -13,6 +15,7 @@ from minigalaxy.ui.library import Library from minigalaxy.ui.gtk import Gtk, Gdk, GdkPixbuf, Notify from minigalaxy.config import Config +from minigalaxy.ui.properties import Properties @Gtk.Template.from_file(os.path.join(UI_DIR, "application.ui")) @@ -28,7 +31,7 @@ class Window(Gtk.ApplicationWindow): menu_logout = Gtk.Template.Child() window_library = Gtk.Template.Child() - def __init__(self, config: Config, api: 'Api', download_manager: DownloadManager, name="Minigalaxy"): + def __init__(self, config: Config, api: 'Api', library: Library, name="Minigalaxy"): current_locale = config.locale default_locale = locale.getdefaultlocale()[0] if current_locale == '': @@ -43,14 +46,11 @@ def __init__(self, config: Config, api: 'Api', download_manager: DownloadManager self.api = api self.config = config self.search_string = "" - self.offline = False # Initialize notifications module Notify.init("minigalaxy") - # Set library - self.library = Library(self, config, api, download_manager) - + self.library = library self.window_library.add(self.library) self.header_installed.set_active(self.config.installed_filter) @@ -65,28 +65,12 @@ def __init__(self, config: Config, api: 'Api', download_manager: DownloadManager else: settings.set_property("gtk-application-prefer-dark-theme", False) - # Show the window + # Maximize the window if self.config.keep_window_maximized: self.maximize() - self.show_all() self.make_directories() - # Interact with the API - logger.debug("Checking API connectivity...") - self.offline = not self.api.can_connect() - logger.debug("Done checking API connectivity, status: %s", "offline" if self.offline else "online") - if not self.offline: - try: - logger.debug("Authenticating...") - self.__authenticate() - logger.debug("Authenticated as: %s", self.api.get_user_info()) - self.HeaderBar.set_subtitle(self.api.get_user_info()) - except Exception: - logger.warn("Starting in offline mode after receiving exception", exc_info=1) - self.offline = True - self.sync_library() - @Gtk.Template.Callback("filter_library") def filter_library(self, switch, _=""): self.library.filter_library(switch) @@ -111,17 +95,28 @@ def show_categories(self, button): category_filters_window.run() category_filters_window.destroy() + def show_properties(self, game: Game): + properties_window = Properties(self, game, self.api) + properties_window.run() + properties_window.destroy() + + def show_information(self, game: Game, download_manager: DownloadManager): + information_window = Information(self, game, self.config, self.api, download_manager) + information_window.run() + information_window.destroy() + @Gtk.Template.Callback("on_menu_logout_clicked") def logout(self, button): question = _("Are you sure you want to log out of GOG?") if self.show_question(question): + logger.debug("Logging user %s out", self.config.username) # Unset everything which is specific to this user self.HeaderBar.set_subtitle("") self.config.username = "" self.config.refresh_token = "" self.hide() # Show the login screen - self.__authenticate() + self.authenticate() self.HeaderBar.set_subtitle(self.api.get_user_info()) self.sync_library() self.show_all() @@ -136,8 +131,8 @@ def on_window_state_event(self, widget, event): @Gtk.Template.Callback("on_header_sync_clicked") def sync_library(self, _=""): if self.library.offline: - self.__authenticate() - self.library.update_library() + self.authenticate() + self.library.update_library(self.show_error, self.show_properties, self.show_information) def make_directories(self): # Create the thumbnails directory @@ -150,11 +145,11 @@ def make_directories(self): if not os.path.exists(ICON_DIR): os.makedirs(ICON_DIR, mode=0o755) - def reset_library(self): - self.library.reset() + def set_subtitle(self, subtitle_text): + self.HeaderBar.set_subtitle(subtitle_text) - def update_library(self): - self.library.update_library() + def reset_library(self): + self.library.reset(self.show_error, self.show_properties, self.show_information) def show_error(self, text, secondary_text=""): dialog = Gtk.MessageDialog( @@ -190,7 +185,7 @@ def show_question(self, text, secondary_text=""): The token is not valid for a long time """ - def __authenticate(self): + def authenticate(self): url = None if self.config.stay_logged_in: token = self.config.refresh_token diff --git a/tests/test_ui_library.py b/tests/test_ui_library.py index 30774159..c6f0e850 100644 --- a/tests/test_ui_library.py +++ b/tests/test_ui_library.py @@ -2,6 +2,7 @@ import os import sys import uuid +from json import JSONDecodeError from unittest import TestCase, mock from unittest.mock import MagicMock, patch, mock_open import tempfile @@ -13,10 +14,13 @@ m_gametile = MagicMock() m_gametilelist = MagicMock() m_categoryfilters = MagicMock() +m_loadingscreen = MagicMock() class UnitTestGtkTemplate: + Callback = MagicMock() + def __init__(self): self.Child = m_gtk @@ -34,6 +38,10 @@ class Gtk: Template = UnitTestGtkTemplate() Widget = m_gtk + Box = m_gtk + Dialog = m_gtk + AboutDialog = m_gtk + ApplicationWindow = m_gtk class Viewport: pass @@ -47,8 +55,7 @@ class GdkPixbuf: class Gio: pass - class GLib: - pass + GLib = MagicMock() class Notify: pass @@ -62,6 +69,7 @@ class Notify: sys.modules['minigalaxy.ui.gametile'] = m_gametile sys.modules['minigalaxy.ui.gametilelist'] = m_gametilelist sys.modules['minigalaxy.ui.categoryfilters'] = m_categoryfilters +sys.modules['minigalaxy.ui.loadingscreen'] = m_loadingscreen from minigalaxy.game import Game # noqa: E402 from minigalaxy.ui.library import Library, get_installed_windows_games, read_game_categories_file, \ update_game_categories_file # noqa: E402 @@ -79,6 +87,56 @@ class Notify: class TestLibrary(TestCase): + + def test_init_happy_path(self): + with patch('os.listdir', return_value=[]): + config_mock = MagicMock() + config_mock.locale = "en_US.UTF-8" + config_mock.keep_window_maximized = False + api_mock = MagicMock() + api_mock.authenticate.return_value = True + download_manager_mock = MagicMock() + test_library = Library(config=config_mock, api=api_mock, download_manager=download_manager_mock) + loading_screen_mock = MagicMock() + window_mock = MagicMock() + test_library._do_initialization(loading_screen_mock, window_mock) + expected = False + actual = test_library.offline + self.assertEqual(expected, actual) + window_mock.authenticate.assert_called_once() + + def test_init_fallback_to_offline_mode(self): + with patch('os.listdir', return_value=[]): + config = MagicMock() + config.locale = "en_US.UTF-8" + config.keep_window_maximized = False + api = MagicMock() + api.can_connect.return_value = False + download_manager = MagicMock() + test_library = Library(config=config, api=api, download_manager=download_manager) + loading_screen_mock = MagicMock() + window_mock = MagicMock() + test_library._do_initialization(loading_screen_mock, window_mock) + expected = True + actual = test_library.offline + self.assertEqual(expected, actual) + + def test_init_network_error_should_lead_to_offline_mode(self): + with patch('os.listdir', return_value=[]): + config = MagicMock() + config.locale = "en_US.UTF-8" + config.keep_window_maximized = False + api = MagicMock() + download_manager = MagicMock() + test_library = Library(config=config, api=api, download_manager=download_manager) + loading_screen_mock = MagicMock() + window_mock = MagicMock() + window_mock.authenticate.side_effect = JSONDecodeError(msg='mock', doc='mock', pos=0) + test_library._do_initialization(loading_screen_mock, window_mock) + expected = True + actual = test_library.offline + self.assertEqual(expected, actual) + def test1_add_games_from_api(self): self_games = [] for game in SELF_GAMES: @@ -90,7 +148,8 @@ def test1_add_games_from_api(self): config = MagicMock() api_mock = MagicMock() api_mock.get_library.return_value = api_games, err_msg - test_library = Library(MagicMock(), config, api_mock, MagicMock()) + download_manager = MagicMock() + test_library = Library(config=config, api=api_mock, download_manager=download_manager) test_library.games = self_games test_library._Library__add_games_from_api() exp = len(API_GAMES) @@ -108,7 +167,8 @@ def test2_add_games_from_api(self): config = MagicMock() api_mock = MagicMock() api_mock.get_library.return_value = api_games, err_msg - test_library = Library(MagicMock(), config, api_mock, MagicMock()) + download_manager = MagicMock() + test_library = Library(config=config, api=api_mock, download_manager=download_manager) test_library.games = self_games test_library._Library__add_games_from_api() exp = True @@ -129,7 +189,8 @@ def test3_add_games_from_api(self): config = MagicMock() api_mock = MagicMock() api_mock.get_library.return_value = api_games, err_msg - test_library = Library(MagicMock(), config, api_mock, MagicMock()) + download_manager = MagicMock() + test_library = Library(config=config, api=api_mock, download_manager=download_manager) test_library.games = self_games test_library._Library__add_games_from_api() exp = True @@ -152,7 +213,8 @@ def test4_add_games_from_api(self): config = MagicMock() api_mock = MagicMock() api_mock.get_library.return_value = api_games, err_msg - test_library = Library(MagicMock(), config, api_mock, MagicMock()) + download_manager = MagicMock() + test_library = Library(config=config, api=api_mock, download_manager=download_manager) test_library.games = self_games test_library._Library__add_games_from_api() exp = "http://test_url1" @@ -170,7 +232,8 @@ def test5_add_games_from_api(self): config = MagicMock() api_mock = MagicMock() api_mock.get_library.return_value = api_games, err_msg - test_library = Library(MagicMock(), config, api_mock, MagicMock()) + download_manager = MagicMock() + test_library = Library(config=config, api=api_mock, download_manager=download_manager) test_library.games = self_games test_library._Library__add_games_from_api() exp = "Neverwinter Nights: Enhanced Edition" @@ -184,7 +247,8 @@ def test6_add_games_from_api(self): config = MagicMock() api_mock = MagicMock() api_mock.get_library.return_value = api_games, err_msg - test_library = Library(MagicMock(), config, api_mock, MagicMock()) + download_manager = MagicMock() + test_library = Library(config=config, api=api_mock, download_manager=download_manager) test_library.games = self_games test_library._Library__add_games_from_api() exp = 1 diff --git a/tests/test_ui_window.py b/tests/test_ui_window.py index 8725c731..b87098a5 100644 --- a/tests/test_ui_window.py +++ b/tests/test_ui_window.py @@ -1,7 +1,6 @@ import sys -from unittest import TestCase -from unittest.mock import MagicMock, patch -from simplejson.errors import JSONDecodeError +from unittest import TestCase, skip +from unittest.mock import MagicMock m_gtk = MagicMock() m_gi = MagicMock() @@ -10,6 +9,9 @@ m_login = MagicMock() m_about = MagicMock() m_categoryfilters = MagicMock() +m_properties = MagicMock() +m_information = MagicMock() +m_game = MagicMock() class UnitTestGtkTemplate: @@ -58,44 +60,16 @@ def __init__(self, title): sys.modules['minigalaxy.ui.about'] = m_about sys.modules['minigalaxy.ui.gtk'] = u_gi_repository sys.modules['minigalaxy.ui.categoryfilters'] = m_categoryfilters -from minigalaxy.ui.window import Window # noqa: E402 +sys.modules['minigalaxy.ui.properties'] = m_properties +sys.modules['minigalaxy.ui.information'] = m_information +sys.modules['minigalaxy.ui.game'] = m_game +# from minigalaxy.ui.window import Window # noqa: E402 class TestWindow(TestCase): + @skip("no significant logic to test left in constructor") def test1_init(self): - with patch('minigalaxy.ui.window.Api.can_connect', return_value=False): - config = MagicMock() - config.locale = "en_US.UTF-8" - config.keep_window_maximized = False - api = MagicMock() - api.can_connect.return_value = False - test_window = Window(api=api, config=config, download_manager=MagicMock()) - exp = True - obs = test_window.offline - self.assertEqual(exp, obs) - - def test2_init(self): - config = MagicMock() - config.locale = "en_US.UTF-8" - config.keep_window_maximized = False - api = MagicMock() - api.authenticate.return_value = True - test_window = Window(api=api, config=config, download_manager=MagicMock()) - exp = False - obs = test_window.offline - self.assertEqual(exp, obs) - api.authenticate.assert_called_once() - - def test3_init(self): - config = MagicMock() - config.locale = "en_US.UTF-8" - config.keep_window_maximized = False - api = MagicMock() - api.authenticate.side_effect = JSONDecodeError(msg='mock', doc='mock', pos=0) - test_window = Window(api=api, config=config, download_manager=MagicMock()) - exp = True - obs = test_window.offline - self.assertEqual(exp, obs) + pass del sys.modules['gi'] @@ -105,3 +79,7 @@ def test3_init(self): del sys.modules['minigalaxy.ui.login'] del sys.modules['minigalaxy.ui.about'] del sys.modules['minigalaxy.ui.gtk'] +del sys.modules['minigalaxy.ui.categoryfilters'] +del sys.modules['minigalaxy.ui.properties'] +del sys.modules['minigalaxy.ui.information'] +del sys.modules['minigalaxy.ui.game']