From 5b318f2dbc7747b3c56dc17458c239e9ebd12a5a Mon Sep 17 00:00:00 2001 From: Maurane GLAUDE Date: Fri, 30 Aug 2024 11:00:31 +0200 Subject: [PATCH 1/9] fix(gui.windows): fix shortcut not created --- src/antares_web_installer/app.py | 30 +++++++++++-------- src/antares_web_installer/gui/controller.py | 18 +++++++++++ .../shortcuts/_win32_shell.py | 11 ------- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index e9f038b..364b993 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -21,7 +21,7 @@ from antares_web_installer.shortcuts import create_shortcut, get_desktop # List of files and directories to exclude during installation -COMMON_EXCLUDED_FILES = {"config.prod.yaml", "config.yaml", "examples", "logs", "matrices", "tmp"} +COMMON_EXCLUDED_FILES = {"config.prod.yaml", "config.yaml", "examples", "logs", "matrices", "tmp", "*.zip"} POSIX_EXCLUDED_FILES = COMMON_EXCLUDED_FILES | {"AntaresWebWorker"} WINDOWS_EXCLUDED_FILES = COMMON_EXCLUDED_FILES | {"AntaresWebWorker.exe"} EXCLUDED_FILES = POSIX_EXCLUDED_FILES if os.name == "posix" else WINDOWS_EXCLUDED_FILES @@ -47,6 +47,7 @@ class App: progress: float = dataclasses.field(init=False) nb_steps: int = dataclasses.field(init=False) completed_step: int = dataclasses.field(init=False) + version: str = dataclasses.field(init=False) def __post_init__(self): # Prepare the path to the executable which is located in the target directory @@ -123,15 +124,15 @@ def install_files(self): if self.target_dir.is_dir() and list(self.target_dir.iterdir()): logger.info("Existing files were found. Proceed checking old version...") # check app version - version = self.check_version() - logger.info(f"Old application version : {version}.") + old_version = self.check_version() + logger.info(f"Old application version : {old_version}.") self.update_progress(25) # update config file logger.info("Update configuration file...") src_config_path = self.source_dir.joinpath("config.yaml") target_config_path = self.target_dir.joinpath("config.yaml") - update_config(src_config_path, target_config_path, version) + update_config(src_config_path, target_config_path, old_version) logger.info("Configuration file updated.") self.update_progress(50) @@ -143,8 +144,8 @@ def install_files(self): # check new version of the application logger.info("Check new application version...") - version = self.check_version() - logger.info(f"New application version : {version}.") + self.version = self.check_version() + logger.info(f"New application version : {self.version}.") self.update_progress(100) else: @@ -217,9 +218,12 @@ def create_shortcuts(self): Create a local server icon and a browser icon on desktop and """ # prepare a shortcut into the desktop directory + desktop_path = Path(get_desktop()) + logger.info("Generating server shortcut on desktop...") - shortcut_name = SHORTCUT_NAMES[os.name] - shortcut_path = Path(get_desktop()).joinpath(shortcut_name) + shortcut_name, shortcut_ext = SHORTCUT_NAMES[os.name].split('.') + new_shortcut_name = f"{shortcut_name}-{self.version}.{shortcut_ext}" + shortcut_path = desktop_path.joinpath(new_shortcut_name) # if the shortcut already exists, remove it shortcut_path.unlink(missing_ok=True) @@ -227,7 +231,7 @@ def create_shortcuts(self): # shortcut generation logger.info( - f"Shortcut will be created in {shortcut_path}, " + f"Shortcut {new_shortcut_name} will be created in {shortcut_path}, " f"linked to '{self.server_path}' " f"and located in '{self.target_dir}' directory." ) @@ -242,7 +246,8 @@ def create_shortcuts(self): except com_error as e: raise InstallError("Impossible to create a new shortcut: {}\nSkip shortcut creation".format(e)) else: - logger.info("Server shortcut was successfully created.") + assert shortcut_path in list(desktop_path.iterdir()) + logger.info(f"Server shortcut {shortcut_path} was successfully created.") self.update_progress(100) def start_server(self): @@ -287,8 +292,9 @@ def start_server(self): nb_attempts += 1 if nb_attempts == max_attempts: try: - server_process.wait(timeout=5) - except subprocess.TimeoutExpired as e: + httpx.get("http://localhost:8080/", timeout=1) + except httpx.ConnectTimeout: + logger.error("Impossible to launch Antares Web Server after {nb_attempts} attempts.") raise InstallError(f"Impossible to launch Antares Web Server after {nb_attempts} attempts: {e}") time.sleep(5) diff --git a/src/antares_web_installer/gui/controller.py b/src/antares_web_installer/gui/controller.py index f038c13..218bcc7 100644 --- a/src/antares_web_installer/gui/controller.py +++ b/src/antares_web_installer/gui/controller.py @@ -90,18 +90,36 @@ def init_log_file_handler(self): # initialize file handler logger def init_console_handler(self, callback): + """ + + @param callback: + @return: + """ console_handler = ConsoleHandler(callback) self.logger.addHandler(console_handler) def init_progress_handler(self, callback): + """ + Initialize handler log of progress. + The logs generated will be shown on the window console during installation + @param callback: function that is used to update logs + """ progress_logger = ProgressHandler(callback) self.logger.addHandler(progress_logger) def run(self) -> None: + """ + start program + @return: + """ self.view.update_view() super().run() def install(self, callback: typing.Callable): + """ + Run App.install method + @param callback: function that is used to update logs + """ self.init_log_file_handler() self.logger.debug("file logger initialized.") self.init_console_handler(callback) diff --git a/src/antares_web_installer/shortcuts/_win32_shell.py b/src/antares_web_installer/shortcuts/_win32_shell.py index e1e7c6d..205095a 100644 --- a/src/antares_web_installer/shortcuts/_win32_shell.py +++ b/src/antares_web_installer/shortcuts/_win32_shell.py @@ -56,14 +56,6 @@ def create_shortcut( if isinstance(arguments, str): arguments = [arguments] if arguments else [] - target_parent, target_name = str(target).rsplit("\\", maxsplit=1) - new_target_name = "Antares Web Server.lnk" - new_target = os.path.join(target_parent, new_target_name) - - # remove any existing shortcut - if os.path.exists(new_target): - os.remove(new_target) - wscript = _WSHELL.CreateShortCut(str(target)) wscript.TargetPath = str(exe_path) wscript.Arguments = " ".join(arguments) @@ -74,6 +66,3 @@ def create_shortcut( if icon_path: wscript.IconLocation = str(icon_path) wscript.save() - - # add spaces to shortcut name - os.rename(target, new_target) From ad9969eac546580dc7d7e437d8d772017dbc161f Mon Sep 17 00:00:00 2001 From: Maurane GLAUDE Date: Fri, 30 Aug 2024 13:26:40 +0200 Subject: [PATCH 2/9] fix(gui.create_shortcut): fix version checking missing --- src/antares_web_installer/app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 364b993..05f6289 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -153,6 +153,7 @@ def install_files(self): logger.info("No existing files found. Starting file copy...") copytree(self.source_dir, self.target_dir, dirs_exist_ok=True) logger.info("Files was successfully copied.") + self.version = self.check_version() self.update_progress(100) def copy_files(self): From e27b7234b513b0d81e880737ce41b43b2f4596cc Mon Sep 17 00:00:00 2001 From: Maurane GLAUDE Date: Fri, 30 Aug 2024 15:10:26 +0200 Subject: [PATCH 3/9] fix(tests): add comments and improve tests --- src/antares_web_installer/app.py | 4 ++-- tests/integration/test_app.py | 24 ++++++++++++++++-------- tests/test_app.py | 6 +++++- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 05f6289..9d74488 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -222,8 +222,8 @@ def create_shortcuts(self): desktop_path = Path(get_desktop()) logger.info("Generating server shortcut on desktop...") - shortcut_name, shortcut_ext = SHORTCUT_NAMES[os.name].split('.') - new_shortcut_name = f"{shortcut_name}-{self.version}.{shortcut_ext}" + name, ext = SHORTCUT_NAMES[os.name].split('.') + new_shortcut_name = f"{name}-{self.version}.{ext}" shortcut_path = desktop_path.joinpath(new_shortcut_name) # if the shortcut already exists, remove it diff --git a/tests/integration/test_app.py b/tests/integration/test_app.py index fda8f71..6d4c184 100644 --- a/tests/integration/test_app.py +++ b/tests/integration/test_app.py @@ -2,10 +2,12 @@ import shutil from difflib import SequenceMatcher from pathlib import Path +from typing import Any import psutil import pytest from _pytest.monkeypatch import MonkeyPatch +import re from antares_web_installer.app import App from tests.samples import SAMPLES_DIR @@ -67,7 +69,7 @@ class TestApp: Integration tests for the app """ - def test_run__empty_target(self, downloaded_dir: Path, program_dir: Path, settings: None) -> None: + def test_run__empty_target(self, downloaded_dir: Path, program_dir: Path, settings: Any) -> None: """ The goal of this test is to verify the behavior of the application when: - The Antares server is not running @@ -84,18 +86,24 @@ def test_run__empty_target(self, downloaded_dir: Path, program_dir: Path, settin app = App(source_dir=application_dir, target_dir=program_dir, shortcut=True, launch=True) app.run() - def test_shortcut__created(self, downloaded_dir: Path, program_dir: Path, desktop_dir: Path, settings: None): + def test_shortcut__created(self, downloaded_dir: Path, program_dir: Path, desktop_dir: Path, settings: Any): for application_dir in downloaded_dir.iterdir(): # Run the application app = App(source_dir=application_dir, target_dir=program_dir, shortcut=True, launch=True) app.run() - desktop_files = [file_name.name for file_name in list(desktop_dir.iterdir())] - - if os.name != "nt": - assert "AntaresWebServer.desktop" in desktop_files - else: - assert "Antares Web Server.lnk" in desktop_files + match = 0 + + for file in list(desktop_dir.iterdir()): + if os.name == "nt": + pattern = re.compile(r"AntaresWebServer-([0-9]*\.){3}lnk") + if pattern.fullmatch(file.name): + match += 1 + else: + pattern = re.compile(r"AntaresWebServer-([0-9]*\.){3}desktop") + if pattern.fullmatch(file.name): + match += 1 + assert match == 1 def test_shortcut__not_created(self): """ diff --git a/tests/test_app.py b/tests/test_app.py index 1260cf9..3017eb3 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,5 +1,8 @@ import hashlib from pathlib import Path + +import pytest + from antares_web_installer.app import App, EXCLUDED_FILES @@ -13,7 +16,7 @@ def test_kill_running_server(self) -> None: # 3. Vérifier que le serveur a bien été tué pass - def test_install_files__from_scratch(self, tmp_path: Path) -> None: + def test_install_files__from_scratch(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: """ Case where the target directory does not exist. """ @@ -21,6 +24,7 @@ def test_install_files__from_scratch(self, tmp_path: Path) -> None: source_dir = tmp_path / "source" source_dir.mkdir() target_dir = tmp_path / "target" + monkeypatch.setattr("antares_web_installer.app.App.check_version", lambda _: "2.17.0") # Say we have dummy files in the source directory expected_files = ["dummy.txt", "folder/dummy2.txt"] From 1962e4481cc9b2802d4ff121381c213431d7782a Mon Sep 17 00:00:00 2001 From: Maurane GLAUDE Date: Tue, 10 Sep 2024 11:42:08 +0200 Subject: [PATCH 4/9] fix(gui.windows): reformat code with ruff --- src/antares_web_installer/app.py | 4 ++-- src/antares_web_installer/gui/controller.py | 6 +++--- src/antares_web_installer/gui/widgets/frame.py | 9 +++++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 9d74488..1e13bac 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -222,7 +222,7 @@ def create_shortcuts(self): desktop_path = Path(get_desktop()) logger.info("Generating server shortcut on desktop...") - name, ext = SHORTCUT_NAMES[os.name].split('.') + name, ext = SHORTCUT_NAMES[os.name].split(".") new_shortcut_name = f"{name}-{self.version}.{ext}" shortcut_path = desktop_path.joinpath(new_shortcut_name) @@ -294,7 +294,7 @@ def start_server(self): if nb_attempts == max_attempts: try: httpx.get("http://localhost:8080/", timeout=1) - except httpx.ConnectTimeout: + except httpx.ConnectTimeout as e: logger.error("Impossible to launch Antares Web Server after {nb_attempts} attempts.") raise InstallError(f"Impossible to launch Antares Web Server after {nb_attempts} attempts: {e}") time.sleep(5) diff --git a/src/antares_web_installer/gui/controller.py b/src/antares_web_installer/gui/controller.py index 218bcc7..8afd4a7 100644 --- a/src/antares_web_installer/gui/controller.py +++ b/src/antares_web_installer/gui/controller.py @@ -91,7 +91,7 @@ def init_log_file_handler(self): # initialize file handler logger def init_console_handler(self, callback): """ - + @param callback: @return: """ @@ -117,8 +117,8 @@ def run(self) -> None: def install(self, callback: typing.Callable): """ - Run App.install method - @param callback: function that is used to update logs + Run App.install method + @param callback: function that is used to update logs """ self.init_log_file_handler() self.logger.debug("file logger initialized.") diff --git a/src/antares_web_installer/gui/widgets/frame.py b/src/antares_web_installer/gui/widgets/frame.py index e53e239..e7234e9 100644 --- a/src/antares_web_installer/gui/widgets/frame.py +++ b/src/antares_web_installer/gui/widgets/frame.py @@ -5,6 +5,7 @@ from antares_web_installer.shortcuts import get_homedir from .button import CancelBtn, BackBtn, NextBtn, FinishBtn, InstallBtn +from ..mvc import ControllerError if TYPE_CHECKING: from antares_web_installer.gui.view import WizardView @@ -152,8 +153,12 @@ def browse(self): title="Choose the target directory", initialdir=get_homedir(), ) - self.window.set_target_dir(dir_path) - self.target_path.set(dir_path) + try: + self.window.set_target_dir(dir_path) + except ControllerError: + pass + else: + self.target_path.set(dir_path) def get_next_frame(self): # Lazy import for typing and testing purposes From 2a4232e25a1849fec021e42033425ea32a48ab6e Mon Sep 17 00:00:00 2001 From: Maurane GLAUDE Date: Wed, 11 Sep 2024 16:16:39 +0200 Subject: [PATCH 5/9] fix(app): fix check running server step, add logs and improve tests, reformat --- src/__init__.py | 0 src/antares_web_installer/app.py | 78 +++++++++++---------- tests/integration/server_mock/web.py | 1 - tests/integration/test_app.py | 100 ++++++++++++++++++++------- 4 files changed, 117 insertions(+), 62 deletions(-) create mode 100644 src/__init__.py diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 1e13bac..0d1fbdd 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -10,10 +10,11 @@ from pathlib import Path from shutil import copy2, copytree +import httpx + if os.name == "nt": from pythoncom import com_error -import httpx import psutil from antares_web_installer import logger @@ -29,6 +30,8 @@ SERVER_NAMES = {"posix": "AntaresWebServer", "nt": "AntaresWebServer.exe"} SHORTCUT_NAMES = {"posix": "AntaresWebServer.desktop", "nt": "AntaresWebServer.lnk"} +SERVER_ADDRESS = "http://127.0.0.1:8080" + class InstallError(Exception): """ @@ -46,9 +49,9 @@ class App: server_path: Path = dataclasses.field(init=False) progress: float = dataclasses.field(init=False) nb_steps: int = dataclasses.field(init=False) - completed_step: int = dataclasses.field(init=False) version: str = dataclasses.field(init=False) + def __post_init__(self): # Prepare the path to the executable which is located in the target directory server_name = SERVER_NAMES[os.name] @@ -75,10 +78,14 @@ def run(self) -> None: self.current_step += 1 if self.launch: - self.start_server() - self.current_step += 1 - self.open_browser() - self.current_step += 1 + try: + self.start_server() + except InstallError as e: + raise e + else: + self.current_step += 1 + self.open_browser() + self.current_step += 1 def update_progress(self, progress: float): self.progress = (progress / self.nb_steps) + (self.current_step / self.nb_steps) * 100 @@ -96,6 +103,9 @@ def kill_running_server(self) -> None: # evaluate matching between query process name and existing process name try: matching_ratio = SequenceMatcher(None, "antareswebserver", proc.name().lower()).ratio() + except FileNotFoundError: + logger.warning("The process '{}' does not exist anymore. Skipping its analysis".format(proc.name())) + continue except psutil.NoSuchProcess: logger.warning("The process '{}' was stopped before being analyzed. Skipping.".format(proc.name())) continue @@ -222,7 +232,7 @@ def create_shortcuts(self): desktop_path = Path(get_desktop()) logger.info("Generating server shortcut on desktop...") - name, ext = SHORTCUT_NAMES[os.name].split(".") + name, ext = SHORTCUT_NAMES[os.name].split('.') new_shortcut_name = f"{name}-{self.version}.{ext}" shortcut_path = desktop_path.joinpath(new_shortcut_name) @@ -255,60 +265,58 @@ def start_server(self): """ Launch the local server as a background task """ - logger.info("Attempt to start the newly installed server...") - args = [str(self.server_path)] + logger.info(f"Attempt to start the newly installed server located in '{self.target_dir}'...") + logger.debug(f"User permissions: {os.path.exists(self.server_path) and os.access(self.server_path, os.X_OK)}") + + args = [self.server_path] server_process = subprocess.Popen( args=args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - shell=True, cwd=self.target_dir, + shell=True, ) self.update_progress(50) if not server_process.poll(): logger.info("Server is starting up ...") else: - logger.info(f"The server unexpectedly stopped running. (code {server_process.returncode})") + stdout, stderr = server_process.communicate() + msg = f"The server unexpectedly stopped running. (code {server_process.returncode})" + logger.info(msg) + logger.info(f"Server unexpectedly stopped.\nstdout: {stdout}\nstderr: {stderr}") + raise InstallError(msg) nb_attempts = 0 - max_attempts = 5 + max_attempts = 10 while nb_attempts < max_attempts: - attempt_info = f"Attempt #{nb_attempts}: " + logger.info(f"Attempt #{nb_attempts}...") try: - res = httpx.get("http://localhost:8080/", timeout=1) - except httpx.ConnectError: - logger.info(attempt_info + "The server is not accepting request yet. Retry ...") - except httpx.ConnectTimeout: - logger.info(attempt_info + "The server cannot retrieve a response yet. Retry ...") - else: - if res.status_code: - logger.info("Server is now available.") - self.update_progress(100) - logger.debug("Update progress was called.") + res = httpx.get(SERVER_ADDRESS + "/health", timeout=1) + if res.status_code == 200: + logger.info("The server is now running.") break - finally: - nb_attempts += 1 - if nb_attempts == max_attempts: - try: - httpx.get("http://localhost:8080/", timeout=1) - except httpx.ConnectTimeout as e: - logger.error("Impossible to launch Antares Web Server after {nb_attempts} attempts.") - raise InstallError(f"Impossible to launch Antares Web Server after {nb_attempts} attempts: {e}") - time.sleep(5) + except httpx.RequestError: + time.sleep(1) + nb_attempts += 1 + else: + stdout, stderr = server_process.communicate() + msg = "The server didn't start in time" + logger.error(msg) + logger.error(f"stdout: {stdout}\nstderr: {stderr}") + raise InstallError(msg) def open_browser(self): """ Open server URL in default user's browser """ logger.debug("In open browser method.") - url = "http://localhost:8080/" try: - webbrowser.open(url=url, new=2) + webbrowser.open(url=SERVER_ADDRESS, new=2) except webbrowser.Error as e: - raise InstallError(f"Could not open browser at '{url}': {e}") from e + raise InstallError(f"Could not open browser at '{SERVER_ADDRESS}': {e}") from e else: logger.info("Browser was successfully opened.") self.update_progress(100) diff --git a/tests/integration/server_mock/web.py b/tests/integration/server_mock/web.py index b484601..d2118b2 100644 --- a/tests/integration/server_mock/web.py +++ b/tests/integration/server_mock/web.py @@ -26,7 +26,6 @@ async def lifespan(_unused_app: FastAPI) -> t.AsyncGenerator[None, None]: asyncio.create_task(stop_server()) yield - app = FastAPI(lifespan=lifespan) diff --git a/tests/integration/test_app.py b/tests/integration/test_app.py index 6d4c184..18ca6bf 100644 --- a/tests/integration/test_app.py +++ b/tests/integration/test_app.py @@ -1,20 +1,23 @@ import os import shutil +import time + +import psutil +import pytest +import re + from difflib import SequenceMatcher from pathlib import Path from typing import Any -import psutil -import pytest from _pytest.monkeypatch import MonkeyPatch -import re -from antares_web_installer.app import App +from antares_web_installer.app import App, InstallError from tests.samples import SAMPLES_DIR DOWNLOAD_FOLDER = "Download" DESKTOP_FOLDER = "Desktop" -PROGRAM_FOLDER = "Program Files" +PROGRAM_FOLDER = "ProgramFiles" @pytest.fixture(name="downloaded_dir") @@ -51,17 +54,24 @@ def program_dir_fixture(tmp_path: Path) -> Path: @pytest.fixture() def settings(desktop_dir: Path, monkeypatch: MonkeyPatch): + print("Set up data ...") # Patch the `get_desktop` function according to the current platform platform = {"nt": "_win32_shell", "posix": "_linux_shell"}[os.name] monkeypatch.setattr(f"antares_web_installer.shortcuts.{platform}.get_desktop", lambda: desktop_dir) + print("Data was set up successfully") yield # kill the running servers + print("Starting killing servers.") for proc in psutil.process_iter(): - matching_ratio = SequenceMatcher(None, "antareswebserver", proc.name().lower()).ratio() + try: + matching_ratio = SequenceMatcher(None, "antareswebserver", proc.name().lower()).ratio() + except psutil.NoSuchProcess: + continue if matching_ratio > 0.8: proc.kill() proc.wait(1) break + print("Severs were successfully killed.") class TestApp: @@ -69,6 +79,23 @@ class TestApp: Integration tests for the app """ + @staticmethod + def count_shortcut_file(dir_path: Path) -> int: + match = 0 + for file in list(dir_path.iterdir()): + if os.name == "nt": + pattern = re.compile(r"AntaresWebServer-([0-9]*\.){3}lnk") + if pattern.fullmatch(file.name): + match += 1 + else: + pattern = re.compile(r"AntaresWebServer-([0-9]*\.){3}desktop") + if pattern.fullmatch(file.name): + match += 1 + return match + + def kill_running_server(self): + pass + def test_run__empty_target(self, downloaded_dir: Path, program_dir: Path, settings: Any) -> None: """ The goal of this test is to verify the behavior of the application when: @@ -77,35 +104,50 @@ def test_run__empty_target(self, downloaded_dir: Path, program_dir: Path, settin The test must verify that: - Files are correctly copied to the target directory - - Shortcuts are correctly created on the desktop - The server is correctly started """ - # For each application versions, check if everything is working - for application_dir in downloaded_dir.iterdir(): + for source_dir in downloaded_dir.iterdir(): # Run the application - app = App(source_dir=application_dir, target_dir=program_dir, shortcut=True, launch=True) - app.run() + app = App(source_dir=source_dir, target_dir=program_dir, shortcut=False, launch=True) + try: + app.run() + except InstallError: + print("Server execution problem") + raise + + # check if application was successfully installed in the target dir (program_dir) + assert program_dir.is_dir() + assert program_dir.iterdir() + + # check if all files are identical in both source_dir (application_dir) and target_dir (program_dir) + program_dir_content = list(program_dir.iterdir()) + source_dir_content = list(source_dir.iterdir()) + assert len(source_dir_content) == len(program_dir_content) + for index, file in enumerate(source_dir.iterdir()): + assert file.name == program_dir_content[index].name + + # give some time for the server to shut down + time.sleep(2) + + # remove all files before installing the other versions + for file in program_dir.iterdir(): + if file.is_dir(): + shutil.rmtree(file) + else: + os.remove(file) + program_dir_content = list(program_dir.iterdir()) + assert len(program_dir_content) == 0 def test_shortcut__created(self, downloaded_dir: Path, program_dir: Path, desktop_dir: Path, settings: Any): for application_dir in downloaded_dir.iterdir(): # Run the application - app = App(source_dir=application_dir, target_dir=program_dir, shortcut=True, launch=True) + # Deactivate launch option in order to improve tests speed + app = App(source_dir=application_dir, target_dir=program_dir, shortcut=True, launch=False) app.run() - - match = 0 - - for file in list(desktop_dir.iterdir()): - if os.name == "nt": - pattern = re.compile(r"AntaresWebServer-([0-9]*\.){3}lnk") - if pattern.fullmatch(file.name): - match += 1 - else: - pattern = re.compile(r"AntaresWebServer-([0-9]*\.){3}desktop") - if pattern.fullmatch(file.name): - match += 1 + match = self.count_shortcut_file(desktop_dir) assert match == 1 - def test_shortcut__not_created(self): + def test_shortcut__not_created(self, downloaded_dir: Path, program_dir: Path, desktop_dir: Path, settings: Any): """ Test if a shortcut was created on the desktop @param downloaded_dir: @@ -113,4 +155,10 @@ def test_shortcut__not_created(self): @param program_dir: @return: """ - pass + for application_dir in downloaded_dir.iterdir(): + # Run the application + # Deactivate launch option in order to improve tests speed + app = App(source_dir=application_dir, target_dir=program_dir, shortcut=False, launch=False) + app.run() + match = self.count_shortcut_file(desktop_dir) + assert match == 0 From f368f42d0e2c7004a067ae174f060a98be7867fe Mon Sep 17 00:00:00 2001 From: Maurane GLAUDE Date: Wed, 11 Sep 2024 16:44:58 +0200 Subject: [PATCH 6/9] fix(test): reformat code --- src/antares_web_installer/app.py | 3 +-- tests/integration/server_mock/web.py | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/antares_web_installer/app.py b/src/antares_web_installer/app.py index 0d1fbdd..ac98895 100644 --- a/src/antares_web_installer/app.py +++ b/src/antares_web_installer/app.py @@ -51,7 +51,6 @@ class App: nb_steps: int = dataclasses.field(init=False) version: str = dataclasses.field(init=False) - def __post_init__(self): # Prepare the path to the executable which is located in the target directory server_name = SERVER_NAMES[os.name] @@ -232,7 +231,7 @@ def create_shortcuts(self): desktop_path = Path(get_desktop()) logger.info("Generating server shortcut on desktop...") - name, ext = SHORTCUT_NAMES[os.name].split('.') + name, ext = SHORTCUT_NAMES[os.name].split(".") new_shortcut_name = f"{name}-{self.version}.{ext}" shortcut_path = desktop_path.joinpath(new_shortcut_name) diff --git a/tests/integration/server_mock/web.py b/tests/integration/server_mock/web.py index d2118b2..b484601 100644 --- a/tests/integration/server_mock/web.py +++ b/tests/integration/server_mock/web.py @@ -26,6 +26,7 @@ async def lifespan(_unused_app: FastAPI) -> t.AsyncGenerator[None, None]: asyncio.create_task(stop_server()) yield + app = FastAPI(lifespan=lifespan) From 6e42b8ca806b37a643e2f17807628550c4ae6c4b Mon Sep 17 00:00:00 2001 From: Maurane GLAUDE Date: Wed, 11 Sep 2024 16:51:02 +0200 Subject: [PATCH 7/9] fix(test): delete `__init__.py` file because it is not needed --- src/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/__init__.py diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index e69de29..0000000 From 176dfd3431c10e4aa380f37c8b876b57c6d272f8 Mon Sep 17 00:00:00 2001 From: Maurane GLAUDE Date: Wed, 11 Sep 2024 17:49:31 +0200 Subject: [PATCH 8/9] fix(gui.windows): improve test by isolating application repertories --- tests/integration/test_app.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/tests/integration/test_app.py b/tests/integration/test_app.py index 18ca6bf..8961733 100644 --- a/tests/integration/test_app.py +++ b/tests/integration/test_app.py @@ -108,7 +108,14 @@ def test_run__empty_target(self, downloaded_dir: Path, program_dir: Path, settin """ for source_dir in downloaded_dir.iterdir(): # Run the application - app = App(source_dir=source_dir, target_dir=program_dir, shortcut=False, launch=True) + # Make sure each application is installed in new directory + custom_dir = program_dir.joinpath(source_dir.name) + app = App( + source_dir=source_dir, + target_dir=custom_dir, + shortcut=False, + launch=True + ) try: app.run() except InstallError: @@ -116,11 +123,11 @@ def test_run__empty_target(self, downloaded_dir: Path, program_dir: Path, settin raise # check if application was successfully installed in the target dir (program_dir) - assert program_dir.is_dir() - assert program_dir.iterdir() + assert custom_dir.is_dir() + assert custom_dir.iterdir() # check if all files are identical in both source_dir (application_dir) and target_dir (program_dir) - program_dir_content = list(program_dir.iterdir()) + program_dir_content = list(custom_dir.iterdir()) source_dir_content = list(source_dir.iterdir()) assert len(source_dir_content) == len(program_dir_content) for index, file in enumerate(source_dir.iterdir()): @@ -129,15 +136,6 @@ def test_run__empty_target(self, downloaded_dir: Path, program_dir: Path, settin # give some time for the server to shut down time.sleep(2) - # remove all files before installing the other versions - for file in program_dir.iterdir(): - if file.is_dir(): - shutil.rmtree(file) - else: - os.remove(file) - program_dir_content = list(program_dir.iterdir()) - assert len(program_dir_content) == 0 - def test_shortcut__created(self, downloaded_dir: Path, program_dir: Path, desktop_dir: Path, settings: Any): for application_dir in downloaded_dir.iterdir(): # Run the application From 9dd855790cd7c33db3a1736d5f6d6378ceaeb24a Mon Sep 17 00:00:00 2001 From: Maurane GLAUDE Date: Thu, 12 Sep 2024 09:17:28 +0200 Subject: [PATCH 9/9] fix(tests.integration): reformat code with ruff --- tests/integration/test_app.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/integration/test_app.py b/tests/integration/test_app.py index 8961733..b678ec1 100644 --- a/tests/integration/test_app.py +++ b/tests/integration/test_app.py @@ -110,12 +110,7 @@ def test_run__empty_target(self, downloaded_dir: Path, program_dir: Path, settin # Run the application # Make sure each application is installed in new directory custom_dir = program_dir.joinpath(source_dir.name) - app = App( - source_dir=source_dir, - target_dir=custom_dir, - shortcut=False, - launch=True - ) + app = App(source_dir=source_dir, target_dir=custom_dir, shortcut=False, launch=True) try: app.run() except InstallError: